0x00 简述
之前manning在调漏洞的时候,突然发现正常登陆不上去了,当时帮忙跟了下phpcms的登陆流程。之后感觉这个流程貌似有些问题,就仔细看了下,没想到真是一个0day~~
0x01 漏洞原理
我们先直接看这个漏洞最根源的地方,phpsso/index.php文件所有的操作都存在严重的注入问题,这个类文件的构造函数最先调用它的父构造函数,通过auth_key来解析POST传入的data内容,解析后data中的内容会作为注册、登陆、删除用户等操作的内容依据,而这些操作都会将这些数据作为数据库查询语句使用。这个问题其实在XXX的《PHPCMS V9 最新版本配置文件未授权访问读取》中已经体现出来了,不过他仅仅只是分析了信息泄露的问题,而忽略的他利用所使用的注入问题。
我们以phpsso的login流程为例来看这个问题,先看phpsso的解析数据部分的代码:if(isset($_POST['appid'])) {
$this->appid = intval($_POST['appid']);
} else {
exit('0');
}
if(isset($_POST['data'])) {
parse_str(sys_auth($_POST['data'], 'DECODE', $this->applist[$this->appid]['authkey']), $this->data);
if(empty($this->data) || !is_array($this->data)) {
exit('0');
在auth_key解码之后使用parse_str解析成数组格式,这段代码如果在php5.3之前的情况下是没有问题的,因为默认情况下parse_str会启动gpc机制对特殊字符进行转义。但是在php5.3之后gpc机制默认就关闭掉了,这就导致如果解析出来的内容如果带有单引号这类个特殊字符,就原封不动的放到的变量中,这导致了注入的风险。下面我们简单来看一下login行为的代码:public function login() {
$this->password = isset($this->data['password']) ? $this->data['password'] : '';
$this->email = isset($this->data['email']) ? $this->data['email'] : '';
if($this->email) {
$userinfo = $this->db->get_one(array('email'=>$this->email));
} else {
$userinfo = $this->db->get_one(array('use