| タイトル | aaPanel BaoTa < 11.8.0 Command Injection |
|---|
| 説明 | In this project, the `InputSql` action in `class/database.py` is used to import a compressed database backup archive. The archive password (`get.password`) is retrieved directly from the HTTP request, but the problem is that it is simply enclosed in single quotes and concatenated into the shell command. This results in neither the `'` character being escaped nor
`shlex.quote`. Consequently, an authenticated admin user can bypass the `unzip` parameter and execute arbitrary
shell commands as root.
Note: The injected command is executed before the `unzip` error is reported. Consequently, the HTTP response returns `{“status”: false, ‘msg’: “Unzip error!”}`, but the injected `id` has already been executed as root and written a marker file owned by root. This results in a situation where the API claims failure, but the root command has already been executed.
The vulnerability maintainer has acknowledged the issue and has already implemented a fix; however, the patched version 11.8.1 has not yet been released.
Affected Versions and Components
Process: `/www/server/panel/BT-Panel`
Files: `/www/server/panel/class/database.py:1738, 1741, 1793-1794`
Path: `POST /database?action=InputSql`
Backend DB: Panel’s SQLite database; the `InputSql` operation affects user MySQL database records
Prerequisites: MySQL/MariaDB must be installed, and there must be at least one MySQL database record in the panel (this condition is almost always met in production environments on Baota).
Severity: High
CWE: CWE-78
Vulnerable code:
# database.py:1738 — password comes from HTTP, with no validation whatsoever
zip_password = getattr(get, “password”, None)
# database.py:1741 — Enclosed in single quotes, but ' is not escaped
password_shell = “-P ‘{zip_password}’”.format(zip_password=zip_password)
# database.py:1793-1794 — Concatenated into the shell string, shell=True
command = “unzip {password_shell} -o ‘{file}’ -d ‘{input_dir}’”.format(
password_shell=password_shell, file=file, input_dir=input_dir)
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
`get.password` is fully controllable by an attacker; it enters `shell=True` without any filtering. In single-quote context, the opening `'` can easily close the quote, and `;` can be used to append arbitrary commands.
|
|---|
| ソース | ⚠️ https://gist.github.com/zuesdevil/42ac3ee7ab5554b31784da14f175e029 |
|---|
| ユーザー | zuesdevil (UID 100502) |
|---|
| 送信 | 2026年08月11日 09:45 (2 月 ago) |
|---|
| モデレーション | 2026年09月27日 13:05 (2 months later) |
|---|
| ステータス | 承諾済み |
|---|
| VulDBエントリ | 410877 [aaPanel BaoTa 迄 11.8.0 Database Backup class/database.py InputSql パスワード 特権昇格] |
|---|
| ポイント | 20 |
|---|