数据库安全——SQL注入

不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动。在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一。

SQL注入定义

SQL注入(SQL injection),简称注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。

简单解释:SQL注入就是一种通过操作输入来修改后台SQL语句达到代码执行进行攻击目的的技术。

SQL注入实例

多语句执行注入

Get请求语句:

1
http://localhost/test/userinfo.php?username=plhwin

SQL语句:

1
SELECT uid,username FROM user WHERE username='plhwin'

如果用户Get请求改为:

1
http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack

SQL语句变为:

1
SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'

经过上面的SQL注入后,页面输出了所有表信息。

如果用户接着Get请求:

1
http://localhost/test/userinfo.php?username=plhwin';DROP TABLE user-- hack

整个user数据库表都消失了。

or方法注入一

Web登录表单:

1
2
3
4
5
<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>

后台处理逻辑:

1
2
3
username:=r.Form.Get("username")
password:=r.Form.Get("password")
sql:="SELECT * FROM user WHERE username='"+username+"' AND password='"+password+"'"

普通用户输入:

1
2
账户:myuser
密码:xxx

SQL语句:

1
SELECT * FROM user WHERE username='myuser' AND password='xxx'

如果用户输入:

1
2
账户:myuser' or 'foo' = 'foo' --
密码:xxx

SQL语句变为:

1
SELECT * FROM user WHERE username='myuser' or 'foo' = 'foo' --'' AND password='xxx'

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

or方法注入二

SQL语句:

1
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"

如果用户输入:

1
2
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";

SQL语句变为:

1
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"

上面的SQL语句相当于:

strSQL = “SELECT * FROM users;”

控制系统

某些版本MSSQL数据库系统命令:

1
2
sql:="SELECT * FROM products WHERE name LIKE '%"+prod+"%'"
Db.Exec(sql)

如果攻击者提交一下内容作为变量prod的值:

1
a%' exec master..xp_cmdshell 'net user test testpass /ADD' --

SQL语句变为:

1
SELECT * FROM products WHERE name LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--%'

MSSQL服务器会执行这条SQL语句,包括它后面那个用于向系统添加新用户的命令。如果这个程序是以sa运行而 MSSQLSERVER服务又有足够的权限的话,攻击者就可以获得一个系统帐号来访问主机了。

可能危害

  1. 数据表中的数据外泄,例如个人机密数据,账户数据,密码等。

  2. 数据结构被黑客探知,得以做进一步攻击(例如SELECT * FROM sys.tables)。

  3. 数据库服务器被攻击,系统管理员账户被窜改(例如ALTER LOGIN sa WITH PASSWORD=’xxxxxx’)。

  4. 获取系统较高权限后,有可能得以在网页加入恶意链接、恶意代码以及XSS等。

  5. 经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统(例如xp_cmdshell “net stop iisadmin”可停止服务器的IIS服务)。

  6. 破坏硬盘数据,瘫痪全系统(例如xp_cmdshell “FORMAT C:”)。

避免办法

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

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

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

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

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

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

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