您好,登錄后才能下訂單哦!
escapeshellcmd()對shell元字符過濾加反斜杠;
反斜線(\)會在以下字符之前插入: #&;`|*?~<>^()[]{}$, \x0A 和 \xFF,但在php5.2.5及之前存在通過輸入多字節(jié)繞過escapeshellcmd的問題。5.2.6 已經(jīng)修復(fù)了該問題。
執(zhí)行 escapeshellcmd("echo ".chr(0xc0).";id");
加上反斜杠之后,也就是echo \xc0\x5c;id,在中文環(huán)境中\(zhòng)xc0\x5c是會被認(rèn)為是gbk字符的。
>>> hex(ord('\\'))
'0x5c'
>>> s='\xc0\x5c'
>>> print s.decode('gbk').encode('utf8')
繺
>>> s.decode('gbk').encode('utf8')
'\xe7\xb9\xba'
\被吃掉之后于是就變成了echo 繺;id 了。
gbk是寬字節(jié),兩個(gè)字節(jié),gbk字符范圍:8140-FEFE,首字節(jié)在81-FE直接,尾字節(jié)在40-FE之間,顯然5C在尾字節(jié)中??紤]0xbf;id,escape之后就變成了0xbf5c;id,0xbf5c是一個(gè)合法的GBK編碼,那就變成了[0xbf5c];id了。而utf8表示中文一般三個(gè)字節(jié)。
同樣受影響的還有escapeshellarg(),源碼中的處理是一個(gè)字節(jié)一個(gè)字節(jié)來處理的。這種漏洞應(yīng)該有一定普遍性,在當(dāng)時(shí)來說。下面我們看下修復(fù)的源代碼:
char *php_escape_shell_cmd(char *str) {
register int x, y, l;
char *cmd;
char *p = NULL;
TSRMLS_FETCH();
l = strlen(str);
cmd = safe_emalloc(2, l, 1); //申請了2倍字符
for (x = 0, y = 0; x < l; x++) {
int mb_len = php_mblen(str + x, (l - x));
//這一段是5.2.6新加的,就是在處理多字節(jié)符號的時(shí)候,當(dāng)多字節(jié)字符小于0的時(shí)候不處理,大于1的時(shí)候跳過,等于1的時(shí)候執(zhí)行過濾動作
/* skip non-valid multibyte characters */
if (mb_len < 0) {
continue;
} else if (mb_len > 1) {
memcpy(cmd + y, str + x, mb_len);
y += mb_len;
x += mb_len - 1;
continue;
}
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;
}
這個(gè)bypass已經(jīng)成為過去時(shí)了,但是還是有很大的借鑒意義,就是寬字節(jié)注入,這種情況不僅僅發(fā)生命令注入時(shí),更多的時(shí)候在sql注入,下面來分析一下寬字節(jié)注入如下三種情況,都是由于寬字節(jié)的問題導(dǎo)致的。
1,一種情況 iconv轉(zhuǎn)換,addslashes之后從gbk轉(zhuǎn)到utf8
$user = $_POST[ 'username' ];
$user = addslashes($user);
$user = iconv("gbk", 'utf8', $user);
$pass = $_POST[ 'password' ];
$pass = md5( $pass );
$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
print_r($qry);
$result = @mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );
var_dump($result);
處理過程如下:
%bf%27----(addslashes)->%bf%5c%27-----(utf8)---->縗' 這樣單引號就放出來了,大體流程是%bf%27經(jīng)過addslashes之后變成了%bf%5c%27,再經(jīng)過iconv從gbk轉(zhuǎn)換為utf8的時(shí)候,變成了%e7%b8%97%27,也就是縗'。利用的前提是設(shè)置了set names utf8。
2,在php中使用mysql_query('set names gbk'),指定了客戶端,連接層,結(jié)果為gbk編碼。構(gòu)造數(shù)據(jù)%bf%27,過程和第一種情況類似
%bf%27---(addslashes)-->%bf%5c%27---(set names gbk)--->縗'
3,iconv轉(zhuǎn)換從utf8到gbk,set names字符集為gbk,構(gòu)造數(shù)據(jù)如下%e9%8c%a6帶入反斜杠,注釋掉單引號
大體數(shù)據(jù)流程:%e9%8c%a6-----(utf8)----%e5%5c----(addslashes)--->%e5%5c%5c
>>> s = '\xe9\x8c\xa6'
>>> s.decode('utf8')
u'\u9326'
>>> s.decode('utf8').encode('gbk')
'\xe5\\'
總之一條,都是打的%5c的注意,要么轉(zhuǎn)義后轉(zhuǎn)utf8吃掉%5c,要么轉(zhuǎn)utf8后再轉(zhuǎn)義放出%5c
參考:
http://seclists.org/bugtraq/2008/May/61
http://www.sektioneins.de/en/advisories/advisory-032008-php-multibyte-shell-command-escaping-bypass-vulnerability.html
http://php.net/ChangeLog-5.php
http://php.net/releases/
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。