源码分析
1搜索关键字select发现mysql.class文件下有一个变函数里面有select 并且后面没有过滤
全局搜索一下发现在sms_check文件里调用了这个函数get_one
get_one('sms_checkcode',"`code`='$code' AND `posttime`>$posttime",'*',0,'id DESC');
if($r) {
exit('{"info":"验证通过","status":"y"}');
} else {
exit('{"info":"验证失败","status":"n"}');
通过$code api查看
get_one('sms_checkcode',"`code`='$code' AND `posttime`>$posttime",'*',0,'id DESC');
if($r) {
exit('{"info":"验证通过","status":"y"}');
} else {
exit('{"info":"验证失败","status":"n"}');
?>
通过$GLOBALS获取param的值,然后通过strip_tags过滤html标签
然后引入db类,再次对传入的值进行过滤,如果是数组则进入if,把括号 单引号这些过滤掉。不是则走else 过滤 %20 %27
?>
$val) {//foreach,每次循环中,当前单元的值被赋给$val
$val = str_replace("%20", '', $val);//str_replace,替换字符串中的一些字符(区分大小写)
$val = str_replace("%27", '', $val);
$val = str_replace("(", '', $val);
$val = str_replace(")", '', $val);
$val = str_replace("'", '', $val);
$sql .= $sql ? " AND `$key` = '$val' " : " `$key` = '$val' ";
}
return $sql;
} else {
$data = str_replace("%20", '', $data);
$data = str_replace("%27", '', $data);
return $data;
}
}
?>
出现漏洞的地方就在这个过滤上面,我们传入的值不是数组,所以不走if
而else只过滤了%20和%27,我们的传参会经过一url编码,但服务器也会解码一次,如果是二次编码else才会起过滤作用
coreframe\app\attachment\admin\index.php中存在dir方法
*/
public function dir()
{
$dir = isset($GLOBALS['dir']) && trim($GLOBALS['dir']) ? str_replace(array('..\\', '../', './', '.\\'), '', trim($GLOBALS['dir'])) : '';
$dir = str_ireplace(array('%2F', '//'), '/', $dir);
$lists = glob(ATTACHMENT_ROOT . $dir . '/' . '*');//glob该函数返回一个包含有匹配文件 / 目录的数组。如果出错返回 false
if (!empty($lists)) rsort($lists);//rsort对数组中的元素按字母进行降序排序:
$cur_dir = str_replace(array(WWW_ROOT, DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR), array('', DIRECTORY_SEPARATOR), ATTACHMENT_ROOT . $dir . '/');
include $this->template('dir', M);
}
分析逻辑发现,将../,./,.\,..\替换成空再添加/结尾,这里可以通过多写绕过
![](https://nc0.cdn.zkaq.cn/md/9250/db670ba073f79877ecb445a601ceff46_95358.png)
![](https://nc0.cdn.zkaq.cn/md/9250/a283af8986788c10b3085f38c77dd1f9_65398.png)
读到的文件也可以删除,找到del方法
```php
public function del()
{
$id = isset($GLOBALS['id']) ? $GLOBALS['id'] : '';
$url = isset($GLOBALS['url']) ? remove_xss($GLOBALS['url']) : '';
if (!$id && !$url) MSG(L('operation_failure'), HTTP_REFERER, 3000);
if ($id) {
if(!is_array($id)) {
$ids = array($id);
} else {
$ids = $id;
}
foreach($ids as $id) {
$where = array('id' => $id);
$att_info = $this->db->get_one('attachment', $where, 'usertimes,path');
if ($att_info['usertimes'] > 1) {
$this->db->update('attachment', 'usertimes = usertimes-1', $where);
}
else {
$this->my_unlink(ATTACHMENT_ROOT . $att_info['path']);
$this->db->delete('attachment', $where);
$this->db->delete('attachment_tag_index', array('att_id'=>$id));
}
}
MSG(L('delete success'), HTTP_REFERER, 1000);
}
else {
if (!$url) MSG('url del ' . L('operation_failure'), HTTP_REFERER, 3000);
$path = str_ireplace(ATTACHMENT_URL, '', $url);
if ($path) {
$where = array('path' => $path);
$att_info = $this->db->get_one('attachment', $where, 'usertimes,id');
if (empty($att_info)) {
$this->my_unlink(ATTACHMENT_ROOT . $path);
MSG(L('operation_success'), HTTP_REFERER, 3000);
}
if ($att_info['usertimes'] > 1) {
$this->db->update('attachment', 'usertimes = usertimes-1', array('id' => $att_info['id']));
}
else {
$this->my_unlink(ATTACHMENT_ROOT . $path);
$this->db->delete('attachment', array('id' => $att_info['id']));
MSG(L('operation_success'), HTTP_REFERER, 3000);
}
}
else {
MSG(L('operation_failure'), HTTP_REFERER, 3000);
}
}
}
全局搜索删除文件的函数unlink
然后发现这里调用了函数并赋给$path
$this->my_unlink(path:ATTACHMENT_ROOT . $path);
2.在del函数里找到了调用删除文件函数
$path = str_ireplace(ATTACHMENT_URL, ‘’, $url);
然后来分析调用的过程 调用删除的时候通过把$path和ATTACHMENT_ROOT 拼接
而ATTACHMENT_ROOT是前面定义的一个默认路径
path则是前面的$url 来的
在看前面的if 如果path有值则进入到if里面 然后经过的数据库的get_one查询操作 应该这里是要查出一个东西
但是因为我数据库是空的 则进入的是第一个if里面 哪怕是查出1条 也是可以的
这里也没有其他过滤
然后网上看url的来源
GLOBALS 那就可以直接通过传参的 前面也介绍了 id为空的话 也就进入到了else里面
到这里也就可以构造payload了
$path = str_ireplace(ATTACHMENT_URL, ‘’, $ur
通过url获取路径后,检测了ATTACHMENT_URL参数,替换为空
后面没有其他过滤,直接传入my_unlink:
private function my_unlink($path)
{
if(file_exists($path)) unlink($path);//file_exists,检查文件或者目录是否存在
//unlink,删除文件
}
先在目录下建一个1.txt文件
![](https://nc0.cdn.zkaq.cn/md/9250/d26bb59bef72fd715ff3bd440f7d301c_28589.png)
然后构造http://127.0.0.1/wuzhicms-wuzhicms-v4.1.0-0-g0a9144f/wuzhicms-wuzhicms-0a9144f/www/index.php?m=attachment&f=index&v=del&_su=wuzhicms&url=../1.txt
![](https://nc0.cdn.zkaq.cn/md/9250/ca38110296b2d4f6c845028afa9755df_16047.png)
![](https://nc0.cdn.zkaq.cn/md/9250/003c0e79fc7aba2e269d1c208824369d_79094.png)
在api/uc.php中
通过传参可以调用uc_note类的任意方法:
可以任意更改用户名和密码
在coreframe\app\core\libs\function\common.func.php中set_cache方法:
写入缓存后面没有过滤,跟进函数,看看哪里调用了set_cache
找到一处调用set_cache的地方
根据代码,可以直接获取setting写入缓存
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.
郎贤坤
发表于 2022-8-15
对于任意文件删除那一部分还是有些不理解,希望路过的师傅可以指点一下,这是文件删除的源码
评论列表
加载数据中...
君叹
发表于 2022-8-26
wuzhi漏洞,wuzhi不行,wuzi不行???
评论列表
加载数据中...
st2021
发表于 2022-9-10
请问uc.php的逻辑漏洞,楼主是怎么编写code的?我是从网上找了个大神写的一个脚本,编写所需传参然后生成code完成逻辑漏洞复现的。
评论列表
加载数据中...