├── GSA.py ├── README.md └── requirements.txt /GSA.py: -------------------------------------------------------------------------------- 1 | import srp 2 | import base64 3 | from datetime import datetime 4 | import requests 5 | import plistlib 6 | 7 | def GSA_authenticate(username, password): 8 | 9 | #################### 10 | ###### Step 1 ###### 11 | #################### 12 | 13 | 14 | # Create the a2k section of the plist payload. 15 | a2k_data = srp.create_salted_verification_key(username, password, hash_alg=srp.SHA256, ng_type=srp.NG_2048) 16 | a2k = base64.b64encode(a2k_data[1]).decode("utf-8") 17 | time = datetime.utcnow().isoformat()[:-7]+'Z' 18 | 19 | # Request headers for Apple's GSA API. 20 | 21 | headers = { 22 | 'Host': 'gsa.apple.com', 23 | 'Content-Type': 'text/x-xml-plist', 24 | 'X-Mme-Client-Info': ' ', 25 | 'Accept': '*/*', 26 | 'Accept-Language': 'en-us', 27 | 'User-Agent': 'akd/1.0 CFNetwork/978.0.7 Darwin/18.7.0' 28 | } 29 | 30 | url = "https://gsa.apple.com/grandslam/GsService2" 31 | 32 | data = """ 33 | 34 | 35 | 36 | Header 37 | 38 | Version 39 | 1.0.1 40 | 41 | Request 42 | 43 | A2k 44 | 45 | """+a2k+""" 46 | 47 | cpd 48 | 49 | AppleIDClientIdentifier 50 | D4B7512F-E841-4AEA-A569-4F1E84738182 51 | X-Apple-I-Client-Time 52 | """+time+""" 53 | X-Apple-I-MD 54 | AAAABQAAABCMMt6qegoLwK7/SjhV8/XQAAAAAw== 55 | X-Apple-I-MD-M 56 | BvleDr7BzY/U0+RwcEwPJiikBNW9J69y8qtmJi1xrzXVwz+iTq5fZWSA2S+9ssE3dDpMpuXCxsWQ/at1 57 | X-Apple-I-MD-RINFO 58 | 17106176 59 | X-Apple-I-SRL-NO 60 | C39L80JCFNJT 61 | X-Mme-Device-Id 62 | 2c7a7a35e0a441245fbf7e2c5cad03fce2dca5d8 63 | bootstrap 64 | 65 | capp 66 | AppStore 67 | ckgen 68 | 69 | dc 70 | #d4c5b3 71 | dec 72 | #e1e4e3 73 | loc 74 | en_US 75 | pbe 76 | 77 | prtn 78 | ME349 79 | svct 80 | iTunes 81 | 82 | o 83 | init 84 | ps 85 | 86 | s2k 87 | s2k_fo 88 | 89 | u 90 | """+username+""" 91 | 92 | 93 | """ 94 | 95 | r = requests.post(url, data=data, headers=headers, verify=False) 96 | content = r.content 97 | pl = plistlib.loads(content) 98 | 99 | #print(content) #uncomment this to print out the output. 100 | 101 | # Extract s and B from request. 102 | s_b64 = base64.b64encode(pl["Response"]["s"]).decode("utf-8") 103 | B_b64 = base64.b64encode(pl["Response"]["B"]).decode("utf-8") 104 | 105 | #Extract c parameter which is used in subsequent header. 106 | c = pl["Response"]["c"] 107 | 108 | 109 | #Build M1 110 | s = base64.b64decode(s_b64) 111 | B = base64.b64decode(B_b64) 112 | 113 | usr = srp.User( username, password, hash_alg=srp.SHA256, ng_type=srp.NG_2048 ) 114 | M1 = usr.process_challenge( s, B ) 115 | M1 = base64.b64encode(M1).decode("utf-8") 116 | 117 | print("M1: "+M1) 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | #################### 129 | ###### Step 2 ###### 130 | #################### 131 | 132 | time = datetime.utcnow().isoformat()[:-7]+'Z' 133 | 134 | 135 | data2 = """ 136 | 137 | 138 | 139 | Header 140 | 141 | Version 142 | 1.0.1 143 | 144 | Request 145 | 146 | M1 147 | 148 | """+M1+""" 149 | 150 | c 151 | """+c+""" 152 | cpd 153 | 154 | AppleIDClientIdentifier 155 | D4B7512F-E841-4AEA-A569-4F1E84738182 156 | X-Apple-I-Client-Time 157 | """+time+""" 158 | X-Apple-I-MD 159 | AAAABQAAABCMMt6qegoLwK7/SjhV8/XQAAAAAw== 160 | X-Apple-I-MD-M 161 | BvleDr7BzY/U0+RwcEwPJiikBNW9J69y8qtmJi1xrzXVwz+iTq5fZWSA2S+9ssE3dDpMpuXCxsWQ/at1 162 | X-Apple-I-MD-RINFO 163 | 17106176 164 | X-Apple-I-SRL-NO 165 | C39L80JCFNJT 166 | X-Mme-Device-Id 167 | 2c7a7a35e0a441245fbf7e2c5cad03fce2dca5d8 168 | bootstrap 169 | 170 | capp 171 | AppStore 172 | ckgen 173 | 174 | dc 175 | #d4c5b3 176 | dec 177 | #e1e4e3 178 | loc 179 | en_US 180 | pbe 181 | 182 | prtn 183 | ME349 184 | svct 185 | iTunes 186 | 187 | o 188 | complete 189 | u 190 | """+username+""" 191 | 192 | 193 | """ 194 | 195 | 196 | 197 | 198 | r = requests.post(url, data=data2, headers=headers, verify=False) 199 | content = r.content 200 | #print(content) #uncomment this to print out the output. Will currently result in invalid Apple ID / Password message. 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | GSA_authenticate("EMAIL HERE", "PASSWORD HERE") 210 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apple GSA Protocol 2 | 3 | This repository includes a simple script for authenticating with Apple's GrandSlam Authentication protocol. Although there is a little documentation on this process online, I could not find any resources on how to set up some of the parameters for GSA authentication, which is why I decided to make this repository. 4 | 5 | 6 | ## What is GrandSlam Authentication (GSA) ? 7 | 8 | GSA is based on the [SRP-6a authentication protocol](https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) which can verify a user has the correct password to an account without actually transmitting it. GSA is utilized in many of Apple's applications for authentication. Some apps that use GSA endpoints include iCloud and the App Store. 9 | 10 | The endpoint for GSA is https://gsa.apple.com/grandslam/GsService2 11 | 12 | ## Analyzing traffic 13 | 14 | All of Apple's applications utilize SSL pinning which means you must take a couple of extra steps in order to read some of the traffic yourself. 15 | 16 | **macOS**: 17 | The first step in obtaining the web traffic would be to intercept the SSL pinning functions with a tool such as Frida to effectively render pinning useless, but in order to do so you must disable System Integrity Protection (SIP), otherwise, Frida cannot hook to the process properly and will throw an error. 18 | 19 | **iOS**: Using a jailbroken device, you may use Frida or [SSL Kill Switch 2](https://github.com/nabla-c0d3/ssl-kill-switch2) to bypass the SSL pinning. 20 | 21 | **Important Note**: Regardless of what application or process you want to analyze, if you're after GSA traffic, you need to hook into Auth Kit Daemon (AKD). This process is entirely responsible for all GSA protocols. The process will be titled `akd`. If you're going to use SSL Kill Switch 2 on iOS, then akd is launched before it can be hooked, which means that you'll need to execute a kill -9 command to kill akd and have it restart so that SSL Kill Switch 2 can properly hook it next time. 22 | 23 | 24 | ## Python Script 25 | 26 | The python script in this repository can successfully execute one of the first steps towards proper authentication via the GSA protocol (getting s, B to make the M1 parameter as well as getting the c parameter), but it may not provide much help in getting past any further for reasons explained below. Nevertheless, the first step can be considered complete and this provides a nice overview of how some parameters such as the a2k are generated. 27 | 28 | Note: If you're going to utilize this Python script, please be sure to modify some of the other parameters under cpd, also known as the Anisette data. This includes X-Mme-Device-Id (Device UDID) and X-Apple-I-SRL-NO (Device Serial Number) to name a few. 29 | 30 | ## Limitations 31 | 32 | I have not been successful in terms of getting an M2 token when trying to recreate the second GSA request. According to some online sources, the `X-Apple-I-MD` parameter is time-sensitive and lasts only about 30 seconds. The first step in getting a full implementation would be to figure out how this is generated. 33 | 34 | Because it is difficult to analyze Apple's binaries to get this information, some people have resorted to hooking into Apple's AFD binaries to call the function that generates the `X-Apple-I-MD` token and extracting it for utilization. In a future update, I will likely incorporate support for this. 35 | 36 | ## Contributions 37 | 38 | Contributions in the form of issues or pull requests are always welcome. It may take a community-led effort to get the whole process completed. 39 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | srp 2 | requests 3 | backports.pbkdf2 4 | --------------------------------------------------------------------------------