| Titel | aaPanel BaoTa < 11.8.0 Command Injection |
|---|
| Beschreibung | `/files?action=UnZip` calls `panelTask.bt_task._unzip` in the active path; this function executes `unzip -X -P ‘<password>’ ...` on `.zip` files (`public.ExecShell`, shell context). `password` is taken directly from the HTTP request without any escaping. An attacker can inject commands using closed single quotes to execute an arbitrary shell with **root** privileges.
Note: The API also returns “File unpacked successfully,” making the response highly misleading.
Severity: High
CWE:CWE-78
The vendor 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
1. Product: Baota Linux Panel (https://github.com/aaPanel/BaoTa)
2. Process: `/www/server/panel/BT-Panel` (running as `root`, PID 10001)
3. File: `/www/server/panel/class/panelTask.py`
4. Path: `POST /files?action=UnZip`
5. Prerequisite: The admin uploads an arbitrary `.zip` file as an `sfile`
Vulnerability Code:
`panelTask.py:583, 602`
https://github.com/aaPanel/BaoTa/blob/main/class/panelTask.py#L583-L602
this is source code :
public.ExecShell("unzip -X -P '"+password+"' -o '" + sfile + "' -d '" + dfile + "' &> " + log_file)
split_log = lambda x: x[len(dfile)+13 if dfile[-1] == '/' else len(dfile)+14:].split('/')[0].strip() if not x.startswith('Archive') else ""
elif sfile[-7:] == '.tar.gz' or sfile[-4:] == '.tgz' or (tarfile.is_tarfile(sfile) and sfile[-3:] == '.gz'):
public.ExecShell("tar zxvf '" + sfile +
"' -C '" + dfile + "' &> " + log_file)
split_log = lambda x: x.strip().split('/')[0]
elif sfile[-4:] == '.rar':
rar_file = '/www/server/rar/unrar'
if not os.path.exists(rar_file):
self.install_rar()
pass_opt = '-p-'
if password:
password = password.replace("&","\&").replace('"','\"')
pass_opt = '-p"{}"'.format(password)
public.ExecShell(rar_file + ' x '+ pass_opt +' -u -y "' + sfile + '" "' + dfile + '" &> ' + log_file)
split_log = lambda x: re.search(r"/[^\s]+", x).group().strip()[len(dfile) if dfile[-1] == '/' else len(dfile)+1:].split('/')[0] if x.strip().endswith('OK') and re.search(r"/[^\s]+", x) else ""
elif sfile[-4:] == '.war':
public.ExecShell("unzip -X -P '"+password+"' -o '" +
sfile + "' -d '" + dfile + "' &> " + log_file)
split_log = lambda x: x[len(dfile)+13 if dfile[-1] == '/' else len(dfile)+14:].split('/')[0].strip() if not x.startswith('Archive') else ""
elif sfile[-4:] == '.bz2':
public.ExecShell("tar jxvf '" + sfile +
"' -C '" + dfile + "' &> " + log_file)
split_log = lambda x: x.strip().split('/')[0]
elif sfile[-3:] == '.7z':
_7zbin = self.get_7z_bin()
if not _7zbin:
self.install_7zip()
err_msg = 'p7zip组件未安装,无法解压7z文件,已尝试自动安装,请稍等几分钟重试!'
public.WriteLog("文件管理","解压文件失败,原因:{},文件: {}".format(err_msg,sfile))
return public.returnMsg(False, err_msg)
pass_opt = ""
if password:
pass_opt = '-p"{}"'.format(password)
public.ExecShell('{} x "{}" -o"{}" -bb3 -y {} &> {}'.format(_7zbin,sfile,dfile,pass_opt,log_file))
split_log = lambda x: x.strip()[1:].split('/')[0].strip() if x.startswith('-') and not x.startswith('--') else ""
else:
public.ExecShell("gunzip -c " + sfile + " > " + sfile[:-3])
Analysis:
# panelTask.py:583 — The password is concatenated directly into the unzip command without escaping
public.ExecShell(“unzip -X -P ‘”+password+“’ -o ‘” + sfile + “’ -d ‘” + dfile + “’ &> ” + log_file)
# panelTask.py:602 — Same for the .war branch
public.ExecShell(“unzip -X -P ‘”+password+“’ -o ‘” + sfile + “’ -d ‘” + dfile + “’ &> ” + log_file)
`password` is fully controllable by an attacker; `public.ExecShell` is a shell context; single quotes can be escaped with `'`.
Prerequisites
1. Valid admin panel credentials
2. An `x-http-token` bound to the session.
3. The admin must upload an arbitrary `.zip` file as an `sfile`.
PoC, Proof, and original email correspondence with the vendor's maintainer, please see the reference URL: https://gist.github.com/zuesdevil/ba0b8aa9f7516ea0e57b173146ce5408
|
|---|
| Benutzer | zuesdevil (UID 100502) |
|---|
| Einreichung | 11.08.2026 11:23 (vor 2 Monaten) |
|---|
| Moderieren | 27.09.2026 13:05 (2 months later) |
|---|
| Status | Akzeptiert |
|---|
| VulDB Eintrag | 410879 [aaPanel BaoTa bis 11.8.0 Unzip panelTask.py panelTask.bt_task._unzip password erweiterte Rechte] |
|---|
| Punkte | 20 |
|---|