漏洞公告在http://www.sektioneins.de/advisories/SE-2008-03.txt
PHP 5 <= 5.2.5
PHP 4 <= 4.4.8
一些允许如GBK,EUC-KR, SJIS等宽字节字符集的系统都可能受此影响,影响还是非常大的,国内的虚拟主机应该是通杀的,在测试完这个漏洞之后,发现还是十分有意思的,以前也有过对这种类型安全漏洞的研究,于是就把相关的漏洞解释和一些自己的想法都写出来,也希望国内的一些有漏洞的平台能迅速做出响应,修补漏洞。
这个漏洞出在php的用来转义命令行字符串的函数上,这些函数底层是用的php_escape_shell_cmd这个函数的,我们先来看看他的处理过程:
| /* {{{ php_escape_shell_cmd Escape all chars that could possibly be used to break out of a shell command This function emalloc's a string and returns the pointer. Remember to efree it when done with it. *NOT* safe for binary strings */ char *php_escape_shell_cmd(char *str) { register int x, y, l; char *cmd; char *p = NULL; l = strlen(str); cmd = safe_emalloc(2, l, 1); for (x = 0, y = 0; x < l; x++) { switch (str[x]) { case '"': case '\'': #ifndef PHP_WIN32 if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) { /* noop */ } else if (p && *p == str[x]) { p = NULL; } else { cmd[y++] = '\\'; } cmd[y++] = str[x]; break; #endif case '#': /* This is character-set independent */ case '&': case ';': case '`': case '|': case '*': case '?': case '~': case '<': case '>': case '^': case '(': case ')': case '[': case ']': case '{': case '}': case '$': case '\\': case '\x0A': /* excluding these two */ case '\xFF': #ifdef PHP_WIN32 /* since Windows does not allow us to escape these chars, just remove them */ case '%': cmd[y++] = ' '; break; #endif cmd[y++] = '\\'; /* fall-through */ default: cmd[y++] = str[x]; } } cmd[y] = '\0'; return cmd; } /* }}} */ |
可以看到,php通过将",',#,&,;.....等等在shell命令行里有特殊意义的字符都通过在前面加上\变成\".\',\#,\&,\;......来进行转义,使得用户的输入被过滤,来避免产生command injection漏洞。在php看来,只要过滤了这些字符,送入到system等函数中时,参数就会是安全的,php手册中给出的利用例子如下:
| <?php $e = escapeshellcmd($userinput); // here we don't care if $e has spaces system("echo $e"); $f = escapeshellcmd($filename); // and here we do, so we use quotes system("touch \"/tmp/$f\"; ls -l \"/tmp/$f""); ?> |

