数据库的表构造见图1。新闻表wp_news的内容见图2。用户表wp_user的内容见图3。
图1
图2

图3
本节的目标是通过HTTP的GET办法输入的id值,将本应查询新闻表的功能转变成查询admin(常日为管理员)的账号和密码(密码常日是hash值,这里为了演示变为明文this_is_the_admin_password)。管理员的账号和密码是一个网站系统最主要的凭据,入侵者可以通过它登录网站后台,从而掌握全体网站内容。
通过网页访问链接http://192.168.20.133/sql1.php?id=1,结果见图4。
图4
页面显示的内容与图2的新闻表wp_news中的第一行id为1的结果同等。事实上,PHP将GET方法传入的id=1与前面的SQL查询语句进行了拼接。原查询语句如下:
收到要求http://192.168.20.133/sql1.php?id=1的$_GET['id']被赋值为1,末了传给MySQL的查询语句如下:
我们直接在MySQL中查询也能得到相同的结果,见图5。
图5
现在互联网上绝大多数网站的内容是预先存储在数据库中,通过用户传入的id等参数,从数据库的数据中查询对应记录,再显示在浏览器中,如https://bbs.symbo1.com/t/topic/53中的“53”,见图6。
图6
下面演示通过用户输入的id参数进行SQL注入攻击的过程。
访问链接http://192.168.20.133/sql1.php?id=2,可以看到图7中显示了图2中id为2的记录,再访问链接http://192.168.20.133/sql1.php?id=3-1,可以看到页面仍显示id=2的记录,见图8。这个征象解释,MySQL对“3-1”表达式进行了打算并得到结果为2,然后查询了id=2的记录。
从数字运算这个特色行为可以判断该注入点为数字型注入,表现为输入点“$_GET['id']”附近没有引号包裹(从源码也可以证明这点),这时我们可以直接输入SQL查询语句来滋扰正常的查询(结果见图9):
图7 正常的查询链接
图8
图9
这个SQL语句的浸染是查询新闻表中id=1时对应行的title、content字段的数据,并且联合查询用户表中的user、pwd(即账号密码字段)的全部内容。
我们通过网页访问时应只输入id后的内容,即访问链接:http://192.168.20.133/sql1.php?id=1 union select user,pwd from wp_user。结果见图10,图中的“%20”是空格的URL编码。浏览器会自动将URI中的分外字符进行URL编码,做事器收到要求后会自动进行URL解码。
图10
然而图10中并未按预期显示用户和密码的内容。事实上,MySQL确实查询出了两行记录,但是PHP代码决定了该页面只显示一行记录,以是我们须要将账号密码的记录显示在查询结果的第一行。此时有多种办法,如可以连续在原有数据后面加上“limit 1,1”参数(显示查询结果的第2条记录,见图11)。