SEEDLAB - FORMAT_STRING_SERVER 格式化字符串攻击
介绍
C语言中printf()函数的作用是根据字符串的格式输出字符串。它的第一个参数称为format string,它定义了字符串应该如何格式化。格式字符串使用由%字符标记的占位符为printf()函数的输出填充数据。格式字符串的使用不仅限于printf()函数,许多其他函数,如sprintf()、fprintf()和scanf(),也使用格式字符串。有些程序允许用户以格式字符串的形式提供全部或部分内容。如果这些内容没有被清除,恶意用户可以利用这个机会让程序运行任意代码。这样的问题称为格式字符串漏洞。
Task1:运行程序,了解程序的主要作用。
实验中给出的是一个具有格式化字符串漏洞的程序server.c:
程序执行时,会打开9090作为socket端口接收UDP包,并将其中的内容打印出来,其第29行存在格式化字符串漏洞。
运行代码:
使用SEED ubuntu虚拟机进行重叠实验,首先要关闭一些针对此攻击的防御机制来简化实验:
-
地址空间随机化(Address Space Layout Randomization):使用sudo sysctl -wkernel.randomize_va_space=0关闭ASLR。
-
StackGuard保护方案:GCC编译器实现了一个被称为“ Stack Guard”的安全机制的防御机制重叠攻击。所以在编译漏洞程序时加上-fno-stack-protector参数来关闭该机制。
-
不可执行的堆栈:Ubuntu曾经允许栈执行,但是现在程序必须声明栈是否允许执行。内核和链接器检查程序头的标志来判断是否允许栈被执行。GCC在模式情况下设置栈不可执行,因此需要在编译时加入-z execstack参数来允许栈执行。
具体步骤:
- 关闭ASLR:sudo sysctl -w kernel.randomize_va_space=0
- 编译:gcc -g -z execstack -fno-stack-protector -o server server.c
- 使用sudo su进入root用户:由于之后需要获取root shell,因此建议Task1开始,在server端使用sudo su进入root用户;否则,因为不同的uid会被分配不同的堆栈空间,在普通用户下的payload将无法在root之下被使用
- 运行程序:./server
- 与程序交互:ctrl +shift+t开启一个新终端,并输入nc -u 127.0.0.1 9090进行连接,输入交互内容,可以看到原窗口将输入的内容输出
- 关闭程序:ctrl+c退出连接