几年前,我用艰难的方式在C中学习了Format String Attacks。现在,我最近看到了一些像这样的PHP代码:
<?php
echo sprintf($_GET['format'], $_GET['value1'], $_GET['value2']);
我尝试将此$_GET['format']
设置为%s%s%s...
之类的字符串,但PHP只存在于PHP Warning: sprintf(): Too few arguments in file.php on line 2
。是不是仍然可以进行格式字符串攻击?
答案 0 :(得分:3)
不是传统意义上的,因为PHP的sprintf
不支持任何真正危险的转换,例如%n
。用户控制的格式字符串仍然可能导致一些有限的破坏(考虑%99999999s
),但我认为可能做的最坏情况是消耗内存和时间。
答案 1 :(得分:2)
我还发现了整数溢出。这导致了这个:
<?php
echo sprintf('%2147483646$s', "foo"); # Warning: Too few arguments
echo sprintf('%2147483647$s', "foo"); # Warning: Argument number must be greater than zero
我将此归档为PHP Bug #61531。我不确定,它是否可以被利用。
答案 2 :(得分:0)
高级语言倾向于验证传递的参数数量,而不是盲目地信任程序员。你需要找到另一个攻击媒介。
答案 3 :(得分:-2)
不确定是否存在PHP sprintf()漏洞,但示例代码似乎是不执行操作的主要示例。
就我而言,sprintf应该帮助你锁定字符串,而不是相反。例如,这是我认为使用sprintf()的有用理由:
$sql = sprintf(
"insert into table (myname, myvalue) values ('%s', '%s')",
mysql_real_escape_string( $_GET['name'] ),
intval( $_GET['value'] )
);
使用sprintf的一个更有用的理由是借用它的堂兄 vsprintf 并不断重复使用:
// takes variable number of parameters
function sanitize() {
$args = func_get_args();
$sql = array_shift( $args );
foreach( $args as $k => $v ) $args[$k] = mysql_escape_string( $v );
$safe_sql = vsprintf( $sql, $args );
return( $safe_sql );
}
有了它,您可以安全地从查询中隔离参数并假设它们将被清理:
$t = mysql_query(sanitize(
"insert into mytable (myname, myvalue) values ('%s', '%s')",
$_GET['name'],
$_GET['value']
));