简单 SQL 注入的 Base64 编码字符串

3

除了性能问题外,base64_encode()是否是防止SQL注入的“好”做法?

当然不是适用于所有字段(列),仅适用于一个TEXT字段(例如:在联系表单中)。

我们知道,base64_encode()函数返回的字符是“安全”的,甚至不需要转义(如果我错了,请纠正我),但我想知道它在每种情况下是否都是“安全”的(字符集编码或类似情况)。

简单实用的例子:

$dbc = new mysqli( DBHOSTNAME, DBUSERNAME, DBPASSWORD );

$name = preg_replace( "#[^A-Za-z0-9@_]#", "", $_POST[ "name" ] );

$phone = preg_replace( "#[^0-9 +]#", "", $_POST[ "phone" ] );

/*
Assuming this function check and sanitize a valid email
*/ 
$email = is_email( $_POST[ "email" ] );

$dbc->query( "INSERT INTO `testdb`.`testtable` 
( `name`, `email`,`phone`,`message` )
VALUES ( '$name', '$email', '$phone', '" . base64_encode( $_POST[ "message" ] ) . "' )" );

另一方面,预处理语句:

$dbc = new mysqli( DBHOSTNAME, DBUSERNAME, DBPASSWORD );

$name = preg_replace( "#[^A-Za-z0-9@_]#", "", $_POST[ "name" ] );
$phone = preg_replace( "#[^0-9 +]#", "", $_POST[ "phone" ] );

/*
Assuming this function check and sanitize a valid email
*/ 
$email = is_email( $_POST[ "email" ] );

$stmt = $dbc->prepare( " INSERT INTO `testdb`.`testtable` 
( `name`, `email `phone`, `message` )
VALUES( '$name', '$email', '$phone', ? ) " );

$stmt->bind_param( 's', $_POST[ "message" ] );
$stmt->execute();

我们每天都需要处理各种不同类型的黑客攻击和注入技术。

从逻辑上讲,PDO或mysqli(使用预处理语句)是安全的。但在我的情况下,输出(消息)会被转换成base64格式(项目的其他部分要求这样做),所以为什么不在存储之前进行转换呢?(数据库需要一些额外的空间)


3
使用标准的转义机制或绑定参数有什么问题? - alex
实际上,我正在使用准备好的语句(使用mysqli),逻辑上是正确的,功能齐全且安全。没有任何问题。只是对base64_encode()在每种情况下的行为感到好奇。 - h2odev
1
预处理语句中的参数绑定不仅仅是为了防止 SQL 注入。请绑定所有参数,真的没有理由不这样做。 - rjdown
2个回答

3
由于base64_encode()函数的特性(使二进制数据在不支持8位传输的传输层中存活),您无需转义任何内容!
返回的字符是[0-9a-zA-Z/]。
但我强烈建议您使用准备好的语句(使用mysqli或PDO)。虽然速度稍慢,但您不必每次处理表结构时都更改净化逻辑。
而且,同样重要的是,也许将来您需要在表格上索引数据(例如搜索LIKE或FULLSEARCH)。
您的第二个示例是正确的(绑定所有参数)。

2

base64_encode 函数并不是用于转义字符串的,也就是说,并没有任何保证特定的 SQL 方言不会将 base64 编码的任何字符视为分隔符;您应该始终依赖专用的转义函数。

然而我们并不知道任何 SQL 方言会将 base64 字符视为分隔符,因此总体来说是安全的。


我已经研究了base64_encode()的C源代码(/ect/standard/base64.c),并且完全是安全的(使用静态的base64_table数组,其中包含[A-Za-z0-9/]中的字符)。 这就是我所需要的。 - h2odev
我的担忧并不在于base64_encode返回哪些字符,而是这些字符可能被SQL引擎解释的方式。假设一个SQL解释器使用斜杠(/)作为字符串分隔符,那么一个base64编码的字符串就可能破坏查询。这并不是科幻小说,在DB2中,例如,您可以在引号(")和撇号(')之间选择字符串分隔符。正如我所说,我不知道任何SQL语言将[A-Za-z0-9/]中的任何字符用作字符串分隔符,但这并不意味着没有(或不会有)使用它们的语言。 - Daniels118

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接