通常表明,不可执行的数据段可以通过 return-to-libc 攻击绕过。这很明显,/bin/sh
但是否也可以调用远程 shell?
远程返回进入 libc 攻击
漏洞利用的通用部分通常被称为“shell 代码”,因为它们通常会这样做:启动 shell 进程并将 stdin/stdout 连接到网络套接字。
这篇论文可能很有趣:
为了演示,我们对预分叉并发服务器执行网络暴力返回到 libc 攻击,以获得对 shell 的远程访问。
当然有可能!打个电话怎么样system()
?堆栈本身可能无法执行,但它仍然包含参数,因此只要被利用的进程以必要的权限运行,任何事情都可以完成。
我想,如果我做对了,你会问:
“返回 libc 攻击与标准缓冲区溢出有什么区别,涉及调用远程 shell 的漏洞利用仍然可能吗?”
差异是微妙的。首先让我们看一下堆栈。Avid 会喜欢这段代码:
int insecure_function(char* source)
{
char buffer[200];
memcpy(buffer, source, strlen(source));
这显然容易受到缓冲区溢出的影响。此函数的堆栈应如下所示:
Low Address High Address
char buffer --------------------------------- | ret address | char* source
some data 200 sizeof(char)'s long | 0x134543344 | 0x4374234294
现在,传统的缓冲区溢出允许您这样做:
Low Address High Address
char buffer --------------------------------- | ret address | char* source
Shell code here ---------- then some padding --- 0x999999999 | 0x4374234294
/\ |
|| |
--------- < the address points to here < -------------
这是一个非常简单的例子——你覆盖返回地址以指向你的堆栈。在实践中这非常困难,因此您最终会使用相当于“瞄准正确的地方”的NOP Sled 。
当然,如果该堆栈区域是不可执行的,那么所有这些都将失败,因为处理器不会执行这些指令。优秀的!
不完全是。我们无法将自己的 shellcode 放入内存中执行,但幸运的是,代码中有很多库可以执行几乎任何系统调用。从技术上讲,我们可以完全选择我们喜欢的任何功能,但最明显的选择是libc
因为它提供了各种功能。就像打开贝壳一样。所以在这种情况下,我们要做的是提供我们自己的堆栈帧和返回地址给那个函数:
Low Address High Address
char buffer --------------------------------- | ret address | char* source
Arguments - libc uses these! | 0x011010101 | 0x4374234294
|
< off to libc we go ----------------------
当我们到达 libc 时,堆栈框架设置了函数所需的参数,所以我们可以做我们选择的函数可以做的任何事情,例如启动一个实例,/bin/sh
它的 IO 重定向到我们喜欢的任何地方。
这显然非常困难,并且取决于很多事情。缓冲区有多大?它是否被操纵后缓冲区溢出(覆盖您的参数)?您是否关心目标进程(您刚刚破坏其堆栈的进程)是否正常运行?实际问题很多,但理论上是可以做到的。