关于读取popen输出结果时未截断字符串导致的命令行注入详解

2020-01-06 18:41:28于海丽

0x00 前言

这种命令行注入在pwn中出现的比较少,所以记录分享一下。

0x01 命令行注入介绍

熟悉web安全的话就知道,如果对特殊字符过滤不当,会引发sql注入或者xss等安全漏洞。其中,命令行注入较为严重,因为可以直接拿到漏洞程序当前权限的OSshell。

然而,命令行注入不仅在web中会出现,在C语言程序中,也会出现命令行注入的漏洞。比方说这道pwn题,就是调用system时,没有对输入数据进行截断以及对特殊字符处理不当而导致的。

命令行注入相对于其他二进制漏洞相比利用比较简单,比方说这道题,举个例子:


sprintf(&s, "du -sh lib/'%s'", v6);
system(&s);

其中设计初衷,v6应当是一个合法的文件名。但是如果攻击者恶意操控v6,比方说,让v6为:'&&/bin/sh'
进行sprintf拼接后,system所执行的命令为:


du -sh lib/''&&/bin/sh''

这里有两个linux命令行的知识:

&&,这是拼接两个命令,如果我们执行 command1&&command2,那么等价于先执行command1在执行command2。其中命令跟&&之间不必加空格。

在命令后不加空格的''(两个单引号)会被忽略,比如ls''等价于ls,/bin/sh''等价于/bin/sh,du -sh lib/''等价于du -sh lib/(即,实际传进去的参数是lib/不是lib/'')

所以,执行上面的命令,相当于先执行了


du -sh lib/

再执行


/bin/sh

所以,可以getshell。

0x02 题目

题目所给的是一个library的服务,可以上传book,查看books,清除books。其中,book存放在lib/文件夹中。

0x03 漏洞点


char *list_books()
{
 FILE *v0; // eax
 char *result; // eax
 char s; // [esp+4h] [ebp-C14h]
 char ptr; // [esp+804h] [ebp-414h]
 char *v4; // [esp+C04h] [ebp-14h]
 FILE *stream; // [esp+C08h] [ebp-10h]
 char *v6; // [esp+C0Ch] [ebp-Ch]
 v0 = popen("ls lib/", "r");
 stream = v0;
 result = (char *)fread(&ptr, 1u, 0x400u, v0);
 v4 = result;
 if ( result )
 {
 v6 = strtok(&ptr, delims);
 result = (char *)send("Book list:nSizetE-bookn");
 while ( v6 )
 {
 sprintf(&s, "du -sh lib/'%s'", v6);
 //很明显,这里存在可能的命令行注入
 system(&s);
 fflush(stdout);
 result = strtok(0, delims);
 v6 = result;
 }
 }
 return result;

其中list_books代码如上,v6来自fread从popen中的返回结果。他本来想做的是输出每个文件的大小,但是fread后没有用截断。所以调用strtok时,可能会读到fread后面的垃圾数据(当然如果可以操控的话就不是垃圾数据了)