Advantech iView多个不同类型匿名RCE漏洞分享

声明

出品|且听安全(ID:QCyber)

以下内容,来自且听安全公众号的作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。

漏洞信息

2022.06 ZDI发布多个Advantech iView漏洞信息CVE-2022-2135&2143&2135 等 :

影响版本为 Advantech iView All versions prior to 5_7_04_6469。重点关注其中评分为 `9.8` 的高危漏洞,发现问题主要集中在 `NetworkServlet`  ,整理的部分漏洞信息如下:

  •  `findCfgDeviceList` :When parsing the COLUMN and VALUE elements of the findCfgDeviceList action, the process does not properly validate a user-supplied string before using it to construct SQL queries. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `getAllActiveTraps` :When parsing the search_date_to and search_date_from elements of the getAllActiveTraps action, the process does not properly validate a user-supplied string before using it to construct SQL queries. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `performZTPConfig` :When parsing any element of the performZTPConfig action, the process does not properly validate a user-supplied string before using it to construct SQL queries. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `setTaskEditorItem` :When parsing the DESCRIPTION element of the setTaskEditorItem action, the process does not properly validate a user-supplied string before using it to construct SQL queries. An attacker can leverage this vulnerability to execute arbitrary code in the context of SYSTEM.

  •  `exportDeviceList` :When parsing the filename element of the exportDeviceList action, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `findCfgDeviceListDetailsExport` :When parsing the filename element of the findCfgDeviceListDetailsExport action, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `backupDatabase` :When parsing the backup_filename element of the backupDatabase action, the process does not properly validate a user-supplied string before using it to execute a system call. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `runProViewUpgrade` :When parsing the fwfilename element of the runProViewUpgrade action, the process does not properly validate a user-supplied string before using it to execute a system call. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  •  `findSummaryUpdateDeviceList` :When parsing the COLUMN and VALUE elements of the findSummaryUpdateDeviceList action, the process does not properly validate a user-supplied string before using it to construct SQL queries. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.

  • 分析发现这些漏洞实现 RCE 的方式主要是以下三种方式:

  •  SQL 注入漏洞结合 `outfile` 实现 getshell 

  •   直接命令拼接 getshell

  •   路径穿越导致 getshell 

  • 查看 `NetworkServlet` 定义:

    定位 

    `com.imc.iview.network.NetworkServlet#doPost` :

    提取参数 `page_action_type` ,根据取值调用不同的函数。下面就选择三个不同接口来分析三种不同 getshell 的方法。

    方式1:SQL注入+outfile getshell

    接口定义:

    提取参数后,调用 `findCfgDeviceList` :

    进入 `getDistinctDeviceTypes` :

    进入 `buildSelectSQL` :

    进行一z列参数赋值与类型转换后进入 `checkForChassisUpdates` ,

    传入的参数 `strSegment` 就是 GET 请求携带的参数 `segment` :

    private boolean checkForChassisUpdates(String strSegment) {    boolean bReturn = false;    new String();    int nCount = 0;    if (this.initDBServices()) {        String strSQL = "SELECT COUNT(*) UpdateCount FROM device_tree_table as a, device_tree_table as b WHERE b.nDeviceTypeId = 18 AND b.dtBuildDate < '2012-07-09 08:04:00' AND a.nDeviceId = b.nParentId AND a.strDescription = '" + strSegment + "'";        Connection conn = this.getConnection();        try {            Statement stmt = conn.createStatement();            ResultSet resultset;            for(resultset = stmt.executeQuery(strSQL); resultset.next(); nCount = resultset.getInt("UpdateCount")) {            }        ...}

    没有对参数进行任何检查,直接拼接进入了 SQL 查询语句,导致出现 SQL 注入漏洞:

    因为 Advantech iView 默认集成的 MySQL 数据库版本较低,支持 `outfile` ,所以可以利用 SQL 注入直接写入 webshell:

    方式2:mysqldump 命令注入 getshell

    接口定义:

    提取请求参数 `backup_filename` ,通过 `checkFileNameIncludePath` 和

    `checkSQLInjection` 对进行检查。

  •  `checkFileNameIncludePath` 函数检查是否存在路径穿越,并对 `\webapps\` 等进行了过滤,很显然 `/webapps/` 就可以绕过。

  •  `checkSQLInjection` 函数对插件的 SQL 注入关键词进行了过滤,也对 `getRuntime().exec` 等命令执行常用字符串进行了过滤,但是没有过滤 `ProcessBuilder` 等其他可以命令执行的函数。

  • 回到 `backupDatabase` 函数,通过过滤检查后,将调用 `mysqldump` 进行数据库备份:

    if (!errFile && !sqlInj) {    if (tempDBServices.getMySQLLocation()) {        String strMySQLPath = tempDBServices.getMySQLPath();        if (tempDBServices.retrieveDbSettings()) {            String strUser = tempDBServices.getStrLoginUserID();            String strPassword = tempDBServices.getStrLoginPassword();            if (tempSystemTable.findDbBackupFilePath()) {                String strDbBackupFilePath = tempSystemTable.getDbBackupFilePath();                strDbBackupFilePath = strDbBackupFilePath + strFilename;                if (OsUtils.isWindows()) {                    strExecuteCmd = "\"" + strMySQLPath;                    strExecuteCmd = strExecuteCmd + "bin\\mysqldump\" -hlocalhost -u " + strUser + " -p" + strPassword + " --add-drop-database -B iview -r \"" + strDbBackupFilePath + "\"";                }                try {                    runtimeProcess = Runtime.getRuntime().exec(strExecuteCmd);                    ...

    将请求的参数直接拼接进入了命令执行语句:

    查看 `mysqldump` 支持的参数列表:

    其中 `-r` 可以指定导出文件的路径, `-w` 用于设置导出的数据条件,但其取值也会导出到文件中,所以我们可以用来传递 shell 内容。最终通过构造特殊的 `backup_filename` 参数实现 getshell :

    方式3:路径穿越可导致 getshell

    接口定义:

    提取参数 `filename` ,传入 `exportDeviceList` 函数,没有检查存在路径穿越风险:

    重点关注 `getExportDevices` 和 `createExportFile` 函数:

  •  `getExportDevices`

  • StringBuffer strSQL = new StringBuffer("SELECT a.nDeviceId AS \"Device Id\", b.strDescription AS \"Segment\", a.strDeviceTypeId AS \"Device Type\", a.strIPAddress AS \"IP Address\", a.strDNSName AS \"Device Domain Name\", a.strMACAddress AS \"MAC Address\", a.strGetCommunity AS \"Get Community\", a.strSetCommunity AS \"Set Community\", a.strDeviceUser AS \"Device User\", a.strDevicePassword AS \"Device Password\" FROM device_tree_table a, device_tree_table b WHERE a.nParentId = b.nDeviceId");String strColNames = "Device Id, Segment, Device Type, IP Address, Device Domain Name, MAC Address, Get Community, Set Community, Device User, Device Password";

    首先从数据表 `device_tree_table` 中查询符合条件的设备列表 `tempDeviceList` ,然后通过 `setExportList` 赋值给 `m_ExportList` 私有变量。

  • `createExportFile`

  • 通过 `getExportList` 提取 `m_ExportList`变量并赋值给

    `tempRowOutputList` ,然后写入路径可控文件。

    从上面分析可知,如果可以将 shell 写入 `device_tree_table` ,那么结合路径穿越可以将 shell 写入任意目录。比较幸运的是在 `NetworkServlet` 中可以找到添加设备的接口 `addDevices` :

    组合 `addDevices` 和 `exportDeviceList` 应该就可以实现 getshell 。

    在漏洞复现时发现, `addDevices` 在多个地方需要通过发送 udp 广播包检查设备的存活性(比如 `Network#updateProViewFunction` 函数):

    伪造数据包肯定可以绕过检查,有兴趣的小伙伴可以自行深入分析协议解析过程完成构造!

    修复方式

    多处增加了SQL注入检查,比如`findCfgDeviceList` :

    多处增加了路径穿越检查,比如 `exportDeviceList` :

    缝缝补补修复的地方很多,但是对比分析后仍然感觉程序代码怎一个乱字了得!

    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 212,294评论 6 493
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 90,493评论 3 385
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 157,790评论 0 348
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 56,595评论 1 284
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 65,718评论 6 386
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 49,906评论 1 290
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 39,053评论 3 410
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 37,797评论 0 268
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 44,250评论 1 303
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 36,570评论 2 327
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 38,711评论 1 341
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 34,388评论 4 332
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 40,018评论 3 316
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 30,796评论 0 21
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 32,023评论 1 266
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 46,461评论 2 360
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 43,595评论 2 350

    推荐阅读更多精彩内容