W7 G: E9 u3 d9 q
SQL注入攻击(SQL Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞 可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作, 甚至有可能获取数据库乃至系统用户最高权限。
. ^1 i$ a. k& d" U" U, j 而造成SQL注入的原因是因为程序没有有效过滤用户的输入,使攻击者成功的向服务器提交恶意的SQL查询代码, 程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变, 额外的执行了攻击者精心构造的恶意代码。 ) X# x( N& a6 A2 ]- R$ e; V
SQL注入实例很多Web开发者没有意识到SQL查询是可以被篡改的,从而把SQL查询当作可信任的命令 殊不知,SQL查询是可以绕开访问控制,从而绕过身份验证和权限检查的更有甚者,有可能通过SQL查询去运行主机系统级的命令。
3 h7 N4 Y4 r+ q7 L- w' B 下面将通过一些真实的例子来详细讲解SQL注入的方式考虑以下简单的登录表单:
6 Z: X8 Q4 _ z. o7 A ~0 T: J# P( M- {' G+ V) Z5 H0 i& o
+ J7 |( U& y( u G Username:
" Z5 D3 u, H- ]
2 m9 T* f$ E; f* j+ H: { Password:
$ s1 _) W5 v/ \7 x' q% V8 n& N/ D7 z+ q- E. {
( E. _; o# M* W$ ?) l$ p4 F- d
6 K- \2 Z$ d$ E. ^1 f$ z0 f ?( r 。 我们的处理里面的SQL可能是这样的:String username = request.get("username");; U9 q4 f# L$ X' Q4 I/ p6 ^
String password = request.get("password");. Q& L# R! }+ N& ~
String sql = "SELECT * FROM user WHERE username="+username+" AND password="+password+"";" x Z! v' v! K" A, p; y
. r7 m& e, W$ Q1 ~9 Q6 i5 ]
如果用户的输入的用户名如下,密码任意:myuser or foo = foo --
S0 }3 h; S+ R0 x% m# R" c0 ^+ p 那么我们的SQL变成了如下所示:SELECT * FROM user WHERE username=myuser or foo = foo -- AND password=xxx5 `4 v) r2 A; I3 r' k" a: Q2 D3 B
- h. q5 H. ?. w! `" }2 C
在SQL里面–是注释标记,所以查询语句会在此中断这就让攻击者在不知道任何合法用户名和密码的情况下成功登录了对于MSSQL还有更加危险的一种SQL注入,就是控制系统, 下面这个可怕的例子将演示如何在某些版本的MSSQL数据库上执行系统命令:。 ' }# f, M: Y' {: A0 B& u
sql:="SELECT * FROM products WHERE name LIKE %"+prod+"%"6 l: p1 f' x1 `5 X* Z9 B0 q: R
Db.Exec(sql)# O% |( j: o( M
如果攻击提交 a% exec master..xp_cmdshell net user test testpass /ADD -- 作为变量 prod的值,那么sql将会变成
! x# x- ^+ ]$ Z' u- F! @ sql:="SELECT * FROM products WHERE name LIKE %a% exec master..xp_cmdshell net user test testpass /ADD--%"! m ^) p4 C, {) R# h: H8 T7 t
1 M8 p T; C: o. v+ l& b MSSQL服务器会执行这条SQL语句,包括它后面那个用于向系统添加新用户的命令 如果这个程序是以sa运行而 MSSQLSERVER服务又有足够的权限的话,攻击者就可以获得一个系统帐号来访问主机了对其他数据库也有类似的攻击。
2 S) b* d( ^: d 如何预防SQL注入永远不要信任外界输入的数据,特别是来自于用户的数据,包括选择框、表单隐藏域和 cookie 就如上面的第一个例子那样,就算是正常的查询也有可能造成灾难下面这些建议或许对防治SQL注入有一定的帮助:。
) \$ y9 o# y1 e- o% L) m- t# H 严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害检查输入的数据是否具有所期望的数据格式,严格限制变量的类型,例如使用regexp包进行一些匹配处理, 或者使用strconv包对字符串转化成其他基本类型的数据进行判断。 8 s* c9 W. c) g
对进入数据库的特殊字符(’”\尖括号&*;等)进行转义处理,或编码转换所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中, 比如Java中的PrepareStatement。
% \7 i) S ^9 T+ }3 N 在应用发布之前建议使用专业的SQL注入检测工具进行检测, 以及时修补被发现的SQL注入漏洞网上有很多这方面的开源工具,例如sqlmap、SQLninja等避免网站打印出SQL错误信息,比如类型错误、字段不匹配等,把代码里的SQL语句暴露出来,以防止攻击者利用这些错误信息进行SQL注入。
% ^: p9 m# g- q6 G" u+ { 总结SQL注入是危害相当大的安全漏洞。所以对于我们平常编写的Web应用,应该对于每一个小细节都要非常重视。
1 v8 q( b7 `3 _' U# m9 [9 L, {: p9 b! d
$ p- ~* j+ M$ m: J$ d8 x% [, ^4 d: o! I* W6 G& @" s5 u. w1 Y8 a
" q# D; h2 R @% J
+ q6 {6 f3 F% W4 K/ S
|