Scope and Environment
My focus was on the app itself. And I registered with linkedin as opposed to my work email. This had some limitations chief among which was restricted access to the members area. I also did not look at all the functionality. Instead I chose to look at what I considered to be the core components. And even then I did not cover everything.
My environment was as follows:
- Jailbroken iPhone 5S running iOS 9.3.3
- jtool
- IDA Pro
- Hopper
- BurpSuite Pro
- Frida
Jailbreak Detection
The first thing I noticed is that the app did not have any jailbreak detection routine. Now before you go crazy and be like "well that's not a security issue.." I tend to agree with you. I don't think lack of these type checks is a security issue per se. I think more in terms of it being a part of a broader defense in depth approach.
Certificate Pinning
The second observation is that the app did not check the authenticity of the remote endpoint by verifying its SSL certificate(Certificate Pinning); therefore its feasible to perform Man-in-the-Middle (MiTM) attacks to eavesdrop on and tamper with data. Let me hasten to say however that this is not as bad as it sounds because first the attacker would have to trick the user into installing a malicious certificate on the device and second - as you will see later on - the app encrypts the data it sends to the back end.
On a side note the argument that the attacker needs to first trick the user into installing a rogue CA is a common one. And yet while I agree there, there are tools that aim to simplify the process. This blog post from Sensepost is one such example.
On a side note the argument that the attacker needs to first trick the user into installing a rogue CA is a common one. And yet while I agree there, there are tools that aim to simplify the process. This blog post from Sensepost is one such example.
One final thing to note here regarding Certificate Pinning, is that the app provides two options for logging in: work email and LinkedIn Verification(see below). As I mentioned before I opted for the latter. A side effect of this choice was that because there was no pinning an attacker could capture the linkedin credentials. Provided of course you installed the malicious cert.
Login options |
Obtaining The Binary
Ok so with those "issues" out of the way let's obtain the binary and start reversing. I use the dumpdecrypted dylib. So I simply ssh'd into the device and ran the following:
root@Jekyl (/var/root)# su mobile
mobile@Jekyl (/var/mobile/Documents)# DYLD_INSERT_LIBRARIES=/var/root/dumpdecrypted.dylib /private/var/containers/Bundle/Application/3C411AB3-6018-4604-97D2-DC2A546EAB85/teamblind.app/teamblind
mach-o decryption dumper
DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.
[+] detected 64bit ARM binary in memory.
[+] offset to cryptid found: @0x1000d4f28(from 0x1000d4000) = f28
[+] Found encrypted data at address 00004000 of length 7995392 bytes - type 1.
[+] Opening /private/var/containers/Bundle/Application/3C411AB3-6018-4604-97D2-DC2A546EAB85/teamblind.app/teamblind for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a plain MACH-O image
[+] Opening teamblind.decrypted for writing.
[+] Copying the not encrypted start of the file
[+] Dumping the decrypted data into the file
[+] Copying the not encrypted remainder of the file
[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset f28
[+] Closing original file
[+] Closing dump file
Note that on iOS 9.3.3 running DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib from root results in the process you are injecting into being killed:
root@Jekyl (/var/root)# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /private/var/containers/Bundle/Application/3C411AB3-6018-4604-97D2-DC2A546EAB85/teamblind.app/teamblind
zsh: killed DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib
root@Jekyl (/var/root)#
The workaround is to first switch to mobile and then cd into /var/mobile/Documents as shown above. Note also that we are able to inject our own dylib because the BLIND app does not have the __RESTRICT Segment.
LC_SEGMENT_64 Mem: 0x100008000-0x100008000 __RESTRICT
Mem: 0x100008000-0x100008000 __RESTRICT.__restrict
This is a null segment (size 0) which serves to notify DLYD not to trust any DLYD* environment variables.
Identifying Endpoints
One of the things I usually do when looking at a binary is to dump the strings and search for URL endpoints. I then use that list to corroborate Burpsuite traffic.
macho-reverser:BLIND macho-reverser$ jtool -d __TEXT.__cstring teamblind.decrypted | grep "http"
Address : 0x1006dcfd0 = Offset 0x6dcfd0
0x1006df366: https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,headline,num-connections,industry,summary,specialties,positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,universal-name,type,size,industry,ticker,email-domains)),educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes),associations,interests,num-recommenders,date-of-birth,publications:(id,title,publisher:(name),authors:(id,name),date,url,summary),patents:(id,title,summary,number,status:(id,name),office:(name),inventors:(id,name),date,url),languages:(id,language:(name),proficiency:(level,name)),skills:(id,skill:(name)),certifications:(id,name,authority:(name),number,start-date,end-date),courses:(id,name,number),recommendations-received:(id,recommendation-type,recommendation-text,recommender),honors-awards,three-current-positions,three-past-positions,volunteer)?format=json
0x1006df80e: http://us.teamblind.com
0x1006e19ad: https://api.linkedin.com/v1/people/~:(id,email-address)?format=json
0x1006e75df: https://m.facebook.com/settings/email
0x1006e760c: https://www.linkedin.com/m/settings/email
0x1006ea5ec: https://docs.google.com/forms/d/e/1FAIpQLSc_J26TtkDL7HXcLeFXC2jy6lb1PmJSPnh51_ng7fr1638p_Q/viewform
0x1006ee9c3: https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=%@&scope=%@&state=%@&redirect_uri=%@
0x1006f4865: https://krapi.teamblind.com
0x1006f4881: https://usapi.teamblind.com
0x1006f489d: http://kr.stage.teamblind.com:8080
0x1006f48c0: http://us.stage.teamblind.com:8080
0x1006f48e3: http://dev.teamblind.com:8080
0x1006f4901: http://us.dev.teamblind.com:8080
0x1006f4922: https://kr.teamblind.com
0x1006f493b: https://us.teamblind.com
0x1006f4954: https://krnotifier.teamblind.com
0x1006f4975: https://usnotifier.teamblind.com
----
You can also use it to get a list of other potential targets as well. That leads us to Burpsuite. Let's fire it up and examine the traffic. Recall earlier I said that the BLIND app did not implement Certificate Pinning and that it wasn't all that of an issue because the app encrypted the data it sent to the backend. This is what a request looks like.
Sample request |
Extracting Classes
To answer those questions, let's first dump the classes and see if anything looks interesting. We start by listing the segments and there we see references to Objective-C:
macho-reverser:BLIND macho-reverser$ jtool -l teamblind.decrypted
LC 00: LC_SEGMENT_64 Mem: 0x000000000-0x100000000 __PAGEZERO
LC 01: LC_SEGMENT_64 Mem: 0x100000000-0x1007a4000 __TEXT
Mem: 0x100007a90-0x100663f18 __TEXT.__text (Normal)
Mem: 0x100663f18-0x10066723c __TEXT.__stubs (Symbol Stubs)
Mem: 0x10066723c-0x10066a560 __TEXT.__stub_helper (Normal)
Mem: 0x10066a560-0x100671ec0 __TEXT.__const
Mem: 0x100671ec0-0x1006dcfc9 __TEXT.__objc_methname (C-String Literals)
Mem: 0x1006dcfd0-0x10074ca58 __TEXT.__cstring (C-String Literals)
Mem: 0x10074ca58-0x100754bb2 __TEXT.__objc_classname (C-String Literals)
Mem: 0x100754bb2-0x100767daa __TEXT.__objc_methtype (C-String Literals)
Mem: 0x100767daa-0x100768e18 __TEXT.__ustring
Mem: 0x100768e18-0x100788c4c __TEXT.__gcc_except_tab
Mem: 0x100788c50-0x10078b967 __TEXT.__swift3_typeref
Mem: 0x10078b968-0x10078c6a0 __TEXT.__swift3_capture
Mem: 0x10078c6a0-0x10078d720 __TEXT.__swift3_fieldmd
Mem: 0x10078d720-0x10078e67d __TEXT.__swift3_reflstr
Mem: 0x10078e680-0x10078edc8 __TEXT.__swift3_assocty
Mem: 0x10078edc8-0x10078f3c8 __TEXT.__swift2_proto
Mem: 0x10078f3c8-0x10078f478 __TEXT.__swift2_types
Mem: 0x10078f478-0x10078f4dc __TEXT.__swift3_builtin
Mem: 0x10078f4dc-0x1007a3d20 __TEXT.__unwind_info
Mem: 0x1007a3d20-0x1007a4000 __TEXT.__eh_frame
LC 02: LC_SEGMENT_64 Mem: 0x1007a4000-0x100980000 __DATA
Mem: 0x1007a4000-0x1007a4ba8 __DATA.__got (Non-Lazy Symbol Ptrs)
Mem: 0x1007a4ba8-0x1007a6dc0 __DATA.__la_symbol_ptr (Lazy Symbol Ptrs)
Mem: 0x1007a6dc0-0x1007a6e00 __DATA.__mod_init_func (Module Init Function Ptrs)
Mem: 0x1007a6e00-0x1007cfd20 __DATA.__const
Mem: 0x1007cfd20-0x10080f300 __DATA.__cfstring
Mem: 0x10080f300-0x100811498 __DATA.__objc_classlist (Normal)
Mem: 0x100811498-0x1008114d0 __DATA.__objc_nlclslist (Normal)
Mem: 0x1008114d0-0x100811890 __DATA.__objc_catlist (Normal)
Mem: 0x100811890-0x1008118e8 __DATA.__objc_nlcatlist (Normal)
Mem: 0x1008118e8-0x1008123b0 __DATA.__objc_protolist
Mem: 0x1008123b0-0x1008123b8 __DATA.__objc_imageinfo
Mem: 0x1008123b8-0x10092bf38 __DATA.__objc_const
Mem: 0x10092bf38-0x100944b20 __DATA.__objc_selrefs (Literal Pointers)
Mem: 0x100944b20-0x100944c88 __DATA.__objc_protorefs
Mem: 0x100944c88-0x100946ee0 __DATA.__objc_classrefs (Normal)
Mem: 0x100946ee0-0x100948918 __DATA.__objc_superrefs (Normal)
Mem: 0x100948918-0x10094ee80 __DATA.__objc_ivar
Mem: 0x10094ee80-0x100965188 __DATA.__objc_data
------
We can therefore dump the classes and their methods using the objc option of jtool - JCOLOR=1 jtool -v -d objc teamblind.decrypted:
Extract class information with jtool |
Disassembling class info |
Ok so at this point we can intercept traffic, but alas, it's encrypted. And that's a bummer. Let's proceed with figuring out how the encryption is implemented. As you saw earlier, BLIND allows you to sign up using either your work email or linkedin. Past that screen that, you are presented with the Create Account option:
Sign Up |
plist snippet |
Now your email is no longer stored in plaintext but is encrypted(?), and your password, along with several other values get added. Keep in mind it's never a good idea to store passwords or anything sensitive for that matter in plist files. The astute reader would have noticed that I did not black out the password_enc value. The name of the key suggests the value might be encrypted since it ends with _enc, but is it? One other thing I want to point out is that this value is integral to the encryption process. But we will get to that later. For now let's dig into this value some more.
As it turns out the "encrypted" password is nothing more than an md5 hash, and you can see this in the requestPassword method of the AuthCompleteViewController class.
Create password hash |
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("password#1")
>>> print m.hexdigest()
5486b4af453c7830dcea12f347137b07
>>>
Identifying ViewControllers
If you are wondering how I determined what class to check, I first navigated to the Create Account page and then using cycript determined the ViewController like so:
root@Jekyl (/var/root)# ps aux | grep blind
mobile 4136 0.1 5.8 815696 59532 ?? Ss 4:10PM 0:06.85 /var/containers/Bundle/Application/3C411AB3-6018-4604-97D2-DC2A546EAB85/teamblind.app/teamblind
root 4139 0.0 0.0 657104 212 s000 R+ 4:11PM 0:00.01 grep blind
root@Jekyl (/var/root)# cycript -p 4136
cy# [[[UIWindow keyWindow] rootViewController] _printHierarchy].toString()
"<UINavigationController 0x15615d000>, state: appeared, view: <UILayoutContainerView 0x157415a30>\n | <RootViewController 0x1570db260>, state: disappeared, view: <UIView 0x157337ab0> not in the window\n | <AuthCompleteViewController 0x155f587c0>, state: appeared, view: <UIView 0x155da07a0>"
cy#
Recall as well that your was email encrypted. The encryption routine is also in the requestPassword method. Your email is first retrieved from the plist(NSUserDefaults) and then passed to the encryptHES256 method of NSString ([NSString encryptHES256:])
Get user email |
Encrypt user email |
With a little help from Frida we can see this in action. If you are not yet familiar with Frida I HIGHLY recommend that you familiarize yourself with it and add it to your arsenal. I cannot say enough about this tool. I also recommend checking out Frida CodeShare for ready to go scripts. Of course it goes without saying that you should review any code before running it.
Using Frida and the ObjC method observer script from CodeShare we can observe the AES256EncryptWithKey method in action:
macho-reverser:BLIND macho-reverser$ frida -U --codeshare mrmacete/objc-method-observer -f com.teamblind.blind
____
/ _ | Frida 10.6.15 - A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
Spawned `com.teamblind.blind`. Use %resume to let the main thread start executing!
[iPhone::com.teamblind.blind]-> %resume
[iPhone::com.teamblind.blind]-> observeSomething('*[* *AES256EncryptWithKey:*]');
(0x125fcdca0) -[NSData AES256EncryptWithKey:]
AES256EncryptWithKey: password#1^0123456789abcdefghijk
0x1001b25cc teamblind!0x11e5cc
0x1000e2c7c teamblind!0x4ec7c
----
Ok so we know how our password and email are encrypted. And by the way figuring out the other encrypted values is basically repeating the above steps. Let's now move to the actual traffic.
As we saw earlier - while monitoring the traffic sent from the device - all requests included a payload. I searched IDA for this string, and after going through the results, found that most of the request parameters were set in the -[NetworkControl encRequestWithParams:showAlert:completionBlock:failBlock:] method.
Payload string search |
The method first tries to retrieve a previously generated encryption key and initialization vector (iv), and if that fails it calls out to the makeKeyAndIvForEnc (-[EncriptControl makeKeyAndIvForEnc]) method of the EncriptControl class, and yes that is Encript with i. Security through obscurity maybe..... :)
Generating the encrypted payload |
This is where things get somewhat interesting, as it appears the encryption key is generated using a combination of the users password and some hardcoded value. Remember the encrypted password(password_enc) from earlier? The method will first try to retrieve it:
Retrieve encrypted password(password_enc) |
Generate some static value |
Generate second md5 hash |
Generate the actual key |
The remainder of the method just sets the initialization vector (iv):
Generate IV |
The encRequestWithParams method of the NetworkControl class calls makeKeyAndIvForEnc of the EncriptControl class to setup encryption. Once that is done the encRequestWithParams method goes on to call makePayloadDataWithJsonString of the EncriptControl class. This method then calls aesEncrypt from CocoaSecurity - using the encryption keys and IV from earlier - and returns the base64 encoded cipher-text which is what you see in Burp.
Encrypt the payload |
Encript instance variables |
if(ObjC.available){
var makeKandIv = ObjC.classes.EncriptControl["- makePayloadDataWithJsonString:"];
Interceptor.attach(makeKandIv.implementation, {
onEnter: function(args) {
/* Get Class/Params */
var obj = ObjC.Object(args[0]);
var params = ObjC.Object(args[2]);
/* Get ivars */
var ivar = obj.$ivars;
// Print ivars values
console.log("-----------------------------------------------------------\n");
console.log("_encKey: " + ivar["_encKey"] + "\n");
console.log("_encIv: " + ivar["_encIv"] + "\n");
console.log("_encIvStr: " + ivar["_encIvStr"] + "\n");
console.log("_encKeyForDM: " + ivar["_encKeyForDM"] + "\n");
console.log("_encKeyForDM: " + ivar["_encIvForDM"] + "\n");
console.log("-----------------------------------------------------------\n");
console.log("PARAMS: " + params);
},
onLeave: function onLeave(retval) {
console.log("Encrypted Payload: " + new ObjC.Object(retval).toString() + "\n");
}
});
}
And so our once encrypted burp traffic:
Now becomes:
Additionally, hooking the convertDictionaryEncWithResultStr: method of the EncriptControl class prints the plaintext server response. At this point you could consider using the Brida Burpsuite plugin for other options.
Conclusion
Well that's all I had for today. As I pointed out earlier I didn't register a BLIND account and so I didn't have access to the member's only section or other member only functionality. I didn't care to, either, I was just interested in the blob of data I saw going across the wires in the Burp. Given the nature and claims of the app I wanted to know more about what was happening under the hood. As such no malicious traffic was sent to the BLIND servers.
Happy hacking!!!
Disclaimer: This blog is intended for educational purposes only. Any actions and or activities related to the material contained within this Website is solely your responsibility.The misuse of the information in this website can result in criminal charges brought against the persons in question. This author will not be held responsible in the event any criminal charges be brought against any individuals misusing the information in this website to break the law.
Encrypted burpsuite traffic |
Plaintext data w/ encryption keys |
Conclusion
Well that's all I had for today. As I pointed out earlier I didn't register a BLIND account and so I didn't have access to the member's only section or other member only functionality. I didn't care to, either, I was just interested in the blob of data I saw going across the wires in the Burp. Given the nature and claims of the app I wanted to know more about what was happening under the hood. As such no malicious traffic was sent to the BLIND servers.
Happy hacking!!!
Disclaimer: This blog is intended for educational purposes only. Any actions and or activities related to the material contained within this Website is solely your responsibility.The misuse of the information in this website can result in criminal charges brought against the persons in question. This author will not be held responsible in the event any criminal charges be brought against any individuals misusing the information in this website to break the law.
This comment has been removed by the author.
ReplyDeleteAndroid Application Development HongKong,
ReplyDeleteHire Best iOS App Developers HongKong,
Best Mobile App Development Services HongKong,
Custom iPhone App Development Services Hong Kong
We are iPhone and iPad mobile app development experts with experience in catering to enterprises belonging to all domains.
ReplyDeleteThanks for sharing the knowledgeable stuff to enlighten us no words for this amazing blog.. learnt so many things I recommend everyone to learn something from this blogger and blog.. I am sharing it with others also..
ReplyDeleteWe are a professional training institute providing training under the following courses, if any one is looking for them click on the blink below:
Summer training in Lucknow
SAP training in Lucknow
SAP FICO training in Lucknow
Python Training in Lucknow
Advance Java Training in Lucknow
SEO Training in Lucknow
Digital marketing training in Lucknow
PHP Training in Lucknow
Android Training in Lucknow
am going to share it with others also, it is a nice article
Thanks for the great post on your blog, it really gives me an insight on this topic.
ReplyDeleteandroid app development services provider in pakistan
Nice blog With Great Tips
ReplyDeleteThanks For Sharing.....
Human Resource Professional Training in Lucknow
Best Graphic Design institute in Lucknow
Personality Development Training In Lucknow
Lucknow corporate training
Digital Marketing Training Institute in Lucknow
Nice Blog With Great Tips
ReplyDeleteThanks For Sharing......
Digital Promotion Company In Lucknow
Website development and Digital Marketing In Lucknow
Brochure Design Company In Lucknow
Motion Graphic Company in Lucknow
3D graphics company in lucknow
Graphic Design In Lucknow
3D Walkthrough Company
KloudWIFI truly believes that reliable, fast networks have been the game changers in driving innovation, productivity and instant collaboration supported by the relentless growth of convenient cloud-hosted applications. Even with a powerful, proven network infrastructure like Cisco Meraki and Ekahau, the end user experience can only be truly optimized by considering all the internal and external factors to the end user experiences. meraki insight partner in hyderabad
ReplyDeleteHi, I am Veronica Kate. I am working as a full-time academic consultant with Livewebtutors. We are providing paper editing service and Deakin Referencing Generator to university and college students across the globe. I have been successfully helping students, scholars and professionals in various services like I mentioned above for more than 5 syears and hold excellent writing, proofreading and editing skills. You would also find various academic tools on Livewebtutors like Paraphrasing Tool and Harvard Referencing Generator.
ReplyDeletekayseriescortu.com - alacam.org - xescortun.com
ReplyDeleteBest Casinos Near Atlanta, GA - MapYRO
ReplyDeleteLooking for Casinos Near Atlanta? · 895 Casino Hotel Dr, Council Bluffs, MS 38664 · Harrah's Cherokee Casino 강원도 출장안마 Resort · 울산광역 출장샵 Hampton Inn 의왕 출장샵 & 양주 출장샵 Suites Council Bluffs, 안산 출장샵
Mmorpg Oyunlar
ReplyDeleteINSTAGRAM TAKİPCİ SATİN AL
tiktok jeton hilesi
Tiktok jeton hilesi
Sac Ekim Antalya
İnstagram takipci
İnstagram takipçi satın al
Mt2 pvp serverler
Takipci
Smm panel
ReplyDeleteSmm panel
https://isilanlariblog.com/
İNSTAGRAM TAKİPÇİ SATIN AL
HIRDAVATÇI
beyazesyateknikservisi.com.tr
SERVİS
Jeton hile
çekmeköy beko klima servisi
ReplyDeletebeykoz daikin klima servisi
maltepe lg klima servisi
kartal toshiba klima servisi
ümraniye toshiba klima servisi
ümraniye beko klima servisi
beykoz alarko carrier klima servisi
üsküdar alarko carrier klima servisi
üsküdar daikin klima servisi
Thank you for sharing such a useful article. I had a great time. This article was fantastic to read. Continue to publish more articles on Earn free Roblox
ReplyDeleteExperience unparalleled performance and reliability with our top-tier best dedicated server Provider solutions. Discover the best provider today!
ReplyDeleteEscape to a luxurious resort in jaipur, where royal elegance meets modern comfort. Enjoy world-class amenities, serene landscapes, and unforgettable experiences.
ReplyDelete