拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

在 iOS 二进制中挖掘硬编码 HTTP URL:MASTG-DEMO-0084 实战剖析(OWASP MASTG)

在 iOS 二进制中挖掘硬编码 HTTP URL:MASTG-DEMO-0084 实战剖析(OWASP MASTG)
  • 文档
  • 教程
  • 网络安全

【免费下载链接】mastg

The OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.

项目地址:https://gitcode.com/gh_mirrors/ow/mastg
点击查看免费下载

本文以 OWASP Mobile Application Security Testing Guide(MASTG)仓库中的 MASTG-DEMO-0084 为骨架,讲解如何对已编译的 iOS 应用二进制执行静态分析,定位硬编码的明文 HTTP 地址,并结合 ATS(App Transport Security)配置判断其真实危害。读者将掌握一条完整的实战链路:解包 IPA → 用 radare2 脚本枚举http://字符串 → 通过交叉引用与反汇编追踪字符串的调用路径 → 结合 Info.plist 中的 ATS 例外评估风险,从而能够在没有源码的情况下独立完成 MASTG-TEST-0321 的判定。

一、Demo 背景:一个注定失败的 iOS 网络样本

MASTG-DEMO-0084属于 MASTG 的demos/ios/MASVS-NETWORK/目录,是一个kind: fail的失败示例,对应的测试用例是 MASTG-TEST-0321: Hardcoded HTTP URLs,关联的安全弱点为 MASWE-0026。它的前身是MASTG-TEST-0065(Testing Data Encryption on the Network),后者已被标记为deprecated并由 MASTG V2 系列测试(0321/0322/0236)取代(见 tests/ios/MASVS-NETWORK/MASTG-TEST-0065.md 的covered_by字段)。

配套样本由三部分构成(见 MASTG-DEMO-0084 目录):

  • MASTestApp:已编译的 Mach-O 主二进制;
  • MastgTest.swift:对应的 Swift 源码,用于对照验证二进制中的字符串与调用;
  • http_urls.r2+run.sh:驱动 radare2 的静态分析脚本与执行入口;
  • output.txt:本次分析的完整输出,即"证据"。

需要强调:MASTG-DEMO-0084讨论的是二进制层面的硬编码 URL 挖掘,而兄弟 Demo MASTG-DEMO-0083 讨论的是Info.plist 层面的不安全 ATS 配置。两者互为印证——前者证明"应用确实使用了明文 URL",后者证明"ATS 恰好放行了该域名",合在一起才能构成完整的失败判定。

二、样本代码:硬编码 HTTP URL 的"犯罪现场"

先看对应的源码 MastgTest.swift,它直观展示了三类 URL 的对比:

import Foundation struct MastgTest { // SUMMARY: This sample demonstrates the use of hardcoded HTTP URLs in iOS apps. static let httpEndpoint = "http://httpbin.org/get" // FAIL: [MASTG-TEST-0321] Hardcoded HTTP URL static let httpApiUrl = "http://example.com/api" // FAIL: [MASTG-TEST-0321] Hardcoded HTTP URL static let httpsEndpoint = "https://httpbin.org/get" // PASS: [MASTG-TEST-0321] HTTPS URL static func mastgTest(completion: @escaping (String) -> Void) { var result = "Testing HTTP URL connections:\n\n" // Attempt to connect to HTTP endpoint if let url = URL(string: httpEndpoint) { let task = URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { result += "HTTP request to \(httpEndpoint) failed: \(error.localizedDescription)\n" } else if let httpResponse = response as? HTTPURLResponse { result += "HTTP request to \(httpEndpoint) returned status: \(httpResponse.statusCode)\n" } completion(result) } task.resume() } else { result += "Invalid URL: \(httpEndpoint)\n" completion(result) } } }

代码注释直接标注了判定结论:

  • http://httpbin.org/get与http://example.com/api均为 FAIL(硬编码 HTTP URL);
  • https://httpbin.org/get为 PASS(HTTPS URL,不触发该测试)。

关键调用链是URL(string: httpEndpoint)构造URL实例,再交给URLSession.shared.dataTask(with:)发起请求——这是 iOS 标准 URL Loading System 的用法,因此受 ATS 管控(这一点对后续判定至关重要:如果应用改用低层 API,ATS 根本不生效,见下文第六节的讨论)。

三、实战步骤:用 radare2 从二进制中"挖"出 URL

3.1 解包并定位主二进制

依据技术文档 MASTG-TECH-0058: Exploring the App Package,首先解压 IPA(本质是一个 zip 包),进入.app包并定位主二进制。本例中路径为:

./Payload/MASTestApp.app/MASTestApp

3.2 编写 radare2 分析脚本

MASTG-DEMO-0084使用 radare2(iOS) 作为分析引擎,其脚本 http_urls.r2 内容如下:

e asm.bytes=false e scr.color=false e asm.var=false ?e Uses of http:// URLs: iz~http:// ?e ?e xrefs to http://httpbin.org/get: axt @ 0x100006c60 ?e ?e Use of http://httpbin.org/get: pd 15 @ 0x100005130 ?e ... pd-- 5 @ 0x100005238

逐条解读脚本的意图:

  • e asm.bytes=false/e scr.color=false/e asm.var=false:关闭字节显示、彩色输出与变量名折叠,保证输出干净、利于后续 grep 与归档;
  • iz~http://:iz列出 Mach-O__TEXT.__cstring段中的字符串,~是 radare2 内置过滤器,等价于 grep,筛出所有含http://的字符串;
  • axt @ 0x100006c60:axt列出该地址的交叉引用(xrefs),找出谁引用了http://httpbin.org/get字符串;
  • pd 15 @ 0x100005130:在引用点反汇编 15 条指令,展示字符串如何被使用;
  • pd-- 5 @ 0x100005238:从0x100005238往前反汇编 5 条指令,展示 URLSession 相关调用点。

3.3 执行脚本

run.sh 是唯一的执行入口,一条命令完成分析:

#! /bin/bash r2 -q -i http_urls.r2 -A MASTestApp > output.txt

参数说明:

  • -q:quiet 模式,抑制交互提示;
  • -i http_urls.r2:以批处理方式执行脚本;
  • -A:启动时自动完成全量分析(aa 等分析步骤),生成函数、交叉引用数据库——没有这一步,axt与pd无法给出有意义的符号级结果;
  • > output.txt:将结果重定向保存为证据文件。

值得说明:radare2 是开源逆向框架,而 rabin2 是它的姊妹命令行工具,常用于快速抽取二进制信息(导入导出、数据段字符串、交叉引用、入口点、架构类型等)。在本流程中 radare2 承担了"交互式深度分析"的角色,两者配合可以覆盖从快速枚举到逐指令追踪的不同需求。

四、观察:output.txt 揭示的二进制证据

运行后得到的 output.txt 是本 Demo 的核心证据,分三段呈现。

4.1 明文 URL 字符串清单

Uses of http:// URLs: 0 0x00006bd0 0x100006bd0 56 57 2.__TEXT.__cstring ascii HTTP request to http://httpbin.org/get returned status: 1 0x00006c10 0x100006c10 47 48 2.__TEXT.__cstring ascii HTTP request to http://httpbin.org/get failed: 2 0x00006c60 0x100006c60 22 23 2.__TEXT.__cstring ascii http://httpbin.org/get 3 0x00006c80 0x100006c80 36 37 2.__TEXT.__cstring ascii Invalid URL: http://httpbin.org/get\n

各列含义:序号 / 文件偏移 / 虚拟地址 / 字符串长度 / 段名 / 类型 / 内容。四条命中全部落在__TEXT.__cstring段,且都指向同一个 URLhttp://httpbin.org/get——既包含直接请求的 URL 本体,也包含拼接进日志文案的间接引用。值得注意的是,源码中还存在http://example.com/api,但在该二进制路径下未出现在本次输出中,说明具体运行代码路径不同,字符串清单会随之变化(本次 Demo 的mastgTest只实际使用了httpEndpoint)。

4.2 交叉引用:谁引用了该字符串

xrefs to http://httpbin.org/get: sym.func.100005024 0x100005130 [STRN:r--] add x8, x8, str.http:__httpbin.org_get

radare2 定位到函数sym.func.100005024,其内部0x100005130处有一条add x8, x8, 0xc60指令,将寄存器指向字符串地址0x100006c60。这证明该 URL不是死字符串,而是被某函数实际取用。

4.3 反汇编:完整的调用链

│ 0x100005130 add x8, x8, 0xc60 ; 0x100006c60 ; "http://httpbin.org/get" │ 0x100005134 sub x27, x8, 0x20 │ 0x100005138 mov x0, x24 │ 0x10000513c bl sym.imp.swift_retain │ 0x100005140 mov x0, x23 ; void *arg0 │ 0x100005144 bl sym.imp.swift_bridgeObjectRetain ; void *swift_bridgeObjectRetain(void *arg0) │ 0x100005148 orr x1, x27, 0x8000000000000000 │ 0x10000514c mov x8, x26 │ 0x100005150 mov x0, 0x16 │ 0x100005154 movk x0, 0xd000, lsl 48 │ 0x100005158 bl sym.imp.Foundation.URL.string_...cfC_ ; Foundation.URL.string(...cfC) │ 0x10000515c ldr x8, [x28, 0x30] │ 0x100005160 mov x0, x26 │ 0x100005164 mov w1, 1 │ 0x100005168 mov x2, x22 ... │ 0x100005224 mov x0, x27 │ 0x100005228 mov x1, x26 │ 0x10000522c mov x2, x22 │ 0x100005230 blr x8 │ 0x100005234 adrp x8, segment.__DATA ; 0x10000c000 │ 0x100005238 ldr x0, [x8, 0xc8] ; [0x10000c0c8:4]=158 │ ; reloc.NSURLSession ; void *arg0 │ 0x10000523c bl sym.imp.objc_opt_self ; void *objc_opt_self(void *arg0) │ 0x100005240 adrp x8, segment.__DATA ; 0x10000c000 │ 0x100005244 ldr x1, [x8, 0xa0] ; [0x10000c0a0:4]=0x6e87 ; reloc.fixup.sharedSession ; char *selector │ 0x100005248 bl sym.imp.objc_msgSend ; void *objc_msgSend(void *instance, char *selector)

对照源码逐段还原:

  • 0x100005130:字符串"http://httpbin.org/get"被装入寄存器(即源码中URL(string: httpEndpoint)的实参准备);
  • 0x100005158:调用Foundation.URL.string(...)构造URL实例——对应源码第 14 行URL(string: httpEndpoint);
  • 0x100005238起:加载reloc.NSURLSession、调用objc_msgSend获取sharedSession(重定位引用reloc.fixup.sharedSession),随后发起会话请求——对应源码第 15 行URLSession.shared.dataTask(with: url)。

至此,从字符串到URL构造再到URLSession的三级调用链在反汇编层面被完整闭合,这正是 MASTG-DEMO-0084 判定"该 URL 确实被应用使用"的硬证据。

五、评估:为什么判定为 FAIL

MASTG-DEMO-0084的结论是明确的失败(kind: fail),依据有两条,缺一不可:

  1. 二进制中存在硬编码的明文 URL:http://httpbin.org/get被实际使用(见上文调用链),触发 MASTG-TEST-0321;
  2. ATS 配置放行了该域名:应用在 Info.plist 中通过NSExceptionDomains为httpbin.org配置了NSExceptionAllowsInsecureHTTPLoads = true(相关细节见 MASTG-DEMO-0083),因此该 HTTP 请求不会被 ATS 拦截,能够真正发出明文流量。

两者结合,说明"硬编码 URL"从潜在风险升级为实际可利用的明文通信缺陷。

需要特别留意 MASTG-TEST-0321 的局限性说明(见 MASTG-TEST-0321.md):

二进制中存在 HTTP URL 并不意味着它一定被用于通信。其使用与否取决于运行时条件,例如 URL 如何被调用、应用 ATS 配置是否允许明文流量。当 ATS 启用且未配置例外时,HTTP 请求可能直接失败(见 MASTG-TEST-0322);而如果应用使用绕过 ATS 的低层 API,请求则可能成功(同样见 MASTG-TEST-0322)。

因此静态分析必须与动态验证互补:例如通过中间人代理捕获真实网络流量,确认应用在运行期确实向这些 HTTP 地址发起连接(对应 MASTG-TEST-0236 的动态测试思路,以及 MASTG-TEST-0065 中"ATS 配置与真实流量可能不一致"的告诫——即使 Info.plist 禁用了明文,低层 API 或配置不当的跨平台框架仍可能偷偷发送 HTTP)。

六、知识延伸:ATS 例外与明文流量判定要点

由于 MASTG-DEMO-0084 的判定强依赖 ATS 上下文,这里补充 MASTG-TEST-0065 / MASTG-TEST-0322 中的关键知识点:

  • iOS 9.0 起,ATS 默认阻止明文 HTTP,但存在多种"后门"使应用仍可发送明文:
    • 在NSAppTransportSecurity中将NSAllowsArbitraryLoads设为true(全局关闭);
    • iOS 10 起可用NSAllowsArbitraryLoadsInWebContent关闭 WebView 内容的 ATS 限制;
    • 通过NSExceptionDomains为指定域名配置NSExceptionAllowsInsecureHTTPLoads = true(本 Demo 即属此类)。
  • ATS 不适用于低层网络接口(如 Network framework、CFNetwork)。Apple 官方建议优先使用 URL Loading System 这类高层框架,因为低层 API 的安全责任完全落在开发者身上,且"犯错容易、代价高昂"(见 MASTG-TEST-0065.md 引用的 Apple 文档)。
  • ATS 例外并非一律不可接受:如 Firefox iOS 出于浏览器产品定位全局禁用 ATS 即属合理例外;但即便如此,也应在 ATS 配置中包含 justification 说明字符串。
  • 静态检查的注意点:应同时覆盖应用主二进制之外的内嵌扩展、framework、Watch App 等所有可执行组件(见 MASTG-TEST-0065.md)。

对应到本 Demo 的 Info.plist,可以看到一个"叠满了 buff"的不安全配置:NSAllowsArbitraryLoads、NSAllowsArbitraryLoadsInWebContent、NSAllowsArbitraryLoadsForMedia、NSAllowsArbitraryLoadsForLocalNetworking全部为true,外加api.example.com与httpbin.org两个域名级例外。MASTG-DEMO-0083 的评估还指出一个易被忽视的细节:当NSAllowsArbitraryLoadsForLocalNetworking、NSAllowsArbitraryLoadsForMedia、NSAllowsArbitraryLoadsInWebContent存在时(无论取值),NSAllowsArbitraryLoads会被忽略。而本 Demo 中实际生效的是httpbin.org的域名级例外——正是它让http://httpbin.org/get的请求得以放行。

七、总结与可复用的检测方法论

MASTG-DEMO-0084 给出了一条可复用的"无源码 iOS 明文 URL 审计"流水线:

  1. 解包定位:按 MASTG-TECH-0058 解压 IPA,定位主二进制(Payload/*.app/*);
  2. 字符串枚举:radare2 的iz~http://快速筛出__TEXT.__cstring中的明文 URL;
  3. 引用追踪:axt @ 地址找到引用者,pd反汇编还原URL构造与URLSession调用链,确认 URL 是否"真正在用";
  4. ATS 交叉验证:检查 Info.plist 的NSAppTransportSecurity,判断明文请求是否会被放行;
  5. 动态确认:用代理抓包验证运行期真实流量,避免误报/漏报(对应 MASTG-TEST-0236)。

整套流程所需的证据文件——分析脚本、执行命令、输出结果——均可在仓库的 MASTG-DEMO-0084 目录 中直接复现验证。它同时展示了 MASTG 方法论的核心:字符串存在 ≠ 实际使用,实际使用 + ATS 放行 ≠ 必然失败——每一步结论都必须有二进制级证据支撑,这正是安全测试从"扫描"走向"验证"的关键。

  • 文档
  • 教程
  • 网络安全

【免费下载链接】mastg

The OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.

项目地址:https://gitcode.com/gh_mirrors/ow/mastg
点击查看免费下载
上一篇:boardgame.io 调试指南:Debug 面板、Redux 增强器与服务器日志的完整实践
下一篇:ZCode 语音输入组件 SpeechInput 实战指南:Web Speech API 与 MediaRecorder 双引擎语音转文字方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表