Windows.Generic.Internet.BlockAccess

Simply adds a new inbound or outbound firewall rule that filters traffic by allowing or blocking network packets that match the specified criteria via netsh advfirewall add rule command. Applicable in case of blocking Internet access.

HOW it does:

  • Use a configurable lookup table to generate additional entries.
    • Using nslookup command first to get IP from specific domain
  • An optional MessageBox may also be configured to alert all logged in users.
    • The message will be truncated to 256 characters.
  • After advfirewall rules application, connection back to the Velociraptor frontend is tested and the rule removed if connection unavailable.
  • To remove rule, select the RemoveRule checkbox.
  • To update rule, simply rerun the artifact.

WHY advfirewall?

  • The netsh ipsec and netsh firewall contexts are provided for backwards-compatibility with Windows 2000/XP/2003 (Now they are all EOL).
  • Netsh AdvFirewall applies to: Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Vista.
  • If you are new to advfirewall, please check reference link from MS first for more information.

NOTE: Test carefully before running at scale in production environment

Inspired by Windows.Remediation.Quarantine from Matt Green - @mgreen27 (use netsh IPsec)


name: Windows.Generic.Internet.BlockAccess
description: |
      Simply adds a new inbound or outbound firewall rule that filters traffic by allowing or blocking network packets that match the specified criteria via `netsh advfirewall add rule` command. Applicable in case of blocking Internet access.
      
      HOW it does:
      
      - Use a configurable lookup table to generate additional entries.
        - Using `nslookup` command first to get IP from specific domain
      - An optional `MessageBox` may also be configured to alert all logged in users.
        - The message will be truncated to 256 characters.
      - After advfirewall rules application, connection back to the Velociraptor
      frontend is tested and the rule removed if connection unavailable.
      - To remove rule, select the `RemoveRule` checkbox.
      - To update rule, simply rerun the artifact.
      
      WHY advfirewall?
      
      - The `netsh ipsec` and `netsh firewall` contexts are provided for backwards-compatibility with Windows 2000/XP/2003 (Now they are all **EOL**). 
      - `Netsh AdvFirewall` applies to: Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Vista.
      - If you are new to advfirewall, please check reference link from MS first for more information.
      
      NOTE: Test carefully before running at scale in production environment
      
      Inspired by `Windows.Remediation.Quarantine` from Matt Green - @mgreen27 (use netsh IPsec)

author: TueDenn - @tuedenn

reference:
  - https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/dd734783(v=ws.10)
  - https://serverfault.com/questions/851922/blocking-ip-address-with-netsh-filter
  - https://docs.velociraptor.app/artifact_references/pages/windows.remediation.quarantine/

required_permissions:
  - EXECVE

precondition: SELECT OS From info() where OS = 'windows'

parameters:
  - name: RuleName
    default: "VeloBlockAccess"
  - name: RuleLookupTable
    type: csv
    default: |
        dir,remoteip,protocol,interface,action,enable,description
        out,13.107.237.39,any,any,block,yes,block openai.com 1
        out,13.107.238.39,any,any,block,yes,block openai.com 2
        out,157.240.199.35,any,any,block,yes,block facbook.com
  - name: MessageBox
    description: |
        Optional message box notification to send to logged in users. 256
        character limit.
  - name: RemoveRule
    type: bool
    description: Tickbox to remove advfirewall rule.

sources:
    - query: |

        // If a MessageBox configured truncate to 256 character limit
        LET MessageBox <= parse_string_with_regex(
                  regex='^(?P<Message>.{0,255}).*',
                  string=MessageBox).Message

        // extract configurable policy from lookuptable
        LET configurable_rule <= SELECT
                  dir,remoteip,protocol,interface,action,enable,description
              FROM RuleLookupTable
        
        // Emit the message if no output is emitted, otherwise emit the output.
        LET combine_results(Stdout, Stderr, ReturnCode, Message) = if(
              condition=Stdout =~ "[^\\s]", then=Stdout,
              else= if(condition=Stderr =~ "[^\\s]", then=Stderr,
              else= if(condition= ReturnCode=0,
                    then=Message )))

        // Removes empty options from the command line
        LET clean_cmdline(CMD) = filter(list=CMD, regex='^(\\w+|\\w+=.+)$')

        LET delete_cmdline = clean_cmdline(
             CMD=('netsh','advfirewall','firewall','delete','rule', 'name=' + RuleName))

        LET entry_cmdline(RuleName, dir,interface,action,remoteip,protocol,enable) = clean_cmdline(
             CMD=('netsh','advfirewall','firewall','add','rule',
               format(format='name=%s', args=RuleName),
               format(format='dir=%s', args=dir),
               format(format='interface=%s', args=interface),
               format(format='action=%s', args=action),
               format(format='remoteip=%s', args=remoteip),
               format(format='protocol=%s', args=protocol),
               format(format='enable=%s', args=enable)))
        
        
        // delete old or unwanted policy
        LET delete_rule = SELECT
              timestamp(epoch=now()) as Time,
              RuleName + ' firewall rule deleted.' AS Result
          FROM execve(argv=delete_cmdline, length=10000)

        // loop over configurable_rule to create advfirewall rule
        LET create_rule = SELECT * FROM foreach(
            row=configurable_rule,
            query= {
                  SELECT
                      timestamp(epoch=now()) as Time,
                      combine_results(Stdout=Stdout, Stderr=Stderr,
                          ReturnCode=ReturnCode,
                          Message='Rule added: ' +
                                 join(array=entry_cmdline(RuleName=RuleName, 
                                                dir=dir,
                                                interface=interface,
                                                action=action,
                                                remoteip=remoteip,
                                                protocol=protocol,
                                                enable=enable), sep=" ")) AS Result
                  FROM execve(argv=entry_cmdline(RuleName=RuleName, 
                                                dir=dir,
                                                interface=interface,
                                                action=action,
                                                remoteip=remoteip,
                                                protocol=protocol,
                                                enable=enable), length=10000)
            })
        
        // Parse a URL to get domain name.
        LET get_domain(URL) = parse_string_with_regex(
             string=URL, regex='^https?://(?P<Domain>[^:/]+)').Domain

        // Parse a URL to get the port
        LET get_port(URL) = if(condition= URL=~"https://[^:]+/", then="443",
              else=if(condition= URL=~"http://[^:]+/", then="80",
              else=parse_string_with_regex(string=URL,
                  regex='^https?://[^:/]+(:(?P<Port>[0-9]*))?/').Port))

        // extract Velociraptor config to get domain and port information
        LET extracted_config <= SELECT * FROM foreach(
                  row=config.server_urls,
                  query={
                      SELECT
                          get_domain(URL=_value) AS DstAddr,
                          get_port(URL=_value) AS DstPort,
                          'VelociraptorFrontEnd' AS Description,
                          _value AS URL
                      FROM scope()
                  })
        
        // Check connection to Velociraptor frontend server
        LET test_connection = SELECT * FROM foreach(
                  row={
                      SELECT * FROM extracted_config
                      WHERE Description = 'VelociraptorFrontEnd'
                  },
                  query={
                      SELECT *
                          Url,
                          response
                      FROM
                          http_client(url='https://' + DstAddr + ':' + DstPort + '/server.pem',
                              disable_ssl_security='TRUE')
                      WHERE Response = 200
                      LIMIT 1
                  })
        
        // final check to keep or remove policy
        LET final_check = SELECT * FROM if(condition= test_connection,
                  then={
                      SELECT
                          timestamp(epoch=now()) as Time,
                          if(condition=MessageBox,
                              then= RuleName + ' connection test successful. MessageBox sent.',
                              else= RuleName + ' connection test successful.'
                              ) AS Result
                      FROM if(condition=MessageBox,
                          then= {
                              SELECT * FROM execve(argv=['msg','*',MessageBox])
                          },
                          else={
                              SELECT * FROM scope()
                          })
                  },
                  else={
                      SELECT
                          timestamp(epoch=now()) as Time,
                          RuleName + ' failed connection test. Removing advfirewall rule.' AS Result
                      FROM delete_rule
                  })

        // Execute content
        SELECT * FROM if(condition=RemoveRule,
                  then=delete_rule,
                  else={
                      SELECT * FROM chain(
                          a=delete_rule,
                          b=create_rule,
                          c=final_check)
                  })