不要使用 addslashes 函数来转义要发送到 mysql 的值。至少使用 mysql_real_escape_string 或 pg_escape,如果你还没有使用预备语句的话。
请记住,单引号不是唯一可能破坏您的 SQL 查询的特殊字符。并且引号是 addslashes 唯一关心的东西。
(PHP 4, PHP 5, PHP 7, PHP 8)
addslashes — 用斜杠引用字符串
返回在需要转义的字符之前添加反斜杠的字符串。这些字符是
'
)"
)\
)addslashes() 的一个用例是在要由 PHP 评估的字符串中转义上述字符
<?php
$str = "O'Reilly?";
eval("echo '" . addslashes($str) . "';");
?>
addslashes() 有时被错误地用来尝试阻止 SQL 注入。相反,应该使用特定于数据库的转义函数和/或预备语句。
string
要转义的字符串。
返回转义后的字符串。
示例 #1 一个 addslashes() 示例
<?php
$str = "Is your name O'Reilly?";
// 输出:Is your name O\'Reilly?
echo addslashes($str);
?>
不要使用 addslashes 函数来转义要发送到 mysql 的值。至少使用 mysql_real_escape_string 或 pg_escape,如果你还没有使用预备语句的话。
请记住,单引号不是唯一可能破坏您的 SQL 查询的特殊字符。并且引号是 addslashes 唯一关心的东西。
Addslashes 从来不是正确答案,它的(滥)用会导致安全漏洞!
如果您需要转义 HTML,它是(不幸的是)
<?php
echo htmlentities($html, ENT_QUOTES|ENT_SUBSTITUTE|ENT_DISALLOWED);
?>
如果您需要引用 shell 参数,它是
<?php
$cmd.= " --file=" . escapeshellarg($arg);
?>
如果您需要引用 SQL 字符串,它是
<?php
$sql.= "WHERE col = '".$mysqli->real_escape_string($str)."'";
?>
或者
<?php
$sql.= "WHERE col = " . $pdo->quote($str);
?>
如果您需要在 javascript/json 字符串中引用,它是
<?php
let str = <?=json_encode($str, JSON_THROW_ON_ERROR);?>;
?>
如果您需要在 xpath 中引用字符串,它是
<?php
// 基于 https://stackoverflow.com/a/1352556/1067003
function xpath_quote(string $value):string{
if(false===strpos($value,'"')){
return '"'.$value.'"';
}
if(false===strpos($value,'\'')){
return '\''.$value.'\'';
}
// 如果值包含单引号和双引号,则构造一个表达式,该表达式将所有非双引号子字符串与引号连接起来,例如:
//
// concat("'foo'", '"', "bar")
$sb='concat(';
$substrings=explode('"',$value);
for($i=0;$i<count($substrings);++$i){
$needComma=($i>0);
if($substrings[$i]!==''){
if($i>0){
$sb.=', ';
}
$sb.='"'.$substrings[$i].'"';
$needComma=true;
}
if($i < (count($substrings) -1)){
if($needComma){
$sb.=', ';
}
$sb.="'\"'";
}
}
$sb.=')';
return $sb;
}
$xp->query('/catalog/items/item[title='.xpath_quote($var).']');
?>
如果您需要在 CSS 中引用字符串,它是
<?php
// CSS 转义代码来自 Zend Framework ( https://github.com/zendframework/zf2/blob/master/library/Zend/Escaper/Escaper.php )
function css_escape_string($string)
{
$cssMatcher = function ($matches) {
$chr = $matches[0];
if (strlen($chr) == 1) {
$ord = ord($chr);
} else {
$chr = mb_convert_encoding($chr, 'UTF-16BE', 'UTF-8'); // $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8');
$ord = hexdec(bin2hex($chr));
}
return sprintf('\\%X ', $ord);
};
$originalEncoding = mb_detect_encoding($string);
if ($originalEncoding === false) {
$originalEncoding = 'UTF-8';
}
;
$string = mb_convert_encoding($string, 'UTF-8', $originalEncoding); // $this->toUtf8($string);
// throw new Exception('mb_convert_encoding(\''.$string.'\',\'UTF-8\',\''.$originalEncoding.'\');');
if ($string === '' || ctype_digit($string)) {
return $string;
}
$result = preg_replace_callback('/[^a-z0-9]/iSu', /*$this->*/$cssMatcher, $string);
// var_dump($result);
return mb_convert_encoding($result, $originalEncoding, 'UTF-8'); // $this->fromUtf8($result);
}
?>
- 但是不添加斜杠。
要将 PHP 变量输出到 Javascript,请使用 json_encode()。
<?php
$var = "He said \"Hello O'Reilly\" & disappeared.\nNext line...";
echo "alert(".json_encode($var).");\n";
?>
输出
alert("He said \"Hello O'Reilly\" & disappeared.\nNext line...") ;
addslashes 不会使您的输入安全地用于数据库查询!它只根据 PHP 的定义进行转义,而不是您的数据库驱动程序定义的。任何使用此函数来转义用于数据库的字符串很可能是一个错误 - 应该使用 mysql_real_escape_string、pg_escape_string 等,具体取决于您的底层数据库,因为每个数据库都有不同的转义要求。特别是,MySQL 需要转义 \n、\r 和 \x1a,而 addslashes 不会这样做。因此,依赖 addslashes 根本不是一个好主意,并且可能会使您的代码容易受到安全风险的影响。我真的不明白这个函数应该做什么。
注意使用 addslashes() 对输入到 serialize() 函数的内容进行转义。serialize() 使用字符串的长度来存储字符串;长度必须与存储的字符串匹配,否则 unserialize() 会失败。
如果序列化 addslashes() 的结果并将其存储在数据库中,可能会出现这种情况;一些数据库(绝对包括 PostgreSQL)会自动从 SELECT 结果中的“特殊”字符中剥离反斜杠,导致返回的字符串比序列化时短。
换句话说,执行以下操作...
<?php
$string="O'Reilly";
$ser=serialize($string); # 安全 -- 不会计算斜杠
$result=addslashes($ser);
?>
...而不是...
<?php
$string="O'Reilly";
$add=addslashes($string); # 有风险!-- 会计算斜杠
$result=serialize($add);
?>
在这两种情况下,在“O'Reilly”中的撇号之后都会添加一个反斜杠;只有在第二种情况下,反斜杠才会包含在 serialize() 记录的字符串长度中。
[注意维护人员:您可以选择将此注释链接到 serialize() 以及 addslashes()。我将避免自己进行这种交叉发布...]
如果您只想像在 PHP 中通常那样引用一个字符串(例如,在返回 AJAX 结果时,在 JSON 字符串值内,或者在使用参数构建 URL 时),请不要使用 addslashes(您不希望同时转义 " 和 ')。相反,只需使用此函数
<?php
function Quote($Str) // 只使用双引号
{
$Str=str_replace('"','\"',$Str);
return '"'.$Str.'"';
} // Quote
?>
轻松修改此函数以获取单引号函数。
对于 PHP 7.3.*,请使用 FILTER_SANITIZE_ADD_SLASHES。
<?php
$str = "Is your name O'Reilly?";
$strWithSlashes = filter_var($str, FILTER_SANITIZE_ADD_SLASHES);
// 输出:Is your name O\'Reilly?
echo $strWithSlashes;
?>
根据这篇文章,此函数在 PHP 4.0 中已弃用
http://www.newsforge.com/article.pl?sid=06/05/23/2141246
此外,值得一提的是,PostgreSQL 很快将开始阻止使用 \ 作为转义字符的转义单引号的查询,在某些情况下,这取决于字符串的编码。在 SQL 中转义引号的标准方式(并非所有 SQL 数据库)是将单引号更改为两个单引号(例如,' ' ' 变为 ' '' ' 用于查询)。
您应该研究其他转义字符串的方法,例如“mysql_real_escape_string”(参见下面的注释)以及其他特定于数据库的转义函数。
注意在创建要转义的字符串时使用双引号还是单引号
$test = 'This is one line\r\nand this is another\r\nand this line has\ta tab';
echo $test;
echo "\r\n\r\n";
echo addslashes($test);
$test = "This is one line\r\nand this is another\r\nand this line has\ta tab";
echo $test;
echo "\r\n\r\n";
echo addslashes($test);
请记住,如果您要对变量使用 LIKE 运算符,也要对下划线 (_) 和百分号 (%) 进行斜杠处理,否则您会得到一些意外的结果。
注意,此函数不适用于 mssql 或 access 查询。
使用上面的函数(也适用于数组)。
function addslashes_mssql($str){
if (is_array($str)) {
foreach($str AS $id => $value) {
$str[$id] = addslashes_mssql($value);
}
} else {
$str = str_replace("'", "''", $str);
}
return $str;
}
function stripslashes_mssql($str){
if (is_array($str)) {
foreach($str AS $id => $value) {
$str[$id] = stripslashes_mssql($value);
}
} else {
$str = str_replace("''", "'", $str);
}
return $str;
}
基于
Danijel Pticar
2009 年 8 月 5 日 05:22
我推荐此扩展版本,以完全替换 addslashes(适用于字符串和数组)
<?php
function addslashesextended(&$arr_r)
{
if(is_array($arr_r))
{
foreach ($arr_r as &$val)
is_array($val) ? addslashesextended($val):$val=addslashes($val);
unset($val);
}
else
$arr_r=addslashes($arr_r);
}
?>
请注意,当对包含西里尔字母的字符串使用 addslashes() 时,addslashes() 会完全混淆字符串,使其无法使用。
如果要为特殊符号添加斜杠以避免它们干扰正则表达式(例如:. \ + * ? [ ^ ] $ ( ) { } = ! < > | :),应使用 preg_quote() 函数。
当您添加 addslashes(addslashes($str)) 时会发生什么?这不是一件好事,可能会被修复。
function checkaddslashes($str){
if(strpos(str_replace("\'",""," $str"),"'")!=false)
return addslashes($str);
else
return $str;
}
checkaddslashes("aa'bb"); => aa\'bb
checkaddslashes("aa\'bb"); => aa\'bb
checkaddslashes("\'"); => \'
checkaddslashes("'"); => \'
希望这能帮助您。
spamdunk at home dot com,您的方式在 PostgreSQL(以及可能在 MySQL)上很危险。您完全正确,ANSI SQL 规定使用 ' 进行转义,但这些数据库也支持 \ 进行转义(我认为违反了标准)。这意味着,如果他们传入包含 "\'" 的字符串,您会将其扩展为 "\'''"(一个转义的引号后跟一个未转义的引号。错误!攻击者可以执行任意 SQL 来删除您的表,让自己成为管理员,无论他们想做什么。)
最安全且正确的做法是
- 不要使用 magic quotes;这种方法很糟糕。首先,这是在假设您将在数据库查询中使用您的输入,这是任意的。(为什么不将所有 "<" 用 "<" 转义呢?跨站脚本攻击也很常见。)最好设置一种方法,当您使用它时,它会对您进行正确的转义,如下所示
- 将数据插入数据库时,使用带占位符的预处理语句。例如,使用 PEAR DB 时
<?php
$stmt = $dbh->prepare('update mb_users set password = ? where username = ?');
$dbh->execute($stmt, array('12345', 'bob'));
?>
请注意,? 周围没有引号。它会自动为您处理。它保证对您的数据库是安全的。(仅在 Oracle 上使用 ',在 PostgreSQL 上使用 \ 和 ',但您甚至不必考虑它。)
此外,如果数据库支持预处理语句(即将发布的 PostgreSQL 7.3、Oracle 等),对同一个 prepare 的多次执行可能会更快,因为它可以重用相同的查询计划。如果它不支持(MySQL 等),这种方式将回退到专门为您的数据库编写的引用代码,避免了我上面提到的问题。
(如果我的语法错误,请原谅我。我不是真正的 PHP 程序员;这是我在 Java、Perl、PL/SQL、Python、Visual Basic 等类似事物中了解到的东西。)
这是一个防止双引号的函数示例,我很惊讶还没有人发布过类似的东西……(也适用于数组)
<?php
function escape_quotes($receive) {
if (!is_array($receive))
$thearray = array($receive);
else
$thearray = $receive;
foreach (array_keys($thearray) as $string) {
$thearray[$string] = addslashes($thearray[$string]);
$thearray[$string] = preg_replace("/[\\/]+/","/",$thearray[$string]);
}
if (!is_array($receive))
return $thearray[0];
else
return $thearray;
}
?>
使用反斜杠 '\$' 转义 '$'。
<?php
$evalStr = "5 + 3";
$sum = 0;
$evalStr = " \$sum = ". $evalStr.";";
eval( $evalStr);
print ("sum ".$sum);
?>