文件包含-综合案例分析
案例一、日志包含
1、信息采集
进入网站首页
通过插件知道Web服务器等信息
常规的端口扫描和目录扫描
8888端口是一个登陆界面
21端口是FTP控制连接端口,有nmap扫一下发现有一个vsftpd 3.0.3,
不是很好利用,就暂时先不考虑了
dirb是一个基于字典的web目录扫描工具,查找现有的(和/或隐藏的)Web对象,通过对Web服务器发起基于字典的攻击并分析响应的数据。 采用递归的方式来获取更多的目录,它还支持代理和http认证限制访问的网站,是在信息收集阶段获取目标信息常用工具手段
有时候御剑扫不出来就用dirb命令试一下,字典可能多一些
进入目录,可以看到有一个文件夹,进入文件夹,每个都点进去看看,源代码啥的
发现phpinfo页面
查看源码发现包含点
2、文件包含
nginx服务器默认日志是放在/var/log/nginx/access.log
,试一试能不能包含,能看到日志信息,那么现在就是要把马写入日志中
在UA头下入就行了
在8888端口登陆界面的UA头写入马,用蚁剑连接
案例二、文件包含配合文件上传
1、信息采集
还是一样的流程,指纹、端口、路径
用PHP写的就把字典选上
用postjson得到的端口,最好用nmap验证一下
进入扫出来的路径看看,可以看到index.php的源码很奇怪,一般GET请求都是?page=login.php
或者?page=login.html
,这个地方就很像包含点了,我们可以测测这里是不是包含点
用php://filter
伪协议试一下,接下来就是把我们扫出来的PHP都审计一下了
2、代码审计
我们需要重点关注的是config.php
和upload.php
这两个文件
在config.php中一般放数据库信息,我们前面做信息采集的时候3306端口也是开放的,在login.php中对密码进行base64_encode
于是我们得到了用户名和密码
kent JWzXuBJJNy
在upload.php中是白名单过滤,检测了图片文件mime类型,白名单不好绕过,那么就先上传一个带马的JPG文件,再用利用include()函数进行文件包含
在index.php找到include()
函数,include("lang/".$_COOKIE['lang'])
index.php
<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>综合测试</title>
</head>
<body>
<center>
<img src="images/wangdun.png"><br />
[ <a href="/">首页</a> ] [ <a href="?page=login">登录</a> ] [ <a href="?page=upload">上传</a> ]
<hr/><br/>
<?php
if (isset($_GET['page']))
{
include($_GET['page'].".php");
}
else
{
echo "Use this server to upload and share image files inside the intranet";
}
?>
</center>
</body>
</html>
config.php
<?php
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>
upload.php
<?php
session_start();
if (!isset($_SESSION['user'])) {
die('你没有登录.'); }
?>
<html>
<body>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='file' id='file' />
<input type='submit' name='submit' value='Upload'/>
</form>
</body>
</html>
<?php
if(isset($_POST['submit'])) {
if ($_FILES['file']['error'] <= 0) {
$filename = $_FILES['file']['name'];
$filetype = $_FILES['file']['type'];
$uploaddir = 'upload/';
$file_ext = strrchr($filename, '.');
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
die('Not allowed extension, please upload images only.');
}
if(strpos($filetype,'image') === false) {
die('Error 001');
}
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
die('Error 002');
}
if(substr_count($filetype, '/')>1){
die('Error 003');
}
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
echo "<img src=\"".$uploadfile."\"><br />";
} else {
die('Error 4');
}
}
}
?>
login.php
<?php
session_start();
require("config.php");
$mysqli = new mysqli($server, $username, $password, $database);
if (isset($_POST['user']) and isset($_POST['pass']))
{
$luser = $_POST['user'];
$lpass = base64_encode($_POST['pass']);
$stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?");
$stmt->bind_param('ss', $luser, $lpass);
$stmt->execute();
$stmt->store_Result();
if ($stmt->num_rows == 1)
{
$_SESSION['user'] = $luser;
header('Location: ?page=upload');
}
else
{
echo "Login failed.";
}
}
else
{
?>
<form action="" method="POST">
<label>用户名: </label><input id="user" type="test" name="user"><br />
<label>密 码: </label><input id="pass" type="password" name="pass"><br />
<input type="submit" name="submit" value="Login">
</form>
<?php
}
3、文件上传
登陆后有文件上传功能
成功上传,文件路径也告诉我们了
4、文件包含
前面代码设计:在index.php找到include()
函数,include("lang/".$_COOKIE['lang'])
前面目录扫描的时候结果是:upload目录和index.php是同一级,所以在对应JPG文件的路径应该是lang/../upload/ddb9741b3b0f77687b4b19123743c6eb.jpg
== upload/ddb9741b3b0f77687b4b19123743c6eb.jpg
验证结果