Heim  >  Artikel  >  Backend-Entwicklung  >  php SQL 防注入的一些经验

php SQL 防注入的一些经验

WBOY
WBOYOriginal
2016-06-20 12:50:00822Durchsuche

原文  http://www.cnblogs.com/liuzhang/p/4753467.html

产生原因

一方面自己没这方面的意识,有些数据没有经过严格的验证,然后直接拼接 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, colour, calories  FROM fruit  WHERE calories < :calories AND colour = :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,比如 wordprss 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 = func_get_args();  array_shift( $args );  // If args were passed as an array (as in vsprintf), move them up  if ( 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 = preg_replace( '|(?<!%)%s|', "'%s'" , $query );     // quote the strings, avoiding escaped strings like %%s  array_walk( $args, array( $this, 'escape_by_ref' ) );  return @ vsprintf( $query, $args );}

总结

安全性很重要,也可以看出一个人基本功,项目漏洞百出,扩展性和可维护性再好也没有用。平时多留意,树立安全意识,养成一种习惯,一些基本的安全当然也不会占用用 coding 的时间。养成这个习惯,即便在项目急,时间短的情况一下,依然可以做的质量很高。不要等到自己以后负责的东西,数据库都被拿走了,造成损失才重视。共勉!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn