日常记录,仅供收藏,用时不慌。
0x01 漏洞描述
cookie是Web服务器返回给客户端的一段常用来标识用户身份或者认证情况的字符串,保存在客户端,浏览器下次请求时会自动带上这个标识,由于这个标识字符串可以被用户修改,所以存在安全风险。一般这块的认证安全问题都出在服务端直接取用cookie的数据而没有校验,其次是cookie加密数据存在可预测的情况。
0x02 审计要点
先看程序的登录功能代码,整个登录过程的业务逻辑有没有可以控制session值或者直接绕过密码验证的漏洞;另外关注程序验证是否为登录的代码,通俗的说是验证cookie的代码,是不是直接去取cookie里面的值,然后怎么去判断这个值来验证是否登录。
0x03 典型漏洞代码
Espcms任意用户登录分析
在文件/interface/memebermain.php的in_center()函数可以看到如下代码:
function in_center() {
if ($this->CON['mem_isucenter']) {
include_onceadmin_ROOT .'public/uc_client/client.php';
}
parent:start_pagetemplate();
parent:member_purview();
$lng = (admin_LNG == 'big5') ? $this->CON['is_lancode'] : admin_LNG;
$db_where = "userid=$this->ec_member_username_id AND username='$this-> ec_member_username' ";
$db_table1 =db_prefix .'member AS a';
$db_table2 =db_prefix .'member_value AS b';
$db_sql = "SELECT * FROM $db_table1 LEFT JOIN $db_table2 ON a.userid = b.userid WHERE a.userid = $this->ec_member_username_id ";
$rsMember = $this->db->fetch_first($db_sql);
$rsMember['rankname'] = $this->get_member_purview($rsMember['mcid'], 'rankname');
$userid = $this->ec_member_username_id; //获取userid
if (empty($userid)) {
exit('user err!');
}
$db_table =db_prefix ."order";
$db_where = " WHERE userid=$userid";
在代码中$userid=$this->ec_member_username_id;这行代码设置当前用户ID,随后根据这个$userid变量去直接操作这个id的用户数据,而这个$this->ec_member_username_id变量的值又是从哪来的呢?注意代码最开始的地方有调用parent:member_purview()函数,我们跟过去看看,在/public/class_connector.php文件的member_purview()函数,代码如下:
function
member_purview(
$userrank
=
false
,$url
=
null,
$upurl
=
false
){
$this
->
ec_member_username
=
$this
->
fun
->
eccode($this
->
fun
->
accept('ecisp_member_username','C'),'DECODE',db_pscode);
$user_info
=
explode('|',$this
->
fun
->
eccode($this
->
fun
->
accept('ecisp_member_info','C'),'DECODE',db_pscode));
//explode()把字符串打散为数组:
list
($this
->
ec_member_username_id,$this
->
ec_member_alias,$this
->
ec_member_integral,$this
->
ec_member_mcid,$this
->
ec_member_email,$this
->
ec_member_lastip,$this
->
ec_member_ipadd,$this
->
ec_member_useragent,$this
->
ec_member_adminclassurl)
=
$user_info;
可以看到list()函数中使用$user_info数组为$this->ec_member_username_id变量进行赋值,而$user_info数组是从cookie中解密出来的,关于这个算法的加密代码在/public可以看到l,代码如下:
function
eccode(
$string,$operation
=
'DECODE',$key
=
'@LFK24s224%@safS3s%1f%',$mcrype
=
true
){
$result
=
null
;
if
($operation
==
'ENCODE'){
for
($i
=
0;$i
<
strlen($string);$i
++
){
$char
=
substr($string,$i,1);
$keychar
=
substr($key,($i%strlen($key))
-
1,1);
$char
=
chr(ord($char)
+
ord($keychar));
$result
.=
$char;
}
$result
=
base64_encode($result);
$result
=
str_replace(array('+','/','='),
array
('-','_',''),$result);
}
elseif
($operation
==
'DECODE'){
$data
=
str_replace(array('-','_'),
array
('+','/'),$string);
$mod4
=
strlen($data)%4;
if
($mod4){
$data
.=
substr('====',$mod4);
}
$string
=
base64_decode($data);
for
($i
=
0;$i
<
strlen($string);$i
++
){
$char
=
substr($string,$i,1);
$keychar
=
substr($key,($i%strlen($key))
-
1,1);
$char
=
chr(ord($char)
-
ord($keychar));
$result
.=
$char;
$result
.=
$char;
}
}
return
$result;
}
这是一个可逆算法,这里就不再分析这个算法。
0x04 防御方案
先了解cookie会话认证的业务逻辑,严格限制输入的异常字符以及避免使用客户端提交上来的内容去直接进行操作。把cookie和session结合起来使用,不能从cookie中获取参数值然后进行操作。另外在设置session时,需要保证客户端不能操作敏感session参数。
特别需要注意的是敏感数据不要放到cookie中,目前还有不少应用会把账号和密码都直接放入到cookie中,cookie在浏览器端以及传输过程中都存在被窃取的可能性,如果程序限制了一个用户只能同时在一个IP上面登录,这时候即使别人拿到了你不带密码的cookie也会使用不了,但是如果cookie里面保存了用户名和密码,这时候攻击者就可以尝试用密码直接登录了。
原文始发于微信公众号(反入侵实验室):0基础入门代码审计-10 cookie会话认证
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论