设为首页 收藏本站
查看: 1104|回复: 0

[经验分享] Web安全之SQL注入***技巧与防范

[复制链接]

尚未签到

发表于 2018-10-21 09:43:19 | 显示全部楼层 |阅读模式
Web安全之SQL注入***技巧与防范
在Web1.0时代,人们更多是关注服务器端动态脚本语言的安全问题,比如将一个可执行脚本(俗称Webshell)通过脚本语言的漏洞上传到服务器上,从而获得服务器权限。在Web发展初期,随着动态脚本语言的发展和普及,以及早期工程师对安全问题认知不足导致很多”安全血案”的发生,至今仍然遗留下许多历史问题,a比如PHP语言至今仍然无法从语言本身杜绝「文件包含漏洞,只能依靠工程师良好的代码规范和安全意识。
  伴随着Web2.0、社交网络、微博等一系列新型互联网产品的兴起,基于Web环境的互联网应用越来越广泛,Web***的手段也越来越多样,Web安全史上的一个重要里程碑是大约1999年发现的SQL注入***,之后的XSS,CSRF等***手段愈发强大,Web***的思路也从服务端转向了客户端,转向了浏览器和用户。
  在安全领域,一般用帽子的颜色来比喻***的善与恶,白帽子是指那些工作在反***领域的技术专家,这个群体是”善”的的象征;而黑帽子则是指那些利用***技术造成破坏甚至谋取私利造成犯罪的群体,他们是”恶”的代表。
  “白帽子”和”黑帽子”是两个完全对立的群体。对于黑帽子而言,他们只要找到系统的一个切入点就可以达到***破坏的目的,而白帽子必须将自己系统所有可能被突破的地方都设防,以保证系统的安全运行。
  这看起来好像是不公平的,但是安全世界里的规则就是这样,可能我们的网站1000处都布防的很好,考虑的很周到,但是只要有一个地方疏忽了,***者就会利用这个点进行突破,让我们另外的1000处努力白费。
常见***方式
  一般说来,在Web安全领域,常见的***方式大概有以下几种:
  1、SQL注入***
  2、跨站脚本*** - XSS
  3、跨站伪造请求*** - CSRF
  4、文件上传漏洞***
  5、分布式拒绝服务*** - DDOS
  说个题外话,本来这篇文章一开始的标题叫做 「Web安全之常见***方法与防范」,我原本想把上面的这5种方法都全部写在一篇文章里,可是刚写完第一个SQL注入***的时候,就发现文章篇幅已经不短了,又很难再进行大幅度的精简,所以索性把Web安全分成一个系列,分多篇文章来呈现给大家,下面你看到的就是第一篇「Web安全之SQL注入***的技巧与防范」。
SQL注入常见***技巧
  SQL注入***是Web安全史上的一个重要里程碑,它从1999年首次进入人们的视线,至今已经有十几年的历史了,虽然我们现在已经有了很全面的防范对策,但是它的威力仍然不容小觑,SQL注入***至今仍然是Web安全领域中的一个重要组成部分。
  以PHP+MySQL为例,让我们以一个Web网站中最基本的用户系统来做实例演示,看看SQL注入究竟是怎么发生的。
  1、创建一个名为demo的数据库:
CREATE DATABASE  `demo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;  2、创建一个名为user的数据表,并插入1条演示数据:

CREATE TABLE  `demo`.`user` (  
`uid` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT  '用户uid',
  
`username` VARCHAR( 20 ) NOT NULL COMMENT  '用户名',
  
`password` VARCHAR( 32 ) NOT NULL COMMENT  '用户密码'
  
) ENGINE = INNODB;
  
INSERT INTO `demo`.`user` (`uid`, `username`, `password`) VALUES ('1', 'plhwin', MD5('123456'));
实例一
  通过传入username参数,在页面打印出这个会员的详细信息,编写 userinfo.php 程序代码:

  

  

  

  
  Web登录系统SQL注入实例
  

  

  
  登录帐号:
  登录密码:
  
  
  

  

  此时如果输入正确的用户名 plhwin 和密码 123456,执行的SQL语句为:
SELECT uid,username FROM user WHERE username='plhwin' AND password='e10adc3949ba59abbe56e057f20f883e'  上面语句没有任何问题,可以看到页面打印出了登录成功后的会员信息,但如果有捣蛋鬼输入的用户名为 plhwin' AND 1=1-- hack,密码随意输入,比如aaaaaa,那么拼接之后的SQL查询语句就变成了如下内容:
SELECT uid,username FROM user WHERE username='plhwin' AND 1=1-- hack' AND password='0b4e7a0e5fe84ad35fb5f95b9ceeac79'  执行上面的SQL语句,因为1=1是永远成立的条件,这意味着***只需要知道别人的会员名,无需知道密码就能顺利登录到系统。
如何确定SQL注入漏洞
  通过以上的实例,我们仍然还会有疑问:***并不知道我们程序代码的逻辑和SQL语句的写法,他是如何确定一个网站是否存在SQL注入漏洞呢?一般说来有以下2种途径:
1、错误提示
  如果目标Web网站开启了错误显示,***者就可以通过反复调整发送的参数、查看页面打印的错误信息,推测出Web网站使用的数据库和开发语言等重要信息。
2、盲注
  除非运维人员疏忽,否则大部分的Web运营网站应该都关闭了错误提示信息,此时***者一般会采用盲注的技巧来进行反复的尝试判断。 仍然以上面的数据表user为例,我们之前的查看会员详情页面的url地址为userinfo.php?username=plhwin,此时***分别访问userinfo.php?username=plhwin' AND 1=1-- hack和userinfo.php?username=plhwin' AND 1=2-- hack,如果前者访问能返回正常的信息而后者不能,就基本可以判断此网站存在SQL注入漏洞,因为后者的1=2这个表达式永远不成立,所以即使username传入了正确的参数也无法通过,由此可以推断这个页面存在SQL注入漏洞,并且可以通过username参数进行注入。
如何防御SQL注入
  对于服务器配置层面的防范,应该保证生产环境的Webserver是关闭错误信息的,比如PHP在生产环境的配置文件php.ini中的display_errors应该设置为Off,这样就关闭了错误提示,下面我们更多的从编码的角度来看看如何防范SQL注入。
  上面用两个实例分析了SQL注入***的技巧,可以看到,但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分,对于用户输入的内容或传递的参数,我们应该要时刻保持警惕,这是安全领域里的「外部数据不可信任」的原则,纵观Web安全领域的各种***方式,大多数都是因为开发者违反了这个原则而导致的,所以自然能想到的,就是从变量的检测、过滤、验证下手,确保变量是开发者所预想的。
1、检查变量数据类型和格式

  如果你的SQL语句是类似where>  比如,我们前面接受username参数例子中,我们的产品设计应该是在用户注册的一开始,就有一个用户名的规则,比如5-20个字符,只能由大小写字母、数字以及一些安全的符号组成,不包含特殊字符。此时我们应该有一个check_username的函数来进行统一的检查。不过,仍然有很多例外情况并不能应用到这一准则,比如文章发布系统,评论系统等必须要允许用户提交任意字符串的场景,这就需要采用过滤等其他方案了。
2、过滤特殊符号
  对于无法确定固定格式的变量,一定要进行特殊符号过滤或转义处理。以PHP为例,通常是采用addslashes函数,它会在指定的预定义字符前添加反斜杠转义,这些预定义的字符是:单引号 (') 双引号 (") 反斜杠 (\) NULL。
  来看2条SQL语句:
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;  
$uid = addslashes(uid);
  
$sql = "SELECT uid,username FROM user WHERE uid='{$uid}'";
  以及
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;  
$uid = addslashes(uid);
  
$sql = "SELECT uid,username FROM user WHERE uid={$uid}";
  对于PHP程序+MySQL构架的程序,在动态的SQL语句中,使用单引号把变量包含起来配合addslashes函数是应对SQL注入***的有效手段,但这做的还不够,像上面的2条SQL语句,根据「检查数据类型」的原则,uid都应该经过intval函数格式为int型,这样不仅能有效避免第二条语句的SQL注入漏洞,还能使得程序看起来更自然,尤其是在NoSQL(如MongoDB)中,变量类型一定要与字段类型相匹配才可以。上面两个查询语句都经过了php的addslashes函数过滤转义,但在安全性上却大不相同,在MySQL中,对于int类型字段的条件查询,上面个语句的查询效果完全一样,由于第一句SQL的变量被单引号包含起来,SQL注入的时候,***面临的首要问题是必须要先闭合前面的单引号,这样才能使后面的语句作为SQL执行,并且还要注释掉原SQL语句中的后面的单引号,这样才可以成功注入,由于代码里使用了addslashes函数,***的***会无从下手,但第二句没有用引号包含变量,那***也不用考虑去闭合、注释,所以即便同样采用addslashes转义,也还是存在SQL***漏洞。
  从上面可以看出,第二个SQL语句是有漏洞的,不过由于使用了addslashes函数,你会发现***的***语句也存在不能使用特殊符号的条件限制,类似where username='plhwin'这样的***语句是没法执行的,但是***可以将字符串转为16进制编码数据或使用char函数进行转化,同样能达到相同的目的,如果对这部分内容感兴趣,可以点击这里查看。而且由于SQL保留关键字,如「HAVING」、「ORDER BY」的存在,即使是基于黑白名单的过滤方法仍然会有或多或少问题,那么是否还有其他方法来防御SQL注入呢?
3、绑定变量,使用预编译语句
  MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法,我们这里仍然以PHP为例,编写userinfo2.php代码:

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-624347-1-1.html 上篇帖子: SQL MAP 使用-经典6步法 下篇帖子: HTML5本地存储——Web SQL Database
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表