故事A段:发现整站SQL对外输出:

什么是SQL注入

SQL注入攻击(SQL
Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞。可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作,甚至有可能获取数据库乃至系统用户最高权限。

而造成SQL注入的原因是因为程序没有有效过滤用户的输入,使攻击者成功的向服务器提交恶意的SQL查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码。

 

SQL注入实例

很多Web开发者没有意识到SQL查询是可以被篡改的,从而把SQL查询当作可信任的命令。殊不知,SQL查询是可以绕开访问控制,从而绕过身份验证和权限检查的。更有甚者,有可能通过SQL查询去运行主机系统级的命令。

下面将通过一些真实的例子来详细讲解SQL注入的方式。

<form action=”/login” method=”POST”>

<p>Username:<input type=”text” name=”username”
/></p>

<p>Password:<input type=”password” name=”password”
/></p>

<p><input type=”submit” value=”登陆” /></p>

</form>

我们的处理里面的SQL可能是这样的:

username:=r.Form.Get(“username”)

password:=r.Form.Get(“password”)

sql:=”SELECT * FROM user WHERE username='”+username+”‘ AND
password='”+password+”‘”

如果用户的输入的用户名如下,密码任意:

myuser’ or ‘foo’ = ‘foo’ —

那么我们的SQL变成了如下所示:

SELECT * FROM user WHERE username=’myuser’ or ‘foo’==’foo’ –” AND
password=’xxx’

在SQL里面–是注释标记,所以查询语句会在此中断。这就让攻击者在不知道任何合法用户名和密码的情况下成功登录了。

对于MSSQL还有更加危险的一种SQL注入,就是控制系统,下面这个可怕的例子将演示如何在某些版本的MSSQL数据库上执行系统命令。

sql:=”SELECT * FROM products WHERE name LIKE ‘%”+prod+”%'”

Db.Exec(sql)

如果攻击提交a%’ exec master..xp_cmdshell ‘net user test testpass /ADD’
–作为变量 prod的值,那么sql将会变成

sql:=”SELECT * FROM products WHERE name LIKE ‘%a%’ exec
master..xp_cmdshell ‘net user test testpass /ADD’–%'”

有个朋友的网站,由于是外包项目,深圳某公司开发的,某天我帮他检测了一下网站相关情况。

如何预防SQL注入

也许你会说攻击者要知道数据库结构的信息才能实施SQL注入攻击。确实如此,但没人能保证攻击者一定拿不到这些信息,一旦他们拿到了,数据库就存在泄露的危险。如果你在用开放源代码的软件包来访问数据库,比如论坛程序,攻击者就很容易得到相关的代码。如果这些代码设计不良的话,风险就更大了。目前Discuz、phpwind、phpcms等这些流行的开源程序都有被SQL注入攻击的先例。

这些攻击总是发生在安全性不高的代码上。所以,永远不要信任外界输入的数据,特别是来自于用户的数据,包括选择框、表单隐藏域和
cookie。就如上面的第一个例子那样,就算是正常的查询也有可能造成灾难。

SQL注入攻击的危害这么大,那么该如何来防治呢?下面这些建议或许对防治SQL注入有一定的帮助。

严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害。

检查输入的数据是否具有所期望的数据格式,严格限制变量的类型,例如使用regexp包进行一些匹配处理,或者使用strconv包对字符串转化成其他基本类型的数据进行判断。

对进入数据库的特殊字符('”尖括号&*;等)进行转义处理,或编码转换。Go
的text/template包里面的HTMLEscapeString函数可以对字符串进行转义处理。

所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中,即不要直接拼接SQL语句。例如使用database/sql里面的查询函数Prepare和Query,或者Exec(query
string, args …interface{})。

在应用发布之前建议使用专业的SQL注入检测工具进行检测,以及时修补被发现的SQL注入漏洞。网上有很多这方面的开源工具,例如sqlmap、SQLninja等。

避免网站打印出SQL错误信息,比如类型错误、字段不匹配等,把代码里的SQL语句暴露出来,以防止攻击者利用这些错误信息进行SQL注入。

我查看了页面源代码,发现了个惊人的事情,竟然整站打印SQL到Html里,着实吓我一跳:

总结

通过上面的示例我们可以知道,SQL注入是危害相当大的安全漏洞。所以对于我们平常编写的Web应用,应该对于每一个小细节都要非常重视,细节决定命运,生活如此,编写Web应用也是这样。

PS:2年前秋色园系列文章有分享一文是整站SQL打印用于分析网站性能,不过也只是本地优化调试,而服务器上也采用某特殊条件才打印。

于是把这赤祼祼的对外公开的SQL问题反映了过去,之后算是取消了。 

AG真人娱乐 1

故事B段:错误异常打印了SQL,诱人: 

 

过了些许天,我又抽空看了看:

原始路径为:

AG真人娱乐 2 

直接打印SQL?这不是引诱人犯罪么?好吧,当时被诱了一下,花了小半天折腾了一下。

 

故事C段:发现有简单的SQL关键字过滤: 

 

随意加了个“and“条件,发现有过滤一些关键字: 

 AG真人娱乐 3 

然后多次检测,发现过滤了:and select,update,delete等关键字。

 

故事D段:发现可以执行自定义语句,但SQL账号似乎没有SA权限或者是关闭了xp_cmdshell服务: 

于是我组了一条truncate table xxx,当然,这是个不存在的表名: 

 

 

试了下,执行完成,没报啥提示,太恐怖了。

既然可以执行自定义语句,那执行下提权语句看看:

 master..xp_cmdshell ‘net user test 1234
 master..xp_cmdshell ‘net localgroup administrators test /add

AG真人娱乐, 

发现没啥提示,但是账号不起效果,所以估计sql的账号没有sa权限可以调用xp_cmdshell,另外这里,由于–符号被用来分隔字符串,所以不起作用。

故事E段:发现登陆有明显的SQL漏洞: 

 

过了点时间,我就不折腾了,我打算注册个账号看看其它情况。 


到了登陆页,发现注册还要绑定手机号,我就不注册了,于是在登陆里随手弄了一个常见的a’
or 1=1–

AG真人娱乐 4

竟然报密码错误,吓我一跳,说明用户名注入了,只是密码那关错误。 

 

故事F段:发现验证码竟然在Cookie里: 

 

通过拦截请求信息,发现更奇葩的事:

AG真人娱乐 5