• 爱情文章
  • 亲情文章
  • 友情文章
  • 生活随笔
  • 校园文章
  • 经典文章
  • 人生哲理
  • 励志文章
  • 搞笑文章
  • 心情日记
  • 英语文章
  • 范文大全
  • 作文大全
  • 新闻阅读
  • 当前位置: 山茶花美文网 > 友情文章 > 正文

    [php,escapeshellcmd多字节编码漏洞解析及延伸] php一个汉字几个字节

    时间:2020-02-19来源:山茶花美文网 本文已影响 山茶花美文网手机站

    漏洞公告在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] = ’’;

    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"");

    ?>

    很明显,如果没有经过escapeshellcmd的处理,用户输入hello;id的话,最后system执行的会是:

    echo hello;id

    ;在shell里是分割命令的作用,这样不仅仅会echo hello,还会执行id这个命令,导致命令注入漏洞。用escapeshellcmd处理之后命令变成:

    echo hello;id

    这样执行的命令就只会是echo,其他的都变成echo的参数,很安全。

    事实上是这样么?php在处理完参数送入system之后它就什么都不管了,后面的工作实际上都是由linux来完成的,那么linux在处理这些参数的时候是怎么样的呢?linux在执行命令的时候会有一些的表示工作环境的环境变量,譬如PWD代表当前的工作环境,UID代表了你的身份,BASH代表命令解释器等等......而在linux系统执行命令的时候,还有一个非常重要的参数,LANG,这个参数决定了linux shell如何处理你的输入,这样就可以当你输入一些中文字符的时候,linux能认识他,不至于出现人与系统之间出现理解上的错误。默认情况下,linux的LANG是en_US.UTF-8,UTF-8是一个很安全的字符集,其系列中包含有对自身的校验,所以不会出现错误,会工作良好。一些系统支持多字节字符集如GBK的时候,这也正是国内的多数情况,你可以设置LANG=zh_CN.GBK,这样你的输入都会被当作GBK编码处理,而GBK是双字节的,合法的GBK编码会被认为是一个字符。

    大家可以看到,在php的处理过程中,它是单字节处理的,它只把输入当作一个字节流,而在linux设置了GBK字符集的时候,它的处理是双字节的,大家的理解很明显地不一致。我们查下GBK的字符集范围为8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,而一个非常重要的字符的编码为5c,在GBK的尾字节范围之内,这样我们考虑一个特殊的输入:

    0xbf;id

    或 0xbf’id

    经过php的escapeshellcmd单字节转码之后将会是

    0xbf5c;id

    0xbf5c’id

    注意0xbf5c是一个合法的GBK编码,那么在linux执行的时候,会认为输入是

    [0xbfbc];id

    很好,后面的id将会被执行。可以做个简单的实验,如下:

    [loveshell@Loveshell tmp]$Content$nbsp;echo 縗

    >

    ?

    [loveshell@Loveshell tmp]$Content$nbsp;set|grep -i lang

    LANG=zh_CN.GB2312

    LANGVAR=en_US.UTF-8

    [loveshell@Loveshell tmp]$Content$nbsp;export LANG=zh_CN.GBK

    [loveshell@Loveshell tmp]$Content$nbsp;echo 縗

    [loveshell@Loveshell tmp]$Content$nbsp;set|grep -i lang

    LANG=zh_CN.GBK

    LANGVAR=en_US.UTF-8

    [loveshell@Loveshell tmp]$Content$nbsp;

    其中縗的编码为0xbf5c,可以看到在不设置LANG为GBK的时候縗是一个非法的gb2312编码,所以会被认为是两个字符,所以其中含有的0x5c起作用,被认为命令没结束。然后我们设置编码为GBK,縗就会被认为是一个字符来echo了。

    那我们如何来证明php的漏洞呢,拿

    作为例子,正常情况下上面的代码工作很好,我们提交

    exp.php?c=loveshell

    • [php,escapeshellcmd多字节编码漏洞解析及延伸] php一个汉字几个字节 相关文章:
    • 爱情文章
    • 亲情文章
    • 友情文章
    • 随笔
    • 哲理
    • 励志
    • 范文大全