Sunday, March 13, 2016

0CTF 2016 Write Up: Monkey (Web 4)

The Chinese 0CTF took place on March 12-13 and it was yet another fun CTF. I played with my teammates from TheGoonies and we were ranked #48.

I found the Web task "Monkey" particularly interesting: I solved it with the help from my friend @danilonc, but it took way longer than it should because of some **Spoiler Alert** DNS glitches. According to the scoreboard status, approximately 35 teams were able to solve it.

Task: Monkey (Web - 4pts)

What is Same Origin Policy?

you can test this problem on your local machine

The running application receives a Proof-of-Work string and an arbitrary URL, instructing a "monkey" to browse the inputted URL for 2 minutes.


Solving the proof-of-work is pretty straightforward. We had to generate random strings and compare the first 6 chars from its MD5 against the challenge. The POW challenge was more cpu-intensive than normal, so the traditional bash/python one-liner ctf scripts would require some performance improvements.

@danilonc had written a quick hack using Go to bruteforce and solve POW from older CTF challs, so we just slightly modified it:

Solving the Proof-of-Work:
Same-Origin-Policy and CORS

The Same-Origin-Policy (SOP) deems pages having the same URI scheme, hostname and port as residing at the same-origin. If any of these three attributes varies, the resource is in a different origin. Hence, if provided resources come from the same hostname, scheme and port, they can interact without restriction.

If you try to use an XMLHttpRequest to send a request to a different origin, you can’t read the response. However, the request will still arrive at its destination. This policy prevents a malicious script on one page from obtaining access to sensitive data (both the header and the body) on another web page, on a different origin.

For this particular CTF challenge, if the secret internal webpage had had an insecure CORS header like "Access-Control-Allow-Origin: *", we would be able to retrieve its data with no effort. This, of course, was not the case.

Bypassing the Same-Origin

The flag was accessible on an internal webserver hosted at The first thing we did was hooking the monkey's browser using BeEF, so we could fingerprint his device, platform, plugins and components.

There was nothing interesting here, a custom user-agent and no known vulnerable component. We enumerated the chars accepted by the server with the following script:

Unfortunately, the server was rejecting special chars like spaces (%20 and +) and there was no command injection signal. Our evil plan to input --disable-web-security $URL to disable Chrome's SOP didn't work so we had to find new ways to retrieve the secrets.

We also thought about using data:uri and file schemes to load a malicious script/webpage, but it wouldn't help us to bypass the SOP. We tried to input URL's like <html><script/**/src=''></script></html> and file:///proc/self/environ (setting custom headers with a malicious HTML), but that is also known not to work on modern browsers.

DNS Rebinding

After some discussion, we came to the conclusion that we needed to perform a DNS Rebinding attack. devttys0 presented about this class of vulnerabilities at DEFCON 18 and @mikispag recently wrote a detailed post describing how to use DNS rebinding to steal WiFi passwords.

DNS rebinding is a technique that can be used to perform a breach of same-origin restrictions, enabling a malicious website to interact with a different domain. The possibility of this attack arises because the segregations in the SOP are based primarily on domain name and port, whereas the ultimate delivery of HTTP requests involves converting domain names into IP addresses.

We had some issues at first because we tried to use the free DNS service from DuckDNS and it was very glitchy. For some obscure reason, we were unable to hook the user's browser when using the service.

In order to make our life miserable, the challenge monkey would browse the site for two minutes only: we also could't use the DNS services from Namecheap because the minimum TTL time is 60 seconds.

Attack Phase

After deciding to set up the DNS server on our own, we came with the following attack scenario:

1) User visits the beef hook page at (IP

2) Webpage will load BeEF javascript hook and his browser will become a zombie.

3) We perform a DNS Rebind to change the A Record from to @danilonc set the BIND Zone file with a low TTL (1 sec) and replaced the answer (lines 14-15) as soon as the browser got hooked.

4) Perform a CORS request using BeeF's "Test CORS Request" module.

Here's a small diagram of the attack:

After a couple of tries we finally managed to get the flag:

Flag: 0ctf{monkey_likes_banananananananaaaa}

Thursday, November 19, 2015

ARRIS Cable Modem has a Backdoor in the Backdoor

A couple of months ago, some friends invited me to give a talk at NullByte Security Conference. I started to study about some embedded device junk hacking hot topics and decided to talk about cable modem security. Braden Thomas keynoted at Infiltrate 2015 discussing about Practical Attacks on DOCSIS so, yeah, cable modem hacking is still mainstream.

On November 21st I'll be at Salvador speaking on "Hacking cable modems: The Later Years". It's not a talk about theft of service and getting free Internet access. I'll focus on the security of the cable modems, the technology used to manage them, how the data is protected and how the ISPs upgrade the firmwares. Spoiler Alert: everything's really really bad.

Securing cable modems is more difficult than other embedded devices because, on most cases, you can’t choose your own device/firmware and software updates are almost entirely controlled by your ISP.

While researching on the subject, I found a previously undisclosed backdoor on ARRIS cable modems, affecting many of their devices including TG862A, TG862G, DG860A. As of this writing, Shodan searches indicate that the backdoor affects over 600.000 externally accessible hosts and the vendor did not state whether it's going to fix it yet.

ARRIS Backdoors

ARRIS SOHO-grade cable modems contain an undocumented library ( that acts as a backdoor, allowing privileged logins using a custom password.

The following files load the backdoor library on ARRIS TG862A Firmware TS0705125D_031115_MODEL_862_GW (released on 2015):


ARRIS password of the day is a remote backdoor known since 2009. It uses a DES encoded seed (set by the ISP using the arrisCmDoc30AccessClientSeed MIB) to generate a daily backdoor password. The default seed is MPSJKMDHAI and guess what - many ISPs won't bother changing it at all.

The backdoor account can be used to enable Telnet and SSH remotely via the hidden HTTP Administrative interface "" or via custom SNMP MIBs.

The default password for the SSH user 'root' is 'arris'. When you access the telnet session or authenticate over SSH, the system spawns the 'mini_cli' shell asking for the backdoor password.

When you log using the password of the day, you are redirected to a restricted technician shell ('/usr/sbin/cli')

Restricted shells are ;restricted

In order to understand how the backdoor works, I built an Puma5 toolchain (ARMEB) and cross compiled some useful tools like strace, tcpdump and gdbserver. I hosted them on my Github, get them here:

While analyzing the backdoor library and the restricted shells, I found an interesting code on the authentication check:

Yes, they put a backdoor in the backdoor (Joel from Dlink is sure to be envy). The undocumented backdoor password is based on the last five digits from the modem's serial number. You get a full busybox shell when you log on the Telnet/SSH session using these passwords.

The vendor asked not to disclose details about the password generation algorithm. I'm really relieved knowing that those awful guys from Metasploit won't be able to reverse this in a timely manner.

Vulnerability, Disclosure and Marketing

Of course, we need a logo so the media can report about this with fancy graphs as well as vendors could distribute customized t-shits at Blackhat.

What I like most about lcamtuf is how visionary he is. While people were still writing dumb fuzzers, he wrote AFL performed a detailed Technical analysis of Qualys' GHOST. Based on his analysis, I hired a couple of marketing specialists to find out the best way to disclose the ARRIS backdoor.

What do we have here?

- Multiple backdoors allowing full remote access to ARRIS Cable modems
- An access key that is generated based on the Cable modem's serial number

After a thoughtful analysis, the marketing committee advised w00tsec members to write a Keygen. In order to write a Keygen, we need a leet ascii art and a cool chiptune. The chosen font was ROYAFNT1.TDF, from the legendary artist Roy/SAC and the chiptune is Toilet Story 5, by Ghidorah.

Here's the POC (make sure you turn the sound on):


I reported these flaws to CERT/CC on 2015-09-13 but we didn't receive much feedback from the vendor. CERT/CC was very helpful and responsive (10/10 would disclose again!). I was asked not to release the POCs immediately so I'm going to wait for the vendor to "fix" the issue.

CERT/CC set a disclosure policy of 45 days long ago. They waited for more than 65 days for them to "fix" it but ARRIS didn't remove the backdoors in a timely manner. Someone needs to update the Responsible Disclosure RFC and include a note describing that vendors shall lose disclosure points whenever they plant a backdoor on the device (ARRIS modems have a third backdoor too, check the ConsoleCowboys Blog).

I'm pretty sure bad guys had been exploiting flaws on these devices for some time (just search for ARRIS DNS on Twitter, for example). We need more people bypassing EULAs and reversing end-user software and firmware. If you haven't heard about the Firmware.RE, check them right now. A broader view on firmwares is not only beneficial, but necessary to discover new vulnerabilities and backdoors, correlating different device families and showing how vulnerabilities reappear across different products.

To all the vendors out there, I would like to finish this post by quoting @daveitel:

Thursday, October 22, 2015 2015 CTF Write Up: Dr. Bob (Forensic 150) 2015 CTF was organised by fluxfingers during October 20-22. It's one of the coolest CTFs around, the only drawback is that it runs during week days (hey guys patch this for the next years). My team TheGoonies ranked #59th, which is not bad considering we only played part-time.

The task Dr. Bob was the one I found most interesting as it included disk forensics, memory forensics and basic crypto tasks.

Task: Dr. Bob (Forensic 150)

There are elections at the moment for the representative of the students and the winner will be announced tomorrow by the head of elections Dr. Bob. The local schoolyard gang is gambling on the winner and you could really use that extra cash. Luckily, you are able to hack into the mainframe of the school and get a copy of the virtual machine that is used by Dr. Bob to store the results. The desired information is in the file /home/bob/flag.txt, easy as that.

The file provided is a VirtualBox image in a saved state. According to the challenge instructions, we have to retrieve the flag from the user home folder. The VM starts on a login terminal of what seems to be a Linux distro.

The easiest route here is to convert the VDI image to raw, mount and extract the key from the home folder. VirtualBox has a builtin tool to convert VDI to raw and it's as simple as:

C:\Program Files\Oracle\VirtualBox\VBoxManage.exe internalcommands converttoraw c:\ctf\home\dr_bob\.VirtualBox\Safe\Safe.vdi c:\ctf\safe.dd

Let's identify the raw image and mount it externally:
sudo fdisk -lu safe.dd

sudo losetup -o 1048576 /dev/loop0 safe.dd
sudo lvmdiskscan

There are two interesting devices: /dev/vg/root and /dev/vg/home, let's 1 - mount the home folder, 2 - grab the flag and 3 - PROFIT!!!

Oh noes, the disk is encrypted... I couldn't find any useful data on the root device (/dev/vg/root). I tried to crack some local password hashes but I didn't get anything and logs/history files didn't reveal any secrets. Time to unleash some CSI skills and perform live memory forensics.

Memory Forensics: Rekall

Unlike VMWare virtual machines, VirtualBox does not offer an easy-to-use memory dump (as far as I know). What do we do now? It's time to perform VM introspection with Rekall.

Memory Analysis Inception
Rekall is the first memory framework to support transparent introspection of VMs with any host-guest OS combination and is independent of the virtualization software layer.

Building the Profile

Linux support in Rekall requires a tailoured profile to the running kernel as well as the System map file. The profile file contains all the debugging symbols extracted into a Rekall standard profile format. To generate this file, it is necessary to build a kernel module with debugging symbols enabled, and then parse the DWARF debugging symbols.

The operating system is a Debian 7.9 i686, with 3.2.0-4-486 Kernel.

The Linux Guide from rekall repository is pretty straightforward. I downloaded a Debian 7.9 i386 ISO, installed it on a clean system, installed the Kernel headers from the target VM and built the corresponding profiles. I mirrored them here:

Memory Analysis Inception

Now that we have the proper profile, we can run VirtualBox, start the VM and perform live forensics on the guest machine.

The vmscan plugin scans the physical memory attempting to find hypervisors and group them together logically as virtual machines.

It's possible to run plugins on any VM by using the --ept (Extended Page Tables) parameter on the command line. To run a rekall plugin on a VM that vmscan found, invoke rekall as you normally would, but add --ept EPT_VALUE as a parameter.

rekal -f \\.\pmem vmscan --live
rekal.exe -f \\.\pmem --profile --ept 0x1ECC0701E

I tried to use the base Plugins that supports Linux analysis, but none of them revealed the secrets necessary to decrypt the disk.

After some time I decided to take a different approach and dump the full memory from the Guest VM and carve for some secrets.

imagecopy output_image='memdump.raw'

Extracting AES Keys from the Memory Dump

You can use tools like bulk_extractor and findaes to extract AES keys from memory dumps. These programs work by carving the images and eliminating anything which is not a valid AES key schedule.

./findaes memdump.raw

The tools found an AES-128 key, and I now needed to recreate this behavior on a lab to make sure that it was the encryption master-key. I set up an encrypted volume on a Debian installation and dumped the master keys using cryptsetup:

cryptsetup luksDump --dump-master-key /dev/sda5

After that, I dumped the operating system memory and used bulk_extractor to search for AES Keys:

bulk_extractor memdump.raw

The AES256 key matches with the MK dump, what brings us to the final step.

Decrypting LUKS volume using the Master Key

Now that we have the AES Key, all we need to do is follow this guide - Cryptsetup and the master key - and decrypt '/dev/vg/home'. There's no command-line to decrypt the disk using the master-key, everything is kind of hackish (you need to corrupt the headers and create a new one using the key).

sudo losetup -o 1048576 /dev/loop1 safe.dd
cryptsetup -v luksDump /dev/vg/home

The Master Key (MK) has 128 bits, which is a good sign. The payload offset is 2048 and we need to do some basic math here to get the LUKS header size: 2048 * 512 / 1024 = 1024 (fdisk -l shows that the cluster size is 512 bytes).

We now proceed to write a new LUKS header on the device using the extracted MK, assigning a new passphrase:

dd if=/dev/vg/home of=test.img
hexdump -C -n 80 test.img
dd if=/dev/zero of=test.img conv=notrunc bs=1024 count=1
hexdump -C -v -n 80 test.img
echo 1fab015c1e3df9eac8728f65d3d16646 | xxd -r -p > key.bin

cryptsetup luksFormat --verify-passphrase --cipher=aes-ecb --hash=sha1 --key-size=128 --master-key-file=key.bin test.img

They tried to hide the flag from "/bin/cat" using the carriage return char (0x0D), but hexdump and Pluma had no problems displaying it:



Flag: flag{v0t3_f0r_p3dr0}

Update 1: @rbaranyi and David Berard pointed out that replacing '/etc/shadow', login with the known password and then use 'strings /dev/lvm' would be easier. That's true, but that wouldn't involve any kind of memory inception.

Update 2: David Berard pointed out that newer 'cryptsetup' offers an option to set a new passphrase using the master key: 'cryptsetup luksAddKey --master-key-file=<master-key-file> <luks device>'

Update 3: According to the writeup from CLGT, you can also dump  VirtualBox RAM using this administrative command: 'VBoxManage debugvm SafeClone dumpvmcore --filename=getthekey'

Update 4: Some teams used the dm_dump volatility plugin: it identifies disks on the target system which were mounted using the device-mapper framework. The output of this plugin gives you the arguments to pass to the dmsetup command to remount the original unencrypted file system on a different machine.

Wednesday, October 7, 2015

Mac OS X 10.11 Partial Lock Screen Bypass

Lock screen bypasses are becoming mainstream. The most notable recent bypasses are the one from Ubuntu 14.04 (hold enter, lock screen crashes, computer unlocked) and the one from Android 5.x (input large strings in the password field, destabilize the lock screen, crash to the home screen).

Many respected researcher had found and published something about this class of bugs and this blog is no different: this post describes a completely useless super serious vulnerability affecting Mac OS X 10.11 and earlier.

Mac OS X 10.11 Partial Lock Screen Bypass

Mac OS X 10.11 (and probably older versions) are vulnerable to a partial lock screen bypass. This is not a *complete* lock screen bypass as you won't be able to freely interact with the Desktop (as far as I know). Here are the steps to reproduce this bug:

1 - Hit the Exposé Key (F3)

2 - Click on any window and keep holding it

3 - Keep holding the left mouse button and lock the screen using Command + Option + Eject (hold all these keys together for some time)

That's it, now the lock screen has an "extra layer" with the miniaturised desktop windows. If you move the mouse cursor over the correct application position and hit the Space Key, a bigger window will be displayed.

You can watch Youtube videos and interact with media players (Quicktime, Spotify etc) using the media control keys. You can't interact directly with the app: if you left-click on the windows or hit Enter, the lock screen takes over that invisible layer.

Proof-of-concept - Mac OS X 10.11:

If Youtube is blocking the video in your country, watch it here:

If you are a serious tech journalist reporting about this bug feature, don't forget to say that this is specially useful to play Youtube and Spotify playlists during parties at a friend's house. You don't want to leave you Mac logged in and unattended, so you simply preload the playlist and lock the screen using this cool technique.

Bonus: Mac OS X 10.11 Hidden Window Bug

This is yet another useless totally serious bug affecting the new Mac OS X El Capitain. You can hide an application window from the user by moving them to another display and alternating the screen mirroring options. Here are the steps to reproduce this bug:

1 - Connect your monitor to an external display ("Use As Separate Display")

2 - Move the window you want to hide to the secondary display

3 - Hit the Exposé Key (F3), move the mouse cursor over the window you want to hide and hit the Space Key.

4 - Alternate the screen mirroring options by inputting Command + F1

5 - The window is gone (OMGBBQ!!!)

Proof-of-concept - Mac OS X 10.11:

I personally use this to hide all the Mac applications from coworkers who leave their computers unlocked and unattended.

Sunday, September 20, 2015

CSAW CTF 2015 Write Up: Weebdate (web500)

The anual CSAW CTF Qualification Round took place on September 18-20 and it was yet another really cool CTF. I played with my friends from TheGoonies and we ranked #128 overall (The Goonies 'R' Good Enough).

Task - Weebdate (web500)

Since the Ashley Madison hack, a lot of high profile socialites have scrambled to find the hottest new dating sites. Unfortunately for us, that means they're taking more safety measures and only using secure websites. We have some suspicions that Donald Trump is using a new dating site called "weebdate" and also selling cocaine to fund his presidential campaign. We need you to get both his password and his 2 factor TOTP key so we can break into his profile and investigate.

Flag is md5($totpkey.$password)

This is a basic Flask application running a dating site. The website has some features like most web applications we are used to: creating users, editing profiles, sending messages, searching users and exposing the whole customer data thourgh SQL Injection and LFI.


The CSP reporting URI was vulnerable to SQL injection. SQLmap had no problems finding and exploiting it.

python -u '' --cookie='session=donaldtrump010_1442717300_f65cb746b519c2b49f8e938a896e08e96f5fc533' --dbms=mysql --batch
The 'weeb' database had three tables: messages, reports and users. The 'user' table had eight columns: user_id, user_name, user_password, user_ip, user_image, user_credits,
user_register_time and user_profile.

Passwords had a SHA256 pattern so I quickly started cracking them using John The Ripper:

john --format=raw-sha256 hash.txt --wordlist=rockyou.txt

Most cracked passwords had patterns like 'testtest', 'lablab' and 'guest1guest1'. After some time I realised that the username was used as a Salt. I generated a small wordlist concatenating donaldtrump's user and password and I finally managed to crack it:

The login form displays "Invalid verification code" when you type a wrong TOTP verification code and it returns "Invalid credentials" when you mistype the password. I knew that his password was 'zebra' but I still needed to find out the TOTP algorithm in order to steal his seed.

The 'image_url' parameter from '/profile/edit' was vulnerable to LFI, displaying the full content from local files:

A curious note here is that it was the first time I managed to find a bug using Burp Collaborator. The scanner identified the external HTTP/DNS interaction and after some digging I quickly found the LFI =)
After some a lot of time bruteforcing the dirs and files, we managed to find the server root:
We are particularly interested on the generate_seed() function:



The TOTP is not stored server-side: it is generated at runtime using a seed based on the username and his registration IP Address. We had the user IP address from the SQLi dump and we can now use the get_otp_key() function to generate his TOTP key:
The flag is the md5($totpkey.$password): a8815ecd3c2b6d8e2e884e5eb6916900