PHP sprintf被认为有害吗?

时间:2012-03-27 18:56:20

标签: php security printf

几年前,我用艰难的方式在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。是不是仍然可以进行格式字符串攻击?

4 个答案:

答案 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']
));