phpphp sql selectt语句需要使用预处理防止sql注入吗?

简明手册:如何在PHP应用中防止SQL注入 -
| 关注黑客与极客
简明手册:如何在PHP应用中防止SQL注入
共235611人围观
,发现 7 个不明物体
SQL注入是一个控制数据库查询的技术,往往会导致丧失机密性。在某些情况下,如果成功执行
SELECT&'&?php&eval(base64_decode(&someBase64EncodedDataHere&));'&INTO&OUTFILE&'/var/www/reverse_shell.php'
将导致服务器被攻击者拿下,而代码注入(包括SQL,LDAP,操作系统命令,XPath注入技术)长年保持在OWASP漏洞排名前十。
更多人分享有关于应用安全的知识是一件极好的事。然而不幸的是,网络上流传的大部分东西(尤其是老博客文章,高搜索引擎排名)都已经过时了。虽然是无意的误导,但是却造成了很大的威胁。
如何防止SQL注入
使用预处理语句,也被称为参数化查询。例如:
$stmt&=&$pdo-&prepare('SELECT&*&FROM&blog_posts&WHERE&YEAR(created)&=&?&AND&MONTH(created)&=&?');if&(!$stmt-&execute([$_GET['year'],&$_GET['month']]))&{
&&&&header(&Location:&/blog/&);&
$posts&=&$stmt-&fetchAll(\PDO::FETCH_ASSOC);
??在PHP应用中预处理语句过滤掉任何SQL注入的可能,无论是什么都需要先传递到$_GET变量。SQL查询语句是攻击者无法改变的(除非你将PDO::ATTR_EMULATE_PREPARES 开启了,这也意味着你还没有真正使用预处理语句)
预处理语句解决应用安全的根本问题:通过发送完全独立的包将操作指令与数据进行单独处理。这和导致堆栈溢出的问题有点类似了。
只要你没有用SQL语句连接user-provided变量和环境变量(并且保证你没有使用emulated prepares),那你就不必担心交叉SQL注入的问题了。
预处理语句确保WEB应用与数据库服务之间的交互(即使两者不在同一台机器上,也会通过TLS进行连接)。攻击者还有可能在字段中存储一个payload,这是相当危险的,比如一个存储过程,我们称之为高阶SQL注入。
在这种情况下,我们建议不要编写存储过程,它会制造一个高阶SQL注入点。
关于输出过滤
应该有人看到过上面这张关于SQL注入攻击的漫画吧,在一些安全会议上甚至都经常被拿来引用,尤其是写给新人的文章中。这张漫画提醒了我们要提高对数据库查询中危险用户输入的意识,但是漫画中的建议却是过滤掉数据库输入,通过对相关问题的理解,我们知道这仅仅是一个折衷的办法。
最好忘记过滤输入
虽然可以在数据发送到数据库之前重写传入的数据流来防止攻击者的攻击,但是这个过程比较难以把控。
除非你想花时间去研究,达到完全掌握所有Unicode格式应用程序,你最好不要尝试过滤你的输入。
此外,改变你的输入数据流可能造成数据损坏。特别是在你正在处理原始二进制文件(图片,加密信息)的时候。
预处理语句能简单粗暴的防止SQL注入
XKCD作者Randall Munroe是个聪明人。如果这幅漫画直到今天才被创作出来,大概会是这个样子的
输入仍应进行验证
数据验证与过滤完全不是一回事,预处理语句可以防止SQL注入,然而并不能让你摆脱那些糟糕的数据。大多数情况下,会使用filter_var()
$email&=&filter_var($_POST['email'],&FILTER_VALIDATE_EMAIL);
if&(empty($email))&{&&&&
&&&&throw&new&\InvalidArgumentException('Invalid&email&address');
列和表标识符
当列和表标识符作为查询语句中的一部分,你不能使用参数表示它们。如果你正在开发的这个应用需要一个动态查询结构,请使用白名单。
白名单是一个应用程序逻辑策略,它只允许少数可信的值。相对来说黑名单,仅仅是禁止已知的恶意输入。
大多数情况下,使用白名单比黑名单更安全!
$qs&=&'SELECT&*&FROM&photos&WHERE&album&=&?';
//&Use&switch-case&for&an&explicit&whitelist
switch&($_POST['orderby'])&{&&&&
&&&&case&'name':&&&&
&&&&case&'exifdate':&&&&
&&&&case&'uploaded':&&&&&&&
&&&&&&&&//&These&strings&are&trusted&and&expected
&&&&&&&$qs&.=&'&ORDER&BY&'.$_POST['orderby'];
&&&&&&&if&(!empty($_POST['asc']))&{
&&&&&&&&&&&$qs&.=&'&ASC';
&&&&&&&}&else&{&&&&&&&&&&&
&&&&&&&&&&&$qs&.=&'&DESC';
&&&&&&&}&&&&
&&&&default:&&&&&&&
&&&&//&Some&other&value&was&passed.&Let's&just&order&by&photo&ID&in&descending&order.
&&&&&&&$qs&.=&'&ORDER&BY&photoid&DESC';
}$stmt&=&$db-&prepare($qs)
&&&&;if&($stmt-&execute([$_POST['album_id']]))&{&&&&
&&&&$photos&=&$stmt-&fetchAll(\PDO::FETCH_ASSOC);&
使用预处理语句看起来很麻烦?
开发者第一次遇到预处理语句,对于需要写大量的冗余代码而感到沮丧(提取,执行,取回;提取,执行,取回;….令人厌烦)
由此,EasyDB[/paragonie/easydb]诞生了。
如何使用EasyDB
这里有两种方法。
你可以使用EasyDB包含你的PDO
如果你熟悉PDO构造,你可以使用\ParagonIE\EasyDB\Factory::create()参数来进行替代
//&First&method:
$pdo&=&new&\PDO('host=dbname=something',&'username',&'putastrongpasswordhere');
$db&=&\ParagonIE\EasyDB\EasyDB($pdo,&'mysql');
//&Second&method:
$db&=&\ParagonIE\EasyDB\Factory::create('host=dbname=something',&'username',&'putastrongpasswordhere');
如果有一个EasyDB对象,你可以开始利用它的快速开发安全数据库应用程序。
预处理语句:安全数据库查询
$data&=&$db-&safeQuery(&&&&
&&&&'SELECT&*&FROM&transactions&WHERE&type&=&?&AND&amount&&=&?&AND&date&&=&?',&
&&&&&&&&$_POST['ttype'],&&&&&&&&
&&&&&&&&$_POST['minimum'],&&&&&&&&
&&&&&&&&$_POST['since']
从一个数据库表中选择多行
$rows&=&$db-&run(
&&&&&'SELECT&*&FROM&comments&WHERE&blogpostid&=&?&ORDER&BY&created&ASC',&&&&&
&&&&&$_GET['blogpostid']
&&&&&foreach&($rows&as&$row)&{
&&&&&&&&&$template_engine-&render('comment',&$row);
从数据库表中选择一行
$userData&=&$db-&row(
&&&&&SELECT&*&FROM&users&WHERE&userid&=&?&,&&&&
&&&&$_GET['userid']
向数据库表中插入新的一行
$db-&insert('comments',&[
&&&&'blogpostid'&=&&$_POST['blogpost'],&&&&
&&&&'userid'&=&&$_SESSION['user'],&&&&
&&&&'comment'&=&&$_POST['body'],&&&&
&&&&'parent'&=&&isset($_POST['replyTo'])&?&$_POST['replyTo']&:&null
动态查询中躲避标识符(列/表/视图名)
$qs&=&'SELECT&*&FROM&some_table';
if&(!empty($where))&{&&&&
&&&&$qs&.=&'&WHERE&';&&&&
&&&&foreach&(\array_keys($where)&as&$column)&{&&&&&&&&
&&&&if&(!\in_array($column,&$whiteListOfColumnNames))&{&&&&&&&&&&&&
&&&&&&&&}&&&&&&&&
&&&&if&($and)&{&&&&&&&&&&&&
&&&&$qs&.=&'&AND&';
&&&&&&&&}&&&&&&&&
&&&&$qs&.=&$db-&escapeIdentifier($column).'&=&?';&&&&&&&&
&&&&$and&=&
}$qs&.=&'&ORDER&BY&rowid&DESC';
//&And&then&to&fetch&some&data
$data&=&$db-&run($qs,&\array_values($where);
警告:escapeIdentifier() 方法意味着输入不应该被转义。
安全从开发人员开始!
*参考来源github,译者/鸢尾 转载请注明来自FreeBuf黑客与极客()
必须您当前尚未登录。
必须(保密)
悟空竟在打飞机
关注我们 分享每日精选文章怎样使用sql注入语句?蒙圈了都【php吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:139,073贴子:
怎样使用sql注入语句?蒙圈了都收藏
sql注入语句应该写在哪啊,我自己写了一个网站,想用来做sql注入实验,但是不会啊,郁闷啊,大神救救我吧
经典作品新视角的3D奇幻悬疑风冒险页游给你带来超一流的摸金体验!
好像是 数据库验证那块儿吧
不知道下面这些东东是不是楼主很关心的:sql注入原理解释搭建PHP开发环境 做出框架图创建测试数据库和表开发用户管理项目PHP之sql注入 万能密码和万能用户名PHP之sql注入 防范(服务器配置、密码比对、pdo预处理)PHP搜索引擎中sql注入问题莫让他人成为网站超级管理员如果是,就点击观看传智播客php视频下载 韩顺平老师主讲的,应该会解决你的问题吧。
不懂sql注入原理怎么实验?
原理是没有对参数进行过滤,黑客就可以构造特殊mysql语句,比如:mysql_query(&SELECT * FROM `news` WHERE id='$id'&);$id没有进行任何过滤,那么,黑客就可以输入$id为:1' UNION (SELECT * FROM `users`) AND WHERE ''='整个mysql语句就成了:SELECT * FROM `news` WHERE id='1' UNION (SELECT * FROM `users`) WHERE ''=''其他语句以此类推防范方法就是过滤id,并过滤mysql语句(检查安全才执行查询,比如禁止union)
PDO对象的prepare可以防止sql语句注入 如7楼那样select * from 表 where 1=2 union select.....其中1=2就会让前面的语句变成false然后执行1=2 之后的union select********可耻的匿了
如果登陆网站没有安全验证或者加密的话,知道用户名加单引号再加#,不可密码就可以直接登陆的,比如admin'#
然后不用密码直接登录就可以 的 这是我们老师讲的SQL注入的一种
登录百度帐号推荐应用php防止sql注入的方法详解
作者:李宗禹
字体:[ ] 类型:转载 时间:
本文主要介绍了php防止sql注入的方法。具有很好的参考价值,下面跟着小编一起来看下吧
一、什么是SQL注入式攻击?
& 所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。常见的SQL注入式攻击过程类如:
& ⑴ 某个ASP.NET Web应用有一个登录页面,这个登录页面控制着用户是否有权访问应用,它要求用户输入一个名称和密码。&&
& ⑵ 登录页面中输入的内容将直接用来构造动态的SQL命令,或者直接用作存储过程的参数。下面是ASP.NET应用构造查询的一个例子:&
System.Text.StringBuilder query = new System.Text.StringBuilder("SELECT * from Users WHERE login = '")。Append(txtLogin.Text)。Append("' AND password='")。Append(txtPassword.Text)。Append("'");
& ⑶ 攻击者在用户名字和密码输入框中输入"'或'1'='1"之类的内容。
& ⑷ 用户输入的内容提交给服务器之后,服务器运行上面的ASP.NET代码构造出查询用户的SQL命令,但由于攻击者输入的内容非常特殊,所以最后得到的SQL命令变成:SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'.
& ⑸ 服务器执行查询或存储过程,将用户输入的身份信息和服务器中保存的身份信息进行对比。
& ⑹ 由于SQL命令实际上已被注入式攻击修改,已经不能真正验证用户身份,所以系统会错误地授权给攻击者。
& 如果攻击者知道应用会将表单中输入的内容直接用于验证身份的查询,他就会尝试输入某些特殊的SQL字符串篡改查询改变其原来的功能,欺骗系统授予访问权限。
& 系统环境不同,攻击者可能造成的损害也不同,这主要由应用访问数据库的安全权限决定。如果用户的帐户具有管理员或其他比较高级的权限,攻击者就可能对数据库的表执行各种他想要做的操作,包括添加、删除或更新数据,甚至可能直接删除表。
二、如何防范?
& 好在要防止ASP.NET应用被SQL注入式攻击闯入并不是一件特别困难的事情,只要在利用表单输入的内容构造SQL命令之前,把所有输入内容过滤一番就可以了。过滤输入内容可以按多种方式进行。
&(1)对于动态构造SQL查询的场合,可以使用下面的技术:
& 第一:替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令的含义。再来看前面的例子,“SELECT * from Users WHERE login = ''' or ''1''=''1' AND password = ''' or ''1''=''1'”显然会得到与“SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'”不同的结果。
& 第二:删除用户输入内容中的所有连字符,防止攻击者构造出类如“SELECT * from Users WHERE login = 'mas' —— AND password =''”之类的查询,因为这类查询的后半部分已经被注释掉,不再有效,攻击者只要知道一个合法的用户登录名称,根本不需要知道用户的密码就可以顺利获得访问权限。
&&第三:对于用来执行查询的数据库帐户,限制其权限。用不同的用户帐户执行查询、插入、更新、删除操作。由于隔离了不同帐户可执行的操作,因而也就防止了原本用于执行SELECT命令的地方却被用于执行INSERT、UPDATE或DELETE命令。
&(2)用存储过程来执行所有的查询。SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限可以限制到只允许特定的存储过程执行,所有的用户输入必须遵从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。
&(3)限制表单或查询字符串输入的长度。如果用户的登录名字最多只有10个字符,那么不要认可表单中输入的10个以上的字符,这将大大增加攻击者在SQL命令中插入有害代码的难度。&&
&(4)检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行——之所以要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。&&
& 在客户端,攻击者完全有可能获得网页的源代码,修改验证合法性的脚本(或者直接删除脚本),然后将非法内容通过修改后的表单提交给服务器。因此,要保证验证操作确实已经执行,唯一的办法就是在服务器端也执行验证。你可以使用许多内建的验证对象,例如RegularExpressionValidator,它们能够自动生成验证用的客户端脚本,当然你也可以插入服务器端的方法调用。如果找不到现成的验证对象,你可以通过CustomValidator自己创建一个。
&(5) 将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较,这相当于对用户输入的数据进行了“消毒”处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。System.Web.Security.FormsAuthentication类有一个HashPasswordForStoringInConfigFile,非常适合于对输入数据进行消毒处理。&
&(6) 检查提取数据的查询所返回的记录数量。如果程序只要求返回一个记录,但实际返回的记录却超过一行,那就当作出错处理。
&(7)使用预处理语句
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具拒绝访问 |
| 百度云加速
请打开cookies.
此网站 () 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3aecdba-ua98).
重新安装浏览器,或使用别的浏览器新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
丰衣足食, 积分 518, 距离下一级还需 482 积分
论坛徽章:1
问题描述:
  如果用户输入的数据在未经处理的情况下插入到一条SQL查询语句,那么应用将很可能遭受到SQL注入攻击,正如下面的例子:$unsafe_variable = $_POST['user_input'];
mysql_query(&INSERT INTO `table` (`column`) VALUES ('& . $unsafe_variable . &')&);复制代码因为用户的输入可能是这样的:value'); DROP TABLE--复制代码那么SQL查询将变成如下:INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE--')复制代码应该采取哪些有效的方法来防止SQL注入?
 最佳回答(来自Theo):
  使用预处理语句和参数化查询。预处理语句和参数分别发送到数据库服务器进行解析,参数将会被当作普通字符处理。这种方式使得攻击者无法注入恶意的SQL。 你有两种选择来实现该方法:
1、使用PDO:$stmt = $pdo-&prepare('SELECT * FROM employees WHERE name = :name');
$stmt-&execute(array('name' =& $name));
foreach ($stmt as $row) {
& & // do something with $row
}复制代码2、使用mysqli:$stmt = $dbConnection-&prepare('SELECT * FROM employees WHERE name = ?');
$stmt-&bind_param('s', $name);
$stmt-&execute();
$result = $stmt-&get_result();
while ($row = $result-&fetch_assoc()) {
& & // do something with $row
}复制代码PDO
  注意,在默认情况使用PDO并没有让MySQL数据库执行真正的预处理语句(原因见下文)。为了解决这个问题,你应该禁止PDO模拟预处理语句。一个正确使用PDO创建数据库连接的例子如下:$dbConnection = new PDO('mysql:dbname=host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection-&setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection-&setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);复制代码在上面的例子中,报错模式(ATTR_ERRMODE)并不是必须的,但建议加上它。这样,当发生致命错误(Fatal Error)时,脚本就不会停止运行,而是给了程序员一个捕获PDOExceptions的机会,以便对错误进行妥善处理。 然而,第一个setAttribute()调用是必须的,它禁止PDO模拟预处理语句,而使用真正的预处理语句,即有MySQL执行预处理语句。这能确保语句和参数在发送给MySQL之前没有被PHP处理过,这将使得攻击者无法注入恶意SQL。了解原因,可参考这篇博文:PDO防注入原理分析以及使用PDO的注意事项。 注意在老版本的PHP(&5.3.6),你无法通过在PDO的构造器的DSN上设置字符集,参考:silently ignored the charset parameter。
  当你将SQL语句发送给数据库服务器进行预处理和解析时发生了什么?通过指定占位符(一个?或者一个上面例子中命名的 :name),告诉数据库引擎你想在哪里进行过滤。当你调用execute的时候,预处理语句将会与你指定的参数值结合。 关键点就在这里:参数的值是和经过解析的SQL语句结合到一起,而不是SQL字符串。SQL注入是通过触发脚本在构造SQL语句时包含恶意的字符串。所以,通过将SQL语句和参数分开,你防止了SQL注入的风险。任何你发送的参数的值都将被当作普通字符串,而不会被数据库服务器解析。回到上面的例子,如果$name变量的值为 ’Sarah’; DELETE FROM employees ,那么实际的查询将是在 employees 中查找 name 字段值为 ’Sarah’; DELETE FROM employees 的记录。 另一个使用预处理语句的好处是:如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度。 如果你想问插入该如何做,请看下面这个例子(使用PDO):$preparedStatement = $db-&prepare('INSERT INTO table (column) VALUES (:column)');
$preparedStatement-&execute(array('column' =& $unsafeValue));复制代码
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
论坛徽章:51
使用预处理是不错的选择。同时使用一些开源的ADO框架,框架会帮你处理这些问题。}

我要回帖

更多关于 php防止sql注入的方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信