JCS-Pro · Joomla 组件漏洞扫描器(Java 汉化重写版)
原版
JCS(Joomla Component Scanner)由 TheM4hd1 用 C# / WinForms 编写;
本项目是它的 Java 重写 + 汉化 + 功能扩展版:命令行、单 jar、零第三方依赖(JDK 17+)。
1. 它解决的问题
Joomla 站点的攻击面大量来自 第三方组件(com_xxx)。
一个组件是否安装、是否带已知漏洞,往往比核心版本更关键。
JCS-Pro 做的事情是:
- 确认目标是不是 Joomla(多特征指纹打分)
- 识别 Joomla 核心版本(6 种方法交叉验证)
- 探测组件是否存在(内置字典 + 页面自动发现,多线程)
- 按版本与组件匹配已知漏洞,并对可无授权验证的漏洞实际发请求验证
- 输出中文报告(HTML / JSON / TXT),可直接贴进漏洞报告
2. 相对原版的变化
| 维度 | 原版 JCS (C#) | JCS-Pro (Java) |
|---|---|---|
| 运行形态 | WinForms 图形界面,需 Visual Studio 编译 | Swing 图形界面 + 命令行,run.bat 双击可用(单 jar,仅 MySQL 驱动/JBCrypt 两个可选依赖) |
| 语言/界面 | 英文 | 全中文(帮助、进度、报告、漏洞描述) |
| 版本识别 | 4 种 | 6 种(新增 language/*/langmetadata.xml、administrator/language/...) |
| 组件库 | 需手工维护 database.txt |
内置 136 条 + 支持 data/components.csv 追加 |
| 组件发现 | 正则爬虫抓链接 | 首页/index.php 抓 option=com_xxx + 链接正则,且页面发现的组件强制探测 |
| 漏洞模块 | 仅列 ExploitDB 链接 | 12 个可执行 POC 模块(见第 5 节),能给出实锤回显 |
| 报告 | HTML | HTML + JSON + TXT,含请求数、指纹得分、证据片段 |
| 副作用控制 | 无 | 危险模块默认不执行,必须 --force-exp |
| 工程性 | 无重试、无代理鉴权细节 | 连接失败自动重试、随机 UA、代理、Cookie、限速、gzip |
3. 构建与运行
:: 构建(需要 JDK 17+,会自动找 JAVA_HOME / PATH / Program Files 下的 JDK)
build.bat
:: 查看全部漏洞模块
run.bat --list-exp
:: 扫描单个目标(默认 all:指纹 + 版本 + 组件 + 漏洞)
run.bat -u http://target.com
:: 批量扫描
run.bat -f targets.txt -t 30 --delay 80 -o reports
:: 只跑指定漏洞模块,并允许有副作用的利用
run.bat -u http://target.com -m exp --only cve-2023-23752-config,cve-2017-8917-com_fields
:: 导出组件字典,按需补充后放回 data/components.csv
run.bat --dump-db
产物:reports/jcs-<host>-<时间>.html|.json|.txt,reports/loot/ 存放泄露到的配置、用户列表等证据。
3.1 图形界面(默认启动)
run.bat :: 直接进图形界面
run.bat --gui :: 同上
run.bat --gui http://192.168.1.10 :: 带目标进图形界面
界面分四页:
| 页 | 内容 |
|---|---|
| 运行日志 | 实时日志(指纹得分、版本与来源、组件发现、漏洞命中、报告路径)、进度条、底部汇总 |
| 组件 | 命中的组件 / 说明 / HTTP 状态 / 判定证据;双击看完整证据 |
| 漏洞 | 等级(严重=红、高危=橙、中危=黄、信息=灰)、名称、CVE、是否命中、详情;未命中也会列出原因(版本不在区间 / 需 --force-exp / 未发现接口) |
| 数据库 / 后台 | 见 5.1:拿到数据库口令后一键建管理员并回显账号口令 |
要点:
- 顶部三个按钮:
开始扫描/停止(可中途取消,已发出的请求不回收)/打开报告目录; - 线程、超时、模式(全量 / 只识别版本 / 只扫组件 / 只跑漏洞)在第二行;
- 扫描过程中「数据库 / 后台」页会自动填入从
configuration.php~或 CVE-2023-23752 拿到的凭据; - 窗口尺寸按 DPI 换算成逻辑像素再居中,150% 缩放下不会被切到屏幕外。
3.2 参数说明
| 参数 | 说明 |
|---|---|
-u, --url <URL> |
目标地址,可重复或空格分隔多个 |
-f, --file <文件> |
从文件读目标,每行一个,# 注释 |
-m, --mode <all\|detect\|scan\|exp> |
默认 all |
--only <id,id> |
只跑指定漏洞模块 |
--force-exp |
允许执行有副作用的利用(注册管理员、上传、爆破等) |
--no-crawl |
不从页面抓取组件名 |
--strict-version |
只探测版本区间相符的组件(原版行为,请求更少、可能漏) |
-t, --threads <N> |
并发线程,默认 20 |
--delay <ms> |
每次请求前间隔,默认 0(绕过 WAF 限速时用) |
--timeout <ms> |
单请求超时,默认 12000 |
--proxy <host:port> |
HTTP 代理 |
--ua <UA> |
固定 User-Agent(默认随机) |
-H "K: V" |
追加请求头,可重复 |
--cookie <串> |
手工 Cookie |
-o, --out <目录> |
报告目录,默认 ./reports |
--list-exp |
列出全部漏洞模块后退出 |
--dump-db |
导出 data/components.csv 后退出 |
--no-color |
关闭 ANSI 彩色 |
5. 漏洞模块(12 个)
| ID | 等级 | 说明 | 影响版本 |
|---|---|---|---|
core-cve-map |
信息 | 核心版本 → 已知 CVE 映射表 | 全部 |
cve-2023-23752-config |
严重 | /api/index.php/v1/config/application?public=true 未授权读数据库账号口令、站点配置 |
4.0.0-4.2.7 |
cve-2023-23752-users |
高危 | /api/index.php/v1/users?public=true 枚举用户名/邮箱/注册时间 |
4.0.0-4.2.7 |
cve-2017-8917-com_fields |
严重 | com_fields list[fullordering] 报错注入,回显 database() |
3.7.0 |
cve-2015-7857-contenthistory |
高危 | com_contenthistory list[select] 注入 |
2.5.0-3.4.4 |
cve-2015-8562-ua-rce |
严重 | User-Agent 反序列化 RCE(版本命中即报,附 gadget 构造要点) | 1.5.0-3.4.5 |
cve-2016-8869-com_users |
严重 | 注册接口提权,可注册管理员(需 --force-exp) |
3.4.4-3.6.3 |
backup-leak |
高危 | configuration.php~/.bak/.save/.old/.txt/.orig、com_akeeba 备份、joomla.sql 等 14 条路径,命中即解析 $host/$user/$password/$db |
全部 |
admin-panel |
信息 | 后台入口与登录字段指纹 | 全部 |
com_jckman-upload |
中危 | com_jckman 历史版本任意文件上传点探测 |
1.0-2.0 |
com_fabrik-check |
中危 | 读 fabrik.xml 取版本,标注 SQLi/上传面 |
3.0-3.9 |
com_ajax-info |
信息 | com_ajax 是否启用及返回结构 |
3.0-4.2 |
说明:模块只做「最小必要验证」——能回显就取回显(库名、账号、口令),
不能回显就只报版本与利用面,不猜测、不伪造成功。
5.1 数据库 / 后台:拿到库口令直接建管理员
界面第四页,或命令行看到 [+] 泄露数据库凭据: user@host:port/db 前缀 jos_ 之后使用。
流程:扫描命中 → 凭据自动进下拉框 → 使用选中凭据 → 测试连接 → 一键创建管理员。
它到底写了什么(Joomla 官方表结构):
| 表 | 写入内容 |
|---|---|
#__users |
name / username / email / password / block=0 / sendEmail=1 / registerDate=now / params='',按目标实际存在的列动态拼 INSERT(1.5 老库缺列也不会报错) |
#__user_usergroup_map |
(user_id, group_id=8) —— 8 即 Super Users(超级用户组,后台最高权限) |
| 老结构 1.5.x | 若无映射表但有 gid 列,则 UPDATE #__users SET gid=25(超级管理员) |
口令方案自动判别(决定能不能登录成功的关键):
- 读站点既有账号的
password字段判断:$2y$/$2a$/$2b$→ bcrypt;含:→md5(password+salt):salt; - 判不出来时按版本推断:≥4.0 或 ≥3.2 用 bcrypt,更早用 md5+salt;
- bcrypt 用 JBCrypt
gensalt(10)生成后把$2a$改写成 Joomla 认的$2y$; - 用户名已存在则重置口令而不是重复插入,最后回读校验
id|username|email|block|hash。
账号口令回显:底部绿色大字 后台: http://目标/administrator/ 账号: jcsadmin 口令: xxxx,复制账号口令 一键进剪贴板,可直接拿去登录后台。
MySQL 严格模式的坑(已修):Joomla 建表时 lastvisitDate / registerDate 的默认值是'0000-00-00 00:00:00',而 MySQL 5.7+ 默认 sql_mode 含 NO_ZERO_DATE,INSERT 时省略这两列会直接失败:
MysqlDataTruncation: Data truncation: Incorrect datetime value: '0000-00-00 00:00:00'
for column 'lastvisitDate' at row 1 (MySQL 侧为 ERROR 1292 22007)
现在的处理是双保险:
- 连接后执行
SET SESSION sql_mode=''(会话级,不影响其他连接); - 更关键的一条:
INSERT前按information_schema.columns逐列检查,凡是没写、且默认值是零日期/NULL 的 NOT NULL 列,一律显式补合法值
—— 日期列给NOW(),整数列给0,字符列给'';自增列与生成列跳过。
日志里会打印[i] 将写入列: ...,方便核对到底写了哪些字段。
所以即使目标库的账号没有权限改 sql_mode,也能正常建号。生成 SQL 输出的语句同样把registerDate/lastvisitDate/lastResetTime 写成 NOW()(resetCount=0),粘进 phpMyAdmin 不会再报 1292。
同一族的另一个坑:Column 'lastResetTime' cannot be null
MySQLIntegrityConstraintViolationException: Column 'lastResetTime' cannot be null
不同 Joomla 版本的 #__users 里,lastResetTime 有的是可空 NULL,有的是datetime NOT NULL DEFAULT '0000-00-00 00:00:00'(MySQL 5.7 常见)。早期版本里我们把它固定写成NULL,碰上后者就会报这句。现在的规则是按 information_schema.columns 的真实可空性走:
| 列类型 | 可空 | 写入值 |
|---|---|---|
| datetime / timestamp | 是 | NULL |
| datetime / timestamp | 否 | NOW() |
| int / bit / tinyint | — | 0 |
| 其它(char/varchar/text) | — | '' |
[i] 将写入列: ... 里能看到 lastResetTime 排在哪一列,回读结果会给出它的实际值。
数据库只允许 localhost 怎么办(很常见,例如 phpStudy 的 root 仅 127.0.0.1):
点 生成 SQL,工具会输出两套可直接粘进 phpMyAdmin 的语句(bcrypt 与 md5+salt),
执行后同样得到超级管理员;也可以在目标上做端口转发后再用直连。
5.2 识别原理
指纹(每命中 +分,≥4 判定为 Joomla):/administrator/、/components/、/templates/system/css/system.css、/media/system/js/core.js、<meta name="generator" content="Joomla!">、/language/en-GB/en-GB.xml。
版本(6 法,按可靠性排序):
/administrator/manifests/files/joomla.xml→<version>/language/en-GB/langmetadata.xml→<version>/administrator/language/en-GB/en-GB.xml→<version>/README.txt→Joomla! x.y.z/plugins/editors/tinymce/tinymce.xml→ TinyMCE 版本 → 反查 Joomla 版本(内置 21 条映射表)/components/com_contact/metadata.xml→ 时间戳特征(仅 1.5.x)
组件存在判定:/components/<com_x>
200且命中 Joomla 空页特征(<html><body bgcolor="#FFFFFF"></body></html>等)→ 存在200正常内容 → 存在403→ 目录存在但禁止访问404/302/连接失败→ 不存在
7. 扩展组件字典
--dump-db 导出 data/components.csv,格式:
name,title,range,vuln,link
com_fabrik,Fabrik 表单,3.0-3.9,SQL 注入 / 任意文件上传,https://cxsecurity.com/ascii/WLB-2017120085
range写成1.5-3.4.5,留空表示全版本- 放回
data/components.csv后启动会自动合并(同名字段以文件为准)
8. 已知限制
- 版本区间是经验值,只用于排序与提示,不代表必然可利用;
cve-2015-8562需要构造 PHP gadget chain(JDatabaseDriverMysqli),工具只判定版本并给出构造要点,不内置通用链;- 需要登录的利用(模板写入、
com_media上传、插件安装)只标注位置,需拿后台凭据后手工执行; - 目标若挂在 CDN/WAF 后,
403与200 空页的判定可能失真,建议配合--delay与-H自定义头; - 建管理员依赖 MySQL 允许远程连接:
root@localhost这类配置下直连会报Access denied for user 'root'@'<本机>',此时请用生成 SQL走 phpMyAdmin(见 5.1); - 建管理员会在目标库留下一个真实账号,请在授权测试范围内使用、并在结束后自行清理。
9. 参考来源
- 原版:JCS — Joomla Component Scanner, by TheM4hd1
- CVE-2023-23752:https://github.com/vulhub/vulhub/tree/master/joomla/CVE-2023-23752
- CVE-2015-8562 POC:https://github.com/RobinHoutevelts/Joomla-CVE-2015-8562-PHP-POC
- com_fields SQLi(ExploitDB 42033)
- com_fabrik 上传(WLB-2017120085)
- 更多清单见
data/refs.md
10. 免责声明
仅用于已获授权的安全测试、教学与自家资产检查。
使用者对自己发出的每一个请求负责。











请登录后查看评论内容