而SQL注入产生的主要原因也就是用户所提交的数据被当作代码来执行,请看下面这个获取文章内容例子(省略了部分代码): <?php $id = $_GET["ID"]; $sql = ‘SELECT * FROM article WHERE ID=’.$id; $mysqli->multi_query($sql); ?> 注意看,当我们要查看这个某个文章的时候,就提交这个文章的ID(一般的网站对于这种请求都是使用GET请求的,即用户可轻易在URL上修改请求的内容。如果是POST请求的,可通过抓包改包或是修改网页内容进行修改请求),就会把SQL语句中的$ID变量赋值为当前用户提交的数据进行SQL查询。 例如:当用户查看一篇ID为3的文章,那么此时的URL为
http://www.xxx.com/article.php?ID=3;
此时服务器$_GET["ID"]所得的值就是3了。在经过SQL语句拼接之后,所得的SQL语句就变为
SELECT * FROM article WHERE ID=3;
当然,这个是程序员所期望的实现的,但黑阔们看到的不是功能,而是漏洞!!
因为存在SQL注入漏洞的关键条件是SQL语句拼接了用户能控制的变量,这个条件,在以上的例子中就符合了,所以黑阔完全可以提交恶意SQL语句与原请求的内容拼接成一个程序员完全没想到的恶意SQL语句提交给数据库引擎去执行。。。
假设黑阔在原本的URL后增加如下的语句:
;DROP TABLE admin– 即原本的URL变为: http://www.xxx.com/article.php?ID=3;DROP TABLE admin– 注意,$_GET["ID"]此事的值就不再是3了,而是3;DROP TABLE admin–了。那拼接后的SQL语句会是怎样的呢?!那就是: SELECT * FROM article WHERE ID=3;DROP TABLE admin–
好了,那我们来分析一下这个SQL语句。。。
首先,会执行:SELECT * FROM article WHERE ID=3,这是一个正常的SQL语句吧?!,是查询文章的内容的。 问题是,执行完这个之后,会再执行:DROP TABLE admin 而这个就是一个恶意的SQL语句了,它的作用是删除admin这个表,这样就导致数据库的数据丢失了,是一个非常危险的语句,同样的,我也可以删除article这个表,导致此网站所有的文章丢失!!很邪恶吧?!!当然,现在用multi_query函数的也比较少了,大多数都是用mysql_query函数,但别以为这样就可以防止SQL注入,因为提交的数据还是被拼接到了SQL语句中,只要构造好恶意的SQL语句,进行SQL注入也是轻而易举的。例如:在原本URL后加入 order by X(X是数字),就可以猜字段数,另外还可以加Union语句也可以做到语句的拼接进行攻击(需要SQL引擎版本的支持,Access数据库不支持),具体的一些攻击技巧,大家可以Google或百度一下,这方面的资料很多,我也没必要展开讲。。。 这也是一个典型的SQL注入的例子,但是现实中,有一大部分小白程序员都会写出这样明显的漏洞代码!!(注意这个语句后面的–,这是MYSQL语句中的注释,用于注释掉后面的内容,避免语句执行错误,因为黑阔一般情况下是不能准确的知道你的SQL语句的结构的)
但是一般的黑阔是不会做这些的,因为做这些对他们自己没有任何益处,他们大部分的目的不是删除你网站的数据,而是要拿到这个网站的shell甚至是服务器权限。所以,他们通常会利用SQL注入去构造恶意语句来获取WEB管理员的后台帐号和密码,然后去登陆后台,进行进一步的渗透(如果数据库用户的权限足够高,黑阔可以直接获取系统权限),这里就不扩展了,有兴趣的童鞋可以Google或百度一下,这方面的资料也是很多的,咱们论坛也有不少。。。
再来看一个很经典的SQL注入例子,那就是万能密码。或许有些人会觉得,万能密码的问题怎么和SQL注入扯一起了呢?!事实上,出现万能密码这种漏洞,本质就是SQL注入,这在 代码注入(番外篇)上已经总结过了,我就不再总结了,直接复制过来吧。。。
看产生万能密码的漏洞代码:
$username = $_POST["username"]; $password = $_POST["password"]; $result = mysql_query(“SELECT * FROM Users where UserName=’$username’ and PassWord=’$password’”); if(mysql_num_rows( $result ) > 0) { echo ‘<script>alert(“login is true!”);window.location = “index.php”</script>’; }
当黑阔提交 ‘or 1=1– (万能密码)的时候,提交的内容被注入到SQL语句中,这时候有几种情况,这里列举两个:
1. 当黑阔猜测用户名为admin,密码提交万能密码的时候,SQL语句变为:
SELECT * FROM Users where UserName=’admin’ and PassWord=”or 1=1–’
此时,where限定的是 UserName内容为admin,PassWord为空才进行返回(这两个限定条件用and连接),但是注意后面有一个or 1=1。
通过逻辑的处理,我们知道这个限定条件的意思是: 当UserName为admin和PassWord为空或者 1=1时 就进行返回查询信息
所以关键就是or这个逻辑,导致前面的限定都行为虚设。
至于or 1=1后面–,在SQL语句中,–为注释,也就是注释掉最后的’,避免执行语句错误
最后返回给 $result变量的是Users表的内容,然后就进行判断$result的数组是否为零,如果大于零,则认为是登陆成功
因为Users表中已经有用户了,所以返回的数组肯定不为空,所以肯定可以登陆,代码如下: if(mysql_num_rows( $result ) > 0)www.myhack58.com { echo ‘<script>alert(“login is true!”);window.location = “index.php”</script>’; } 最后就登陆成功的~
2. 当黑阔提交用户名和密码都为万能密码(’or 1=1–)的时候与1中类似,SQL语句变为如下:
SELECT * FROM Users where UserName=”or 1=1–’ and PassWord=”or 1=1–’ 与1中不同的是,–符号在UserName中就出现了,所以后面的语句已经被忽略了
SQL语句的逻辑变为: 当UserName为空或者 1=1时 就进行返回查询信息 然后与1中一样,返回了Users表中的内容给$result变量,再进行判断,然后就登陆成功了。。。
这里讲了两个SQL注入的例子,或许你以为SQL注入只存在于WEB端,对服务器没有直接的影响,但如果你这样想,那就错了!! 如果权限处理不当,一个SQL注入点就可以直接导出Shell,甚至是在服务器上执行任意命令!! 而据我所知,这些权限处理不当的服务器在互联网中也不占少数,所以希望各位程序猿、网站管理员等的引起足够的重视!!
好了,上面已经分析了SQL注入产生的原因,那下面就讲如何防御了!
SQL注入是一个发现于1998年,可以说是属于上世纪的漏洞了,但现在仍然有不少的网站存在着这样的漏洞,是这种漏洞很难防御吗?!!
答案是否定的,从理论上来说,只要防御方式恰当,SQL注入是可以杜绝的。而我们要防御SQL注入,要做的事就是先把所有可能存在SQL注入的地方都找出来,然后逐个修复,切忌不能因为觉得某个注入点难以挖掘而忽视不管,这样你就轻视了黑阔了!一旦这个注入点被挖掘,你之前做的所有工作都可以说是白费了,这也是平常我们所说的“木桶原理”。
|