当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-084701

漏洞标题:phpok sql注入一枚

相关厂商:phpok.com

漏洞作者: cbuteng

提交时间:2014-12-01 17:30

修复时间:2015-03-01 17:32

公开时间:2015-03-01 17:32

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-12-01: 细节已通知厂商并且等待厂商处理中
2014-12-01: 厂商已经确认,细节仅向厂商公开
2014-12-04: 细节向第三方安全合作伙伴开放
2015-01-25: 细节向核心白帽子及相关领域专家公开
2015-02-04: 细节向普通白帽子公开
2015-02-14: 细节向实习白帽子公开
2015-03-01: 细节向公众公开

简要描述:

phpok4.2.083,刚下的

详细说明:

1.safekey固定,导致加密函数可逆
2.使用固定的safekey加密后发起攻击请求,加密内容在代码中解密,绕过了过滤

/install/index.php中

$content = file_get_contents(ROOT."config.php");
//查找替换
$content = preg_replace('/\$config\["db"\]\["file"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["file"] = "'.$dbconfig['file'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["host"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["host"] = "'.$dbconfig['host'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["port"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["port"] = "'.$dbconfig['port'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["user"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["user"] = "'.$dbconfig['user'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["pass"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["pass"] = "'.$dbconfig['pass'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["data"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["data"] = "'.$dbconfig['data'].'";',$content);
$content = preg_replace('/\$config\["db"\]\["prefix"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["db"]["prefix"] = "'.$dbconfig['prefix'].'";',$content);
$tmpcode = str_rand(rand(10,20));
$content = preg_replace('/\$config\["spam_key"\]\s*=\s*[\'|"][a-zA-Z0-9\-\_]*[\'|"];/isU','$config["spam_key"] = "'.$tmpcode.'";',$content); /*问题所在*/
file_put_contents(ROOT."config.php",$content);


这段的功能是写入安装时的各个配置
注意tmpcode下面一行,正则表达式处/\$config\["spam_key"\]这里去匹配$config["spam_key"] =
然后替代成随机生成的spam_key
但是/config.php中是这样的

$config['db']['cache']['folder'] = ROOT.'data/cache/';
$config['db']['cache']['server'] = 'localhost';
$config['db']['cache']['port'] = 11211;
$config['db']['cache']['time'] = 86400; //Memcache限制不能超过30天,我们建议设置86400,一天
//安全密钥生成
//生成公钥时需配合此密钥进行验证
$config['spam_key'] = 'AdCFGHIjk42*$#@9dafd-0=';
?>


注意最后一行,$config['spam_key']这个是单引号,而安装时,正则匹配的双引号,造成匹配失败,后果是key就一直没有变过。固定的。
现在,漏洞触发在这里,$this->u_id 可控
/framework/api/usercp_control.php
问题出在这个文件的构造函数和avatar_f

class usercp_control extends phpok_control
{
private $u_id; //会员ID
private $u_name; //会员名字
private $is_client = false;//判断是否客户端
function __construct()
{
parent::control();
$token = $this->get('token');
if($token)
{
$info = $this->lib('token')->decode($token); /*无过滤*/
if(!$info || !$info['user_id'] || !$info['user_name'])
{
$this->json(P_Lang('您还没有登录,请先登录或注册'));
}
$this->u_id = $info['user_id']; 无过滤
$this->u_name = $info['user_name'];
$this->is_client = true;
}
else
{
if(!$_SESSION['user_id'])
{
$this->json(P_Lang('您还没有登录,请先登录或注册'));
}
$this->u_id = $_SESSION['user_id'];
$this->u_name = $_SESSION['user_name'];
}
}
//更新会员头像
function avatar_f()
{
$data = $this->get('data');
if(!$data)
{
$this->json(P_Lang('头像图片地址不能为空'));
}
$pInfo = pathinfo($data);
$fileType = strtolower($pInfo['extension']);
if(!$fileType || !in_array($fileType,array('jpg','gif','png','jpeg')))
{
$this->json(P_Lang('头像图片仅支持jpg,gif,png,jpeg'));
}
if(!file_exists($this->dir_root.$data))
{
$this->json(P_Lang('头像文件不存在'));
}
//更新会员头像
$this->model('user')->update_avatar($data,$this->u_id);
//非接口接入则更新相应的session信息
if(!$this->is_client)
{
$this->model('user')->update_session($this->u_id); /*$this->u_id 完全可控*/
}
$this->json(true);
}


$info = $this->lib('token')->decode($token);这里由于key固定,这个decode和encode完全是可逆的。
然后下面这里将decode后的字符串赋值给$this->u_id

$this->u_id = $info['user_id']; 无过滤
$this->u_name = $info['user_name'];
$this->is_client = true;


然后avatar_f中这里$this->u_id带入model层

if(!$this->is_client)
{
$this->model('user')->update_session($this->u_id); /*$this->u_id 完全可控*/
}


然后api的model在这里 /framework/model/api/user_model.php

//更新会员头像
function update_avatar($file,$uid)
{
$sql = "UPDATE ".$this->db->prefix."user SET avatar='".$file."' WHERE id='".$uid."'";
return $this->db->query($sql);
}


如上$this->u_id进来了就执行了

漏洞证明:

这是url调用规则
http://localhost/api.php?c=usercp&f=avatar&token=$sql_injection&data=logo.gif
详细见poc

修复方案:

1.改正则
2.建立编码规范,统一使用规范

版权声明:转载请注明来源 cbuteng@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:12

确认时间:2014-12-01 21:39

厂商回复:

重复了!这条漏洞在360平台那里有会员已提供了!将在12月10号前修正

最新状态:

暂无