seacms v9.92变量覆盖导致越权
漏洞详情
seacms v9.92 及以前版本均存在全局的变量覆盖漏洞,在common.php文件中未对注册的全局变量做完整的安全检查。这里参考:https://xz.aliyun.com/t/6192和https://www.freebuf.com/articles/web/210902.html 对变量覆盖实现越权操作,来学习代码审计,文章使用的是v9.92版本。
漏洞审计分析
在披露这处变量覆盖导致越权的漏洞之前,其实官方就对这里注册变量加强了安全检查。v9.92版本这里漏掉了 _SESSION、_FILES两类。
在common.php中,先在_RunMagicQuotes将用户提交的参数及其值注册为变量和变量值
然后提交到foreach函数中检查,过滤掉一些非法类型的变量。在v9.92版本仅仅是漏掉了SESSION、FILES。而在之前的版本中就只过滤了cfg、GLOBALS
v9.92
v9.2
我这里没找到V9.92的源码,以V9.2版本演示了
common.php文件有很多页面都包含了,其中的注册全局变量的功能可以说非常常用,加上安全过滤时漏掉SESSION类的变量,只要找到使用 session_start 并包含 include/common.php 文件的地方,就可以覆盖 session
找到cms对管理员登录验证的地方
这里会对两个参数进行校验,有趣的是用了一个0R,我们只要满足一个条件就可以了
$_SESSION[‘hashstr’]的值是用管理员密码、数据库名和密码在采用MD5加密形成的,这个不好猜(我要是知道就直接登录了,还越权干嘛)
那就只剩下$cuserLogin->getUserID(),跟进这个函数
这里只要覆盖 ** S E S S I O N [ ′ s e a a d m i n i d ′ ] ∗ ∗ 就行了。先注册一个普通用户,抓到登录包修改 ∗ ∗ _SESSION['sea_admin_id']**就行了。先注册一个普通用户,抓到登录包修改 ** SESSION[′seaadminid′]∗∗就行了。先注册一个普通用户,抓到登录包修改∗∗_SESSION[‘sea_admin_id’]**值为 1
注意 _SESSION[sea_ckstr] 为小写验证码(必需项)
成功登录
但登录后权限不如管理员权限大,归属于网站编辑。接着看,找找原因
发现一处鉴权操作
跟进getUserRank函数
和userid差不多,这里还得覆盖用户组id
poc中还得添加一个参数
POST /seacmsv9.2/login.php HTTP/1.1
············
dopost=login&userid=test&pwd=test&validate=TVND&_SESSION[sea_admin_id]=1&_SESSION[sea_group_id]=1&_SESSION[sea_ckstr]=tvnd
成功越权为管理员
接着分析"FILES"类的变量覆盖
在common.php中发现,如果存在$_FILES类的变量,就会包含uploadsafe.inc.php
跟进uploadsafe.inc.php
这里又发现一处变量覆盖,而且这里没有对$key
的值做限制,但要注意这里的if判断。所以如果我们需要覆盖$SESSION['seaadminid']
,需要在请求中同时添加对应的其他三个参数,如下图所示,请求中提交如下五个参数可以覆盖session中的seaadminid、seagroupid、以及sea_ckstr(登陆需要使用到的验证码)
_FILES[_SESSION][size]=1&_FILES[_SESSION][tmp_name][sea_admin_id]=1&_FILES[_SESSION][tmp_name][sea_group_id]=1&_FILES[_SESSION][tmp_name][sea_ckstr]=验证码小写&_FILES[_SESSION][type]=img&_FILES[_SESSION][name]=111.jpg
成功越权
两种方式其实原理差不多都是覆盖了用户id、用户组id和验证码三个参数。由于uploadsafe.inc.php中可变变量($$key)引起的变量覆盖
Js3suOI-1679561750065)]
两种方式其实原理差不多都是覆盖了用户id、用户组id和验证码三个参数。由于uploadsafe.inc.php中可变变量($$key)引起的变量覆盖
_FILES[_SESSION][tmp_name][sea_admin_id]=1
等价于_SESSION[sea_admin_id]=1