-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS: Support for managing certificate authorities #44
Comments
I've documented the manual install process here: tweaselORG/meta#20 (comment) |
So, let's see how we can automate that. I would prefer to find a method that doesn't require Frida, but we'll see. My first approach: How does macOS store the CAs? Maybe it's similar for iOS. According to https://stackoverflow.com/a/24694579, macOS doesn't have a CA bundle like Linux. https://support.apple.com/en-us/HT208127 mentions a file
|
I also checked how you would add a CA on macOS using the command line. There is a According to https://derflounder.wordpress.com/2011/03/13/adding-new-trusted-root-certificates-to-system-keychain/, the root CAs are stored in While there is no
|
Let's see whether there's anything that helps us there:
|
Next try: I've used an improved version of my SQLite grep script to check if any database on the system contains a string that might be our certificate: # Adapted after: https://stackoverflow.com/a/53875499 and https://stackoverflow.com/a/29548123
NEEDLE="mitmproxy|begin certificate|MIIDoTCCAomg|IVCc6egf0T"
find / -name '*.db' -o -name '*.sqlite*' -print0 2>/dev/null | while IFS= read -r -d '' file; do
for X in $(sqlite3 -readonly "$file" .tables 2>/dev/null);
do sqlite3 -readonly "$file" "SELECT * FROM \"$X\";" 2>/dev/null | grep -iE >/dev/null $NEEDLE && echo "Found in file '$file', table '$X'";
done
done Result:
Values of each column:
|
CyberChef detected the |
We can get that really easily using openssl x509 -outform der -in ~/.mitmproxy/mitmproxy-ca-cert.pem -out mitmproxy-ca-cert.crt |
❯ sha256sum mitmproxy-ca-cert.crt
e487d9636b769d4582f1d5f44cbf23e985b698cf60b1417d891647ff74ad096d mitmproxy-ca-cert.crt |
|
Before I sink too much time into this, let's see whether I'm even on the right track (though I am pretty confident :D). On the other iPhone, I have not yet installed the CA. Settings -> General -> About -> Certificate Trust Settings shows no user certificates. And indeed, the If I copy the database with the mitmproxy cert from the other phone, now the mitmproxy cert does show up but is not trusted: So, I am definitely on the right track. \o/ |
Looks like somebody else already figured this out: https://github.com/ADVTOOLS/ADVTrustStore :( :D |
Here's how they get the Looks like there is no command in |
I've found PKI.js. As a reminder, we want:
With this, I'm almost there: import { readFile } from 'fs/promises';
import * as pkijs from 'pkijs';
(async () => {
const certDer = await readFile('mitmproxy-ca-cert.crt');
const c = pkijs.Certificate.fromBER(certDer);
console.log(c.subject.valueBeforeDecode);
})(); This outputs:
There's just two extra bytes at the beginning. |
ChatGPT says:
This seems really plausible! And indeed, it is correct. Great, that means we can just strip the first two bytes away. |
OK, actually tag and length can be longer than one byte:
For the tag, that doesn't matter for us. We always expect a sequence ( |
Turns out I was making this harder than it has to be. import { readFile } from 'fs/promises';
import * as pkijs from 'pkijs';
(async () => {
const certDer = await readFile('mitmproxy-ca-cert.crt');
const c = pkijs.Certificate.fromBER(certDer);;
const subjectSchema = c.subject.toSchema();
console.log(subjectSchema.valueBlock.toBER());
})(); Gives the desired result:
Side note: I had actually discovered
|
That only leaves trusting the certificate. I was pretty sure that this isn't handled by
This also works the other way around. |
Turns out, this is pretty easy as well. The column Here's the trusted version: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array/>
</plist> And here's the untrusted version: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>kSecTrustSettingsPolicy</key>
<string>1.2.840.113635.100.1.3</string>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>4</integer>
</dict>
<dict>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
</array>
</plist> EDIT: I had them the wrong way around. Curiously, the array is empty for the trusted one. |
I was able to successfully manually insert and trust the CA into an empty |
Hex literals in SQLite look like this: |
I was getting errors from execa about the certificate data ( The solution was simple: We're now encoding everything as hex in the command. .D |
Oh no, I just tried the new functions on the other iPhone with iOS 15, where I had never manually installed the CA, and while the CA now shows up under "Certificate Trust Settings", it is not trusted. :/ |
After I manually trusted the CA once, it now works automatically. Seems like at least some part of the trust status is stored elsewhere. This might explain why some people report that ADVTrustStore automatically trusts the CA, while other say the opposite (ADVTOOLS/ADVTrustStore#12). |
Interestingly, for a new CA, it works immediately. So, there seems to be some global "has the user ever trusted a root CA?" state. |
As this only requires a one-time action by the user, I'll not look into this right now but include a note. We can come back at some later point. |
Currently, this requires a one-time setup step for the added CAs to actually be trusted, we'll have to look into that later, see: #44 (comment)
Currently, this requires a one-time setup step for the added CAs to actually be trusted, we'll have to look into that later, see: #44 (comment)
Currently, this requires a one-time setup step for the added CAs to actually be trusted, we'll have to look into that later, see: #44 (comment)
Currently, this requires a one-time setup step for the added CAs to actually be trusted, we'll have to look into that later, see: #44 (comment)
I looked at what the Settings app does when trusting the first certificate. Apparently it calls
The question remains what the specifier is. I am not sure how to call these functions in frida, though. |
Bing Chat says:
|
Ok, I did some thinking and looking around and I am not sure if I can find out what setting we need to set so easily. Instead, I have considered looking into configuration profiles. Apple says (https://support.apple.com/en-us/HT204477):
So if we manage to deploy our certificates via a configuration profile this should be solved, shouldn't it? (Even though it bothers me that I would like to know what setting needs to be set) Now, as for installing configuration profiles I am not sure how easy it is to automate them. There is a PR in |
Before I sink even more time into this, i would like to decide whether we want to try configuration profiles. I feel like right now looking at frida trace is a shot in the dark and I could spend the time more productively in another way. What do you think, @baltpeter? What I like about configuration profiles is that they enable us to do all sorts of things, including setting the proxy or disabeling other settings. |
I assume that configuration profiles would work even without jailbreak? That would of course be a lot nicer. That being said, do you think that they would be a realistic path forward at this time, because I have some serious doubts about that. Looking at the limd PR you linked this doesn't seem like something we would realistically want to implement ourselves. But it also doesn't look like the PR is going to be merged anytime soon, does it? And even if it is merged, how long will it take until that feature arrives in the distribution packages? This seems like more of a potential for a better implementation in the long term and less like something we can do right now, to be honest. And have you checked what format these configuration profiles are? Can we feasible generate those? |
I don't actually think it is that hard to do. All we need to do is send some XML to the socket of the I also found this nice python library (https://github.com/doronz88/pymobiledevice3/) which implements everything we need from The configuration profiles are just |
Well, I tried around a little bit, first with Apple Configurator. I generated a configuration profile of the mitmproxy CA ceritificate: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadCertificateFileName</key>
<string>mitmproxy-ca-cert.cer</string>
<key>PayloadContent</key>
<data>
[base64 content]
</data>
<key>PayloadDescription</key>
<string>Adds a CA root certificate</string>
<key>PayloadDisplayName</key>
<string>mitmproxy</string>
<key>PayloadIdentifier</key>
<string>com.apple.security.root.EFF0CCD5-2798-497D-8813-5A7A1C526CB0</string>
<key>PayloadType</key>
<string>com.apple.security.root</string>
<key>PayloadUUID</key>
<string>EFF0CCD5-2798-497D-8813-5A7A1C526CB0</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>Untitled</string>
<key>PayloadIdentifier</key>
<string>Lorenzs-MacBook-Pro.6B40D2D8-E1E5-40E0-8F7F-2734C5A68E65</string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>1247ED2B-E6E5-4F4D-8291-01351B3F37EB</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist> Apparently, there still is some manual interaction required to install configuration profiles. The process is the same as it is for downloading a configuration profile from the internet and the certificate is not automatically trusted after the profile is installed. According to Apple Configurator, profiles are only automatically trusted if they are installed to a "supervised" device by the supervising computer. |
Enabling "supervised mode" is apparently pretty easy, you just have to switch a flag in You can do this using plutil from Sileo (and restart the launch daemon after that for the change to take effect):
This helps to enable more settings than were previously available, but the configuration profiles are still not automatically trusted. I think there needs to be some kind of signature thing that signs the configurations or something like this. I will supervise my other phone and try it out. |
As a sidenote, i think this way it should also be easy to enable/disable supervised mode from a (unencrypted) backup, by just editing this plist file, which would make setting this setting also possible for stock devices by backing them up and restoring a modified backup. |
After lots of struggle with the jailbreak on iOS 15.7.5, read out the
|
The
|
I tried signing a mobileconfig with the certificate in the hopes that this would install the certificate without interaction, but without luck. I tried: I noticed that for installed profiles, iOS creates
While for a configuration profile installed via Apple Configurator, it says:
So clearly, there is another way to install configuration profiles that I didn’t know about. root# ps ax | grep dmd
108 ?? Ss 0:00.70 /usr/libexec/dmd I tried to look at the network communication of configurator via usbmux by sniffing the loopnack traffic with wireshark like this (thanks to a Reddit tutorial):
But it seems like all the interesting traffic is of course TLS encrypted. Though I can confirm that Apple Configurator triggers some loopback traffic that originates from a port reserved for |
Just when I was about to give up, i reached a breakthrough. I had a look at the iPhone syslog while installing a profile via configurator, and it was actually informative:
Apparently, there is a request to
That didn’t work, there needs to be some form of authentication. Searching for |
I implemented silent profiles installs in pymobiledevice3: doronz88/pymobiledevice3#472 |
We already have that on Android (tweaselORG/meta#18 (comment)), now we also need to be able to add and remove root CAs on iOS.
The text was updated successfully, but these errors were encountered: