Author Archives: v00d00sec

Spotify Device Name and Folder Name XSS

Found some “Self-XSS” bugs on Spotify. This issue is caused by the mobile device name not being sanitized before being displayed by the WebView in the Spotify Desktop application as shown by the broken image tag. Unfortunately this bug did not qualify for bounty of any sort on Hackerone as it is considered a harmless “Self-XSS”.

The other folder name bug seems to be a duplicate that has been reported by someone else but not fixed. These bugs are considered harmless to Spotify and thus they have not been fixed.

Advertisements

Set Environment Variables in Memory (JAVA)

Potentially evil snippet of code that could help me solve a long-standing problem that I encountered in developing one simple JAVA based exploit. Posting it here for further investigation when I have the time!

protected static void setEnv(Map newenv)
{
  try
    {
        Class processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
        Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
        theEnvironmentField.setAccessible(true);
        Map env = (Map) theEnvironmentField.get(null);
        env.putAll(newenv);
        Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
        theCaseInsensitiveEnvironmentField.setAccessible(true);
        Map cienv = (Map)     theCaseInsensitiveEnvironmentField.get(null);
        cienv.putAll(newenv);
    }
    catch (NoSuchFieldException e)
    {
      try {
        Class[] classes = Collections.class.getDeclaredClasses();
        Map env = System.getenv();
        for(Class cl : classes) {
            if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
                Field field = cl.getDeclaredField("m");
                field.setAccessible(true);
                Object obj = field.get(env);
                Map map = (Map) obj;
                map.clear();
                map.putAll(newenv);
            }
        }
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    } catch (Exception e1) {
        e1.printStackTrace();
    } 
}

Virtual Wireless Access Point with VPN on DD-WRT

I have received many request for more in-depth information on the post that I had on flashing DD-WRT and setting up a virtual AP that has traffic automatically tunnelled via a VPN service such as OpenVPN. I have recently flashed an Asus RT-68U router and have recorded the exact steps taken to do so (in the likely event I end up forgetting). If you have a different router make and model, the goal would be to research how to flash DDWRT on it and then follow step 2 in the later part of this post.

Step 1 – Flashing DDWRT on Asus RT-68U:

– Asus RT-68U on stock “Merlin” firmware, proceed to clear NVRAM via telnet:
– Enable Telnet by going to Advanced Settings -> Administration -> System -> Enable Telnet
– telnet 192.168.1.1 (or whatever is your router’s IP)

Run commands:

mtd-erase2 nvram;
reboot;

– Flash asus_rt-ac68u-firmware_30709.trx (Brainslayer build)
– Reboot the router
– Navigate to Administration -> Commands tab and run:

erase nvram; reboot;

– Flash dd-wrt.v24-K3_AC_ARM_STD.bin (Kong build) via Administration -> Firmware Upgrade Tab (set to factory)
– Reboot the router

Step 2 – Setting up Virtual Wireless AP with VPN Tunneling on DD-WRT:

On page: Setup -> Basic tab:
– (Optional) Rename router to whatever you want
– Set local IP of router 192.168.1.x (or whatever class A IP address you defined)
– Subnet mask 255.255.255.0 (depends on your network)
– Gateway 192.168.1.1 (or whatever your bridged router’s IP is, if bridging to ISP’s router)
– Local DNS 8.8.8.8
– (Optional) Set start IP address from e.g. 190
– Enable DHCP server
– Set static DNS1 to 8.8.8.8 and static DNS2 to 8.8.4.4
– Enable “Use DNSMasq for DHCP”
– Enable DNSMasq for DNS
– Enable NTP server (e.g. asia.pool.ntp.org or whatever timezone you are in)

Navigate to Wireless -> Basic settings tab:
– Add a virtual AP (with AP name etc)
– Enable optimize multicast traffic option and bridged mode
– Save and reboot the router

Navigate to Setup -> Networking tab:
– Add bridges br0 and br1
– Reboot
– Assign br0 to eth1 interface prio 63
– Assign br1 to wl1.1 interface prio 63
– Save and reboot the router
– bridging table should show:

br0 no vlan1 eth1 eth2
br1 no wl1.1

Navigate to Setup -> Networking tab:
– Scroll down to the br1 interface
– Enable masquerade / NAT, make sure the other options are disabled
– Add a subnet ip address you want this bridge to have e.g. 10.13.37.1 with subnet mask 255.255.255.0
– Save and reboot the router

Navigate to Setup -> Networking tab:
– Scroll down to DHCPD
– enable DHCP0 for br1; e.g (ON, start 100, max 50, leasetime 3600)
– Save and reboot the router

Navigate to Services -> VPN tab:
– Scroll down to OpenVPN client and enable it
– Enter your OpenVPN server details (steps to setup OpenVPN server at bottom of post)
– Set tunnel device to TUN
– Set tunnel protocol to UDP
– Set encryption to Blowfish CBC
– Set hash algorithm to SHA1
– Enable user pass authentication if required and add the OpenVPN username and password
– Enable advanced options
– Set TLS ciphers to none
– Set LZO compression to yes
– Enable NAT
– Set firewall protection to disabled
– Leave IP address and subnet mask fields empty
– Set tunnel MTU setting to 1500
– Leave UDP fragment field empty
– Set UDP MSS-Fix to disabled
– Enable nsCertType vertication
– Export your openvpn.ovpn profile from your OpenVPN server (open .ovpn file in text editor. See Step 3 near the end of this post)
– Put the TLS auth key portion in the TLS Auth Key field
– Fields: add config, policy based routing, pkcs12, static key, all set to blank
– Place your CA cert in the CA Cert field
– Place your public client cert in the Public Cert field
– Place your private client key in the Private Key field
– Save and reboot the router

Navigate to Administration -> Commands tab and add the following as a startup script:

Start up script:

sleep 220; # sleep to allow enough time for NTP to update
tun_name=$(ifconfig | sed -n 's/.*\(tun[^ ]\).*/\1/p');
tun_addr=$(ifconfig $tun_name | sed -nr 's/.*P-t-P:([^ ]+) .*/\1/p');
ip rule add from 10.13.37.0/24 table 200; # IP varies on your br1 subnet
ip route add default via $tun_addr dev $tun_name table 200;
ip route flush cache;

– Reboot and make sure NTP updates the router time, if not the TLS negotiation to the OpenVPN server will fail. A workaround is to reboot the router to let NTP attempt an update again

Step 3 – Setting up OpenVPN Server on VPS (such as RamNode):

– wget http://swupdate.openvpn.org/as/openvpn-as-2.0.11-Ubuntu12.i386.deb
– dpkg -i openvpn-as-2.0.11-Ubuntu12.i386.deb
– passwd openvpn
– Login to the interface and export the .ovpn file to be used for the steps mentioned above

That’s it!

Fuzzing with AFL: mpg123

CVE-2016-1000247: Denial of service with crafted id3v2 tags in all mpg123 versions since 0.60.

mpg123_announcement

In the recent weeks, I was reading on the topic of fuzzing binaries and started experimenting as well as trying it out to find new interesting bugs. I decided to use the most user-friendly fuzzer, which is the American Fuzzy Lop (AFL). And thus, the AFL fuzzing journey began.

A close friend of mine recommended fuzzing some open source binaries as an exercise, and we chose to start with mpg123, a command line mp3 player. We managed to find a simple integer underflow denial of service bug, which happens when mpg123 attempts to parse a malformed ID3v2 tag size header. The bug report that was submitted is shown below.

Summary: Segfault (unsigned long underflow) in mpg123 when parsing malformed ID3 header size in id3.c:755:765.
Discovered by : Han Lee & Jerold Hoong

- beep.mp3 id3 header  : 4944 3303 0000 0000 0026 
- crash.mp3 id3 header : 4944 3303 0040 0000 0006

----------------------------
RUN with legit beep.mp3 file
----------------------------

Breakpoint 1, INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:755
755                     while(tagpos < length-10) /* I want to read at least a full header */
(gdb) print tagpos
$1 = 0
(gdb) print length
$2 = 38
(gdb) print length-10
$3 = 28
(gdb)

----------------------------
RUN with malformed crash.mp3
----------------------------

Breakpoint 1, INT123_parse_new_id3 (fr=fr@entry=0x7421c0, first4bytes=<optimized out>) at src/libmpg123/id3.c:755
755                     while(tagpos < length-10) /* I want to read at least a full header */
(gdb) print tagpos
$1 = 1414546737
(gdb) print length
$2 = 6
(gdb) print length-10
$3 = 18446744073709551612
(gdb) n
Breakpoint 2, INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765
765                         if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))
(gdb) n
759                         int head_part = fr->id3v2.version == 2 ? 3 : 4; /* bytes of frame title and of framesize value */
(gdb) n
765                         if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765
765                         if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))
(gdb) bt
#0  INT123_parse_new_id3 (fr=fr@entry=0x7421b0, first4bytes=<optimized out>) at src/libmpg123/id3.c:765
#1  0x0000000000448ac3 in handle_id3v2 (newhead=<optimized out>, fr=0x7421b0) at src/libmpg123/parse.c:1071
#2  wetwork (newheadp=<optimized out>, fr=<optimized out>) at src/libmpg123/parse.c:1241
#3  INT123_read_frame (fr=fr@entry=0x7421b0) at src/libmpg123/parse.c:536
#4  0x0000000000493862 in get_next_frame (mh=0x7421b0) at src/libmpg123/libmpg123.c:623
#5  mpg123_decode_frame (mh=0x7421b0, num=num@entry=0x741968 <framenum>, audio=audio@entry=0x7fffffffe2e0, bytes=bytes@entry=0x7fffffffe2e8) at src/libmpg123/libmpg123.c:859
#6  0x000000000042ecc8 in play_frame () at src/mpg123.c:763
#7  0x0000000000406735 in main (sys_argc=<optimized out>, sys_argv=<optimized out>) at src/mpg123.c:1369
(gdb)

--------
Analysis
--------

Description: Access violation on source operand
Short description: SourceAv (19/22)
Hash: 6bd52e79e6017b9e236d4d9edea21a67.d278ec4c10e616aa909c08fc399072bd
Exploitability Classification: UNKNOWN
Explanation: The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation.
Other tags: AccessViolation (21/22)

Kudos to the upstream maintainer of mpg123, Thomas Orgis, who responded very quickly and released a fix for the bug as well as a perl one-liner hotfix for older versions. The source is available for download at http://mpg123.org/download.shtml, and debian has updated the mpg123 packages as well (https://ftp-master.debian.org/new/mpg123_1.23.8-1.html).

References:

Docker is Awesome

I was playing around with Docker for the past few days and really think that it is an awesome tool. I installed Docker for Mac and created an image based on the original Kali docker base image. I no longer need to spawn a full-fledged virtualbox VM running Kali just to run tools such as msfconsole, wpscan etc.

small_v

I created a Dockerfile project to automatically provision a base image which contains the tools that I require. This file can be tweaked to add/remove tools to your liking, and it is available here: https://github.com/v00d00sec/kali-minimal-dockerfile. If you just want to pull the full image without building it from scratch via the Dockerfile, you can pull the image from: https://hub.docker.com/r/v00d00sec/kali_mini/ by issuing the following commands:

docker pull v00d00sec/kali_mini

After the base image is created, you can view it like this:
screen-shot-2016-09-13-at-3-27-44-pm

After-which, you can run the image like this:

screen-shot-2016-09-13-at-3-28-24-pm

Voila! Instant Kali shell spawned.