做网站的技术路线,手机网站外链怎么,青岛城乡住房建设厅网站,wordpress08教程利用Mysqli和PDO
产生原因主要就是一些数据没有经过严格的验证#xff0c;然后直接拼接 SQL 去查询。导致产生漏洞#xff0c;比如#xff1a;
$id $_GET[id];
$sql SELECT name FROM users WHERE id $id;因为没有对 $_GET[‘id’] 做数据类型验证#xf…利用Mysqli和PDO
产生原因主要就是一些数据没有经过严格的验证然后直接拼接 SQL 去查询。导致产生漏洞比如
$id $_GET[id];
$sql SELECT name FROM users WHERE id $id;因为没有对 $_GET[‘id’] 做数据类型验证注入者可提交任何类型的数据比如 and 1 1 or 等不安全的数据。如果按照下面方式写就安全一些。
$id intval($_GET[id]);
$sql SELECT name FROM users WHERE id $id;把 id 转换成 int 类型就可以去掉不安全的东西。
验证数据
防止注入的第一步就是验证数据可以根据相应类型进行严格的验证。比如 int 类型直接通过 intval 进行转换就行
$id intval($_GET[id]);字符处理起来比较复杂些首先通过 sprintf 函数格式化输出确保它是一个字符串。然后通过一些安全函数去掉一些不合法的字符比如
$str addslashes(sprintf(%s,$str));也可以用mysqli_real_escape_string 函数替代 addslashes 这样处理以后会比较安全。当然还可以进一步去判断字符串长度去防止 [缓冲区溢出攻击] 比如
$str addslashes(sprintf(%s,$str));
$str substr($str,0,40); //最大长度为40参数化绑定
参数化绑定防止 SQL 注入的又一道屏障。php MySQLi 和 PDO 均能提供这样的功能。比如 MySQLi 可以这样去查询
$mysqli new mysqli(localhost,my_user,my_password,world);
$stmt $mysqli-prepare(INSERT INTO CountryLanguage VALUES (?,?,?,?));
$code DEU;
$language Bavarian;
$official F;
$percent 11.2;
$stmt-bind_param(sssd,$code,$language,$official,$percent);PDO 的更是方便比如
/* Execute a prepared statement by passing an array of values */
$sql SELECT name,color,calories
FROM fruit
WHERE calories :calories AND color :colour;
$sth $dbh-prepare($sql,array(PDO::ATTR_CURSOR PDO::CURSOR_FWDONLY));
$sth-execute(array(:calories 150, :colour red));
$red $sth-fetchAll();
$sth-execute(array(:calories 175, :colour yellow));
$yellow $sth-fetchAll();我们多数使用 php 的框架进行编程所以最好不要自己拼写 SQL按照框架给定参数绑定进行查询。遇到较为复杂的 SQL 语句一定要自己拼写的时候一定要注意严格的判断。没有用 PDO 或者 MySQLi 也可以自己写个 prepared比如 wordpress db 查询语句可以看出也是经过严格的类型验证。
function prepare( $query, $args ){if(is_null($query))return;// This is not meant to be foolproof -- // but it will catch obviously incorrect usage.if(strpos($query,%) false){_doing_it_wrong(wpdb::prepare,sprintf(__(The query argument of %s must have a placeholder.),wpdb::prepare()),3.9);}$args fun_get_args();array_shift($args);// If args were passed as an array (as in vsprintf), move them upif(isset($args[0]) is_array($args[0]))$args $args[0];$query str_replace(%s,%s,$query);//in case someone mistakenly already singlequoted it$query str_replace(%s,%s,$query);//doublequote unquoting$query preg_replace(|(?!%)%f|,%F,$query); //Force floats to be locale unaware$query pref_replace(|(?!%)%s|,%s,$query);//quote the strings,avoiding escaped strings like %%sarray_walk($args,array($this,escape_by_ref));return vsprintf($query,$args);
}总结
安全性很重要也可以看出一个人基本功项目漏洞百出扩展性和可维护性再好也没有用。平时多留意树立安全意识养成一种习惯一些基本的安全当然也不会占用 coding 的时间。
养成这个习惯即便在项目急时间短的情况下依然可以做的质量很高不要等到自己以后负责的东西数据库都被拿走了造成损失才重视。
虽然国内很多PHP程序员仍在依靠addslashes防止SQL注入还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于黑客可以用0xbf27来代替单引号而addslashes只是将0xbf27修改为0xbf5c27成为一个有效的多字节字符其中的0xbf5c仍会被看作是单引号所以addslashes无法成功拦截。
当然addslashes也不是毫无用处它是用于单字节字符串的处理多字节字符还是用mysql_real_escape_string吧。
另外对于php手册中get_magic_quotes_gpc的举例
if(!get_magic_quotes_gpc()){$lastname addslashes($_POST[lsquo;lastnamersquo;]);
}else{$lastname $_POST[lsquo;lastnamersquo;];
}最好对magic_quotes_gpc已经开放的情况下还是对$_POST[‘lastname’]进行检查一下。
再说下mysql_real_escape_string和mysql_escape_string这2个函数的区别 mysql_real_escape_string 必须在PHP 4.3.0PHP5的情况下才能使用。否则只能用mysql_escape_string两者的区别是mysql_real_escape_string 考虑到连接的当前字符集而mysql_escape_string 不考虑。
总结一下
addslashes() 是强行加 mysql_real_escape_string() 会判断字符集但是对PHP版本有要求 mysql_escape_string不考虑连接的当前字符集。
参考文章链接 https://mp.weixin.qq.com/s/X6q0xpbnJ9lojIIwNmDzdA
补充
一addslashes
php addslashes函数的作用是在预定义的字符前面加上反斜杠这些预定义字符包括
单引号 双引号 反斜杠\ NULL
$strmy names wxp;
echo addslashes($str);//输出my name\s wxp然后在拼接mysql字符串
$sqlinsert into student(student_name)values(.addslashes($str).);
mysql_query($sql);此时字符串被插入到数据库那么大家是否知道插入的字符串是带反斜杠还是不带反斜杠呢恐怕很多人都会认为肯定是带反斜杠的字符串。其实这个答案是错误的插入的字符串是没有带反斜杠。至于为什么插入的字符串在数据库中是没有加反斜杠请大家继续看下面讲解。
如果字符串$strmy name’s wxp是使用POST和GET提交的数据这个时候插入数据库中的数据是带反斜杠的由此可知addslashes只是在POST和GET数据插入数据库时才会把反斜杠同时插入到数据库其他情况下不会将反斜杠插入到数据库。
注释默认地PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。所以您不应对已转义过的字符串使用 addslashes()因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测
参考 原文链接https://blog.csdn.net/MengJing_/article/details/89353942
二mysql_real_escape_string
mysql_real_escape_string (PHP 4 4.3.0, PHP 5)
mysql_real_escape_string — 将字符串中的特殊字符进行转义以在 SQL 语句中使用 警告 本扩展自 PHP 5.5.0 起已废弃并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL 扩展来替换之。参见 MySQL选择 API 指南来获取更多信息。用以替代本函数的有 mysqli_real_escape_string() PDO::quote() 说明
mysql_real_escape_string(string $unescaped_string, resource $link_identifier NULL): string考虑到连接的当前字符集对 unescaped_string 进行特殊字符转义以便安全地将其放置在 mysql_query() 中。如果要插入二进制数据则必须使用此函数。
mysql_real_escape_string() 调用 mysql 库的函数 mysql_real_escape_string, 在以下字符前添加反斜线\x00、\n、\r、\、、 和 \x1a.
在向 MySQL 发送查询之前必须始终有少数例外使用此函数来确保数据的安全。 警告 安全: 默认字符集 The character set must be set either at the server level,or with the API function mysql_set_charset() for it to affect mysql_real_escape_string(). See the concepts section on character sets for more information. 示例
?php
// Connect
$link mysql_connect(mysql_host, mysql_user, mysql_password)OR die(mysql_error());// Query
$query sprintf(SELECT * FROM users WHERE user%s AND password%s,mysql_real_escape_string($user),mysql_real_escape_string($password));
?三mysql_escape_string
mysql_escape_string (PHP 4 4.0.3, PHP 5)
mysql_escape_string — 转义字符串用于 mysql_query 警告 本函数自 PHP 4.3.0 起已废弃并且它和整个 MySQL 扩展自 PHP 7.0.0 开始被移除。 可以选择出于活跃开发中的MySQLi 或 PDO_MySQL 扩展来作为替代。 参见 MySQL选择 API 指南来获取更多信息。用以替代本函数的有mysqli_escape_string() PDO::quote() 说明
mysql_escape_string(string $unescaped_string): string本函数将转义 unescaped_string使之可以安全用于 mysql_query()。此函数已弃用。
本函数和 mysql_real_escape_string() 相同除了 mysql_real_escape_string() 接受连接处理程序并根据当前字符集进行转义。mysql_escape_string() 不接受连接参数也不遵循当前字符集设定。
示例
?php
$item Zaks Laptop;
$escaped_item mysql_escape_string($item);
printf(Escaped string: %s\n, $escaped_item);
?以上示例会输出
Escaped string: Zak\s Laptop注意: mysql_escape_string() 不转义 % 和 _。