MASTG-DEMO-0154: URLSessionDelegate Accepting Any Server Certificate
Download MASTG-DEMO-0154 IPA Open MASTG-DEMO-0154 Folder Build MASTG-DEMO-0154 IPA
Sample¶
The code below implements two URLSessionDelegate classes that both connect to expired.badssl.com. InsecureURLSessionDelegate calls completionHandler(.useCredential, URLCredential(trust: serverTrust)) without first calling SecTrustEvaluateWithError, accepting the expired certificate. SecureURLSessionDelegate correctly calls SecTrustEvaluateWithError and rejects the connection when trust evaluation fails.
| MastgTest.swift | |
|---|---|
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 | |
Steps¶
- Extract the app ( Exploring the App Package) and locate the main binary
./Payload/MASTestApp.app/MASTestApp. - Run radare2 (iOS) with the script to identify all URLSession authentication challenge handlers and determine which ones call
SecTrustEvaluateWithError.
| auth_challenge.r2 | |
|---|---|
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 | |
| run.sh | |
|---|---|
1 2 | |
Observation¶
The output contains five sections followed by separate disassembly files for each handler:
- Custom authentication-challenge handlers: lists every function whose signature references
NSURLAuthenticationChallenge. BothInsecureURLSessionDelegate(0x00004000) andSecureURLSessionDelegate(0x00004490) appear here because both implement a custom challenge handler. This is the broad signal that the app has taken over part of the server trust evaluation, regardless of whether it does so correctly. - Accessors into the challenge protection space: the
objc_msgSend$protectionSpace(0x000165e0) andobjc_msgSend$serverTrust(0x00016620) stubs confirm the app reaches intochallenge.protectionSpace.serverTrust, an indication of manual server trust handling. - xrefs to URLSession challenge handler implementations:
axffon both ObjC challenge handler methods shows their calls to the underlying Swift implementations.InsecureURLSessionDelegate's ObjC method (0x41f8) calls the Swift implementation at0x00004000.SecureURLSessionDelegate's ObjC method (0x4780) calls its Swift implementation at0x00004490. - Uses of SecTrustEvaluateWithError: confirms
SecTrustEvaluateWithErroris imported into the binary (imp.SecTrustEvaluateWithErrorat0x000161bc). - xrefs to SecTrustEvaluateWithError: only
SecureURLSessionDelegate's Swift implementation (0x4490) callsSecTrustEvaluateWithError, at offset0x4638.InsecureURLSessionDelegate's implementation (0x4000) has no entry here.
Reviewing the disassembled code ( Reviewing Disassembled Objective-C and Swift Code), the disassembly and AI-reversed Swift below show the insecure handler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
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 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Evaluation¶
Both delegates surface in the "Custom authentication-challenge handlers" section, so both have taken control of the server trust evaluation and warrant manual review. The cross-reference to SecTrustEvaluateWithError is what distinguishes the secure handler (0x4490) from the insecure one (0x4000).
The test case fails because InsecureURLSessionDelegate's implementation (0x00004000) does not appear in the "xrefs to SecTrustEvaluateWithError" section.
The disassembly confirms this:
serverTrustis obtained at0x00004064.- the only check is a
nilguard at0x0000408c(cbz x0, 0x4120). NSURLCredentialis created directly at0x000040d8with no call toSecTrustEvaluateWithErroranywhere in the function.
The AI-reversed Swift makes the pattern explicit: any non-nil trust object is accepted unconditionally.
In contrast, SecureURLSessionDelegate's implementation (0x00004490) calls SecTrustEvaluateWithError at 0x00004638 and only creates a URLCredential if that call returns true (tbz w0, 0, 0x46a8 branches to the cancel path on failure):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
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 | |
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 | |