- Justine Osborne (www.isecpartners.com)
- Ryan McGeehan (Facebook)
Secure Application Development on Facebook
This document provides a basic outline/best practice for developing secure applications on the Facebook platform. Facebook applications are web, desktop, or mobile applications that make use of the Facebook API to integrate tightly with the social network experience.
This document is designed for the Facebook developer, but it can also be used as a reference for non-technical readers. Depending on the reader’s level of technical understanding of security vulnerability classes and the Facebook platform, sections of the document may be skimmed or skipped.
Overview of the Facebook Platform
The Facebook application developer has many choices in how they integrate into the Facebook platform with their application. It is important to understand the basic elements of the platform before diving into the details of Facebook application security, as each method of integration has different security properties. If you are already familiar with the Facebook platform components, feel free to skip this section. There are two main categories of Facebook applications: Platform applications and Facebook Connect applications. Both types of application can use Facebook markup and scripting languages, as well as a REST client to access the Facebook API. Facebook Connect applications communicate with Facebook through crossdomain communication channels. Platform applications communicate directly with the Facebook servers. The following terms will be referenced when discussing Facebook applications:
The application canvas is the page on Facebook servers where an application lives. Application canvas pages are accessed through the apps.facebook.com domain. For example, the application canvas URL for a fictional game called “Goatworld” might look like this: http://apps.facebook.com/goatworldgame/ . The application canvas page will either be Facebook markup language or an external site hosted within an IFRAME.
Canvas callback URL
The canvas callback URL is the file or directory on the developer’s application servers where the application files are hosted. Facebook proxies the content from the canvas callback URL to the application canvas page.
Post-Authorize callback URL
The callback URL is a page on the developer’s servers which is pinged by Facebook each time a user authorizes the application. Platform applications Platform applications run in a sandbox and are accessed through the application canvas page. There are two types of platform applications that use different methods for sandboxing, including FBML and IFRAME.
Facebook Connect Applications
The first step in securing any application is to outline the required security guarantees your application needs to make, and then to select mechanisms that support those guarantees. For a Facebook application, the security challenges are slightly different than a regular application. The following is a non-exhaustive list of important items that a Facebook application developer has to keep in mind when thinking about security:
Protect access to the Facebook user account
When a user authorizes your Facebook application, they have permitted your application to obtain access to their Facebook account. The application is granted read access to profile data, friend information, and photo albums. The application can also be granted write access to the user profile, status updates, notifications, and the ability to send emails to the user, when the user grants the application the privilege to access restricted Facebook APIs. The application must be as resilient as possible against attacks which could compromise the application's access to a user’s Facebook account through the trust the user has granted the application.
In order to respect the user’s trust in your application, as well as to keep your application from being removed by Facebook, it is very important to adhere to Facebook’s privacy guidelines. Facebook denotes what user data is allowed to be stored by your application and for how long. When you do store Facebook account data, use sufficient access controls to guard this data from anyone but the legitimate, authenticated user. More information about privacy and storable user data can be found here: http://wiki.developers.facebook.com/index.php/Understanding_User_Data_and_Privacy http://wiki.developers.facebook.com/index.php/Storable_Data
Protect application-specific user account data and state
Make sure you understand the differences between how Facebook applications and traditional applications approach authentication, authorization, and access controls. The application relies on Facebook to tell whether a user has been authenticated, as well as other information about the user’s session. It is your responsibility to ensure that this information has not been forged or tampered with, before calling Facebook APIs or returning Facebook data for the user.
Protect against common web application vulnerabilities
Protect against common web application vulnerabilities that put application specific data and servers at risk. The Facebook sandboxing of platform applications can sometimes be confused as a protection mechanism for the application. However, Facebook sandboxing only provides protection to Facebook servers. Application servers can be attacked directly, and the minor protection mechanisms the platform sandboxing provides can sometimes be bypassed. It is therefore just as crucial to guard your Facebook application against the same common vulnerabilities you would in a traditional application.
Maintain confidentiality and integrity guarantees when integrating Facebook with HTTPS sites
When integrating an HTTPS site with the Facebook platform it is important to maintain the confidentiality and integrity guarantees offered by the protocol, in spite of the fact that Facebook does not serve its own content over SSL. The application canvas page is not served over SSL, which implies that it is impossible to provide support for SSL communication in an FBML application. Facebook Connect does provide support for SSL. This will be important to take into account when deciding on your method of integration with the Facebook platform.
Important Rules to Follow
Before delving into the specifics, consider the following list of important rules for secure development on the Facebook platform. The remainder of this document will provide further detail on the vulnerabilities and protections referred to in each of these rules.
Your Facebook Application secret must be kept secret!
The Facebook Application secret is given to you upon registering your application, and it is used to authenticate requests to and from the application. If the secret is revealed to an attacker then they can forge requests to and from the application. Store the secret in a secure place (i.e. not hardcoded in the source or in source control repositories, such as SVN) and make it available to as few people as possible, such as net ops and dev leads.
Do not hardcode FB application secret
Check the Facebook signatures
The Facebook signatures that are sent with requests should always be checked in order to verify that the request has not been tampered with and was sent legitimately by Facebook. The signature is created by an MD5 hash of the request parameters concatenated with the application secret, which should only be known to the application developer and Facebook. This signature can in some cases also be checked to provide protection from Cross-Site Request Forgery (CSRF) attacks when it is sent in the GET or POST parameters.
Provide additional CSRF protection mechanisms
Provide additional CSRF protection mechanisms especially with Facebook Connect sites. It is recommended to implement a separate CSRF protection mechanism that is designed specifically to mitigate this vulnerability class. In Facebook Connect sites, the signature and parameters are sent as cookie values rather than as URL parameters. Therefore, these sites need additional CSRF protection as the signature will be automatically sent with the request, even if the request was forged by an attacker. This applies to platform applications which make use of features of Facebook Connect. In this case, the signatures will sometimes be sent as request parameters, and sometimes as cookie values.
Validate and perform output encoding of user controlled data
Configure restrictive crossdomain.xml policy file
The crossdomain.xml policy file must be restrictive in order to keep attackers from changing the flashvars passed to the SWF, potentially subverting verification of the Facebook parameters passed. The crossdomain.xml policy file should be as restrictive as possible to allow access only from the trusted domains that are necessary.
Lock down administrative functionality
Keep administrative functionality on an entirely separate domain, preferably available only internally. A common flaw in Facebook applications is that they allow access to the administrative functionality based on a white list of hardcoded Facebook IDs, and is accessible from the same domain as the application. This allows for XSS attacks to have an even more devastating effect and could make it easier to discover the structure of requests for CSRF attacks. Also, because Facebook does not use HTTPS, sessions of administrators may be hijacked and used to access the administrative functionality. Require additional authentication mechanisms for administrative functionality.
Common Vulnerabilities and Protections
The following section will cover a few common web application vulnerabilities where specific care needs to be taken in order to protect Facebook applications.
Authentication and Authorization
The API key
The application secret
The application secret is also distributed during application setup. This secret is used to authenticate the communication between Facebook and your application. The secret is private to your application and must never be revealed.
The session key
The session key is the key to a temporary session which expires after an hour or when the user logs out of Facebook. The session key is set by Facebook when a user authorizes the application. The session key is used to call API methods that require an active session. For example, and calls to friends.get require a session key to determine which user to retrieve the friends for.
The session secret
The Facebook parameters
Facebook passes parameters to the application with any requests that include the API key and the session key, as well as other values which provide information about the user and session. Facebook sends the parameters as part of GET requests for IFRAME applications and as part of the POST body for FBML applications. Different parameters will be set depending on the type of Facebook application and what the user is doing with the application.
The Facebook signature
One value included in the Facebook parameters is the signature, which is an MD5 hash of all the parameters concatenated with the application secret. The application uses this value to verify that the parameters were not tampered with and were really sent by Facebook. Conversely, the signature allows for Facebook to verify that API requests have not been tampered with and were legitimately sent by the application identified by the given API key. Authenticating Communications from Facebook
Authenticate any information received from Facebook
Authenticating information will ensure it was legitimately sent by Facebook and not spoofed or tampered with. When Facebook passes information about the user and session to your application in the Facebook request parameters or cookies, it may be tempting to use that information directly from the request. However, attackers can control this data to forge or tamper with all of the Facebook parameters sent in the request, excluding the signature. The signature cannot be forged, as it is generated with the application secret key which the attacker should not know. Before using the values of any of the parameters received from Facebook, re-calculate the expected signature and verify that it matches the signature sent with the request. In the event of a mismatch, reject the request entirely. Some of the functions in the PHP client do this automatically. For example, the function get_valid_fb_params from the Facebook PHP library will return the validated parameters.
Verifying and Generating Facebook Signatures
The chosen client library should have built in functions to verify and generate the signature, but it can also be preformed manually.
Detailed information on the signature verification process can be found here: [].
Signature verification using the application secret must never be done on the client side, as this would expose the secret. Always perform signature verification using server code. The signature verification process is different depending on the type of Facebook application: Platform applications – In platform applications, Facebook will send the signature and other parameters as part of the GET or POST request. The application should grab the Facebook parameters from the request parameters, and recalculate the expected signature value using the signature generation algorithm, or the built in function from the Facebook client in use. Facebook Connect Applications – For Facebook Connect applications the Facebook parameters are sent as cookies. To verify these parameters, the application must extract the values from the cookies and perform the verification using the signature algorithm. The Facebook PHP client supports cookie based signature verification and is well-tested. The verification method must be checked in any unofficial libraries you may decide to use. Facebook Connect applications do not need to verify the signature very often. The most common scenario which requires verification of the Facebook cookies is when the session is being transferred from the client side to use server side libraries. When this occurs, the application must verify the cookies sent with the session transfer request. Otherwise, a malicious user could tamper with their cookies in order to trick the server into believing they were another user. More information on server side integration with Facebook Connect applications can be found here: http://wiki.developers.facebook.com/index.php/Using_Facebook_Connect_with_Server-Side_Libraries .
Cross Site Request Forgery (CSRF)
CSRF vulnerabilities exist when an application sends predictably structured requests which update server side state. When such a request contains no unpredictable parameters, an attacker can create a forged version of the request and send it on behalf of arbitrary users, without their knowledge. . CSRF attacks and defense are described in detail in the following CSRF whitepaper: https://www.isecpartners.com/files/CSRF_Paper.pdf. This vulnerability class can be difficult to understand. One common example of a CSRF vulnerability and protection mechanism that we are all used to is the password update feature of many web applications. It is a common requirement that the user enter their current password as well as their new password in a password update form. This requirement is in fact a CSRF protection mechanism (as well as adherence to other design principles). Consider the case where the current password is not required when performing the update. In this case, an attacker could forge the request which updates the user password. If the attacker can get the victim to load the forged request in a browser with an active session on the site, the browser will send along the victim’s session cookies with the request. This can be done by placing the forged request as the source of an IMG tag or an invisible IFRAME in a place where users of the application are likely to browse to, or as link disguised with a tinyURL service in a Facebook status message or comment box. When the server receives the request, it will have no way of distinguishing the forged request from a request sent purposefully by the user. The server will thus perform the password update action and update the user account with the attacker supplied password. The victim will then be locked out of their account. Fortunately, most applications require the current password to be sent with password update requests. This way, if an attacker attempts to send a forged request on behalf of their victim, the request will fail because the attacker will not have the victim’s current password. While the user password can act as a CSRF protection mechanism, it would be unreasonable to require the user to enter their password each time they make a request which updates server side state. Fortunately, there are other ways to provide protection from this attack. General protection from CSRF attacks (recommended solution) To provide protection against request forgery, the application should include and require a CSRF prevention token in the request that is both unpredictable and uniquely tied to the user session and action. This token will be sent with every request which updates server side state. When the server receives a request, it can check for the appropriate token value. If the token is incorrect or does not exist, the request will fail. One way such a token can be generated is through the following algorithm: HMAC_sha1(action_name + secret, session_id). More CSRF token generation techniques can be found in the whitepaper referenced at the beginning of this section. This token can be sent in a hidden form field with each request. The server can then perform the calculation upon receiving the request and verify that the token sent with the request matches. Because the secret exists only on the server side, the attacker will have no way of formulating the token for use in a forged request. This is the recommended protection mechanism for CSRF attacks. However, in some cases the Facebook signatures can also provide protection from this attack. Protecting against CSRF attacks using the Facebook Signatures The Facebook signatures can provide protection from CSRF attacks, but they cannot be relied upon in all circumstances. The Facebook signatures are computed in a similar way to the recommended CSRF protection token algorithm; the signature is a cryptographic hash of the request parameters and a server side secret. Note that the use of the HMAC_sha1 hashing algorithm is significantly stronger than the MD5 hashing algorithm used by Facebook, which has been proven to be vulnerable to some attacks1. While the signature is an adequate CSRF protection token, there are a couple very important caveats to keep in mind if the Facebook signature is used as a CSRF protection mechanism: Facebook signatures cannot protect against CSRF attacks when sent as cookie values. CSRF protection tokens provide no protection when sent as cookie values. 1 http://www.win.tue.nl/hashclash/rogue-ca/ The browser will automatically send cookie values with the request, thus the attacker does not need to guess the value, and the structure of the request remains predictable. Facebook Connect applications send the signatures as cookie values, rather than request parameters. It is important to remember that these applications will have to provide a separate CSRF protection mechanism. This caveat highlights one of the reasons to implement a separate CSRF protection system that is designed specifically for this class of vulnerabilities. This way, code can be ported to different types of Facebook (and non-Facebook) applications and will still be protected from this class of attack. The Facebook signature is not sent with all requests. The Facebook signature is not always available for use as a CSRF protection token. If this is your chosen method to provide CSRF protection, you must analyze your application you must analyze your application for areas where the server side state is being updated, but the Facebook signature is not sent with the request parameters. These requests will have to be protected through a separate CSRF protection mechanism.
Cross Site Scripting (XSS)
Considerations for Flash Applications
There are a few things to keep in mind when creating Facebook applications with Flash. Some of the information in this section may overlap with other sections, but is presented from the perspective of Flash applications.
To better understand the issues facing Flash applications, let us consider a fictional Flash based iFrame platform application called “Goatworld”, which is a game where players build teams of goat buddies with their Facebook friends. Users can send goat buddy requests to their Facebook friends, and the more goat buddies the user has, the higher level they obtain in the game.
The application is built using Flash, and runs from a SWF hosted in an iFrame on the application canvas page. The Facebook parameters are automatically passed to the application in the GET request which retrieves the hosting iFrame. The hosting page takes these Facebook parameters and passes them to the Flash application as flashvars. The Flash application then uses these parameters to make calls to Facebook using the ActionScript API. When the game loads, the SWF uses the fb_sig_user parameter to discover the current user’s goat buddies, and then sets the player’s level accordingly. Unfortunately, the hosting page does not validate the Facebook parameters before passing them to the Flash application. This allows an attacker to intercept the request to the hosting page, and change the fb_sig_user parameter to that of a different Facebook user, who has many goat buddies. Then, when the Flash application makes the call to retrieve the user’s goat buddies, it will retrieve the list of the other user’s friends. This allows the attacker to discover the Facebook friends of other users, in addition to providing them with a way to cheat in the game. This exemplifies that the Facebook signature must always be verified when trusting the Facebook parameters. However, there are also other ways that an attacker can manipulate the flashvars passed to a SWF. This has to do with the crossdomain communication policy configuration.
By default, the Flash runtime enforces the same origin policy and SWFs are only allowed to connect back to their domain of origin. If the SWF needs to communicate to servers other than its domain of origin, the crossdomain.xml policy file must be in place to grant access. The crossdomain.xml policy will grant communication to that server from SWFs hosted on the domains specified. When a SWF attempts to make the connection, it will check for the crossdomain.xml file in the web root of the domain it is attempting to connect to. It is very important to properly configure this policy file so that it restricts the access it allows.
A dangerously configured crossdomain.xml is as follows:
<cross-domain-policy> <allow-access-from domain="*"/> </cross-domain-policy>
This dangerous configuration allows access from any domain, effectively enabling Flash content on any site to attack your application. This would allow an attacker to host your SWF on their site, and although the SWF’s domain of origin is now the attacker’s, the SWF can still make calls back to its original domain because of the badly configured crossdomain.xml file in place. This gives the attacker control of the flashvars the SWF uses, and would allow the attacker to, for example, provide a different value for the fb_sig_user parameter and other Facebook parameters passed to the SWF. This also allows any domain to make crossdomain AJAX calls to your server, read data, and send custom headers with requests. This can lead to a whole host of serious issues.
Only configure a crossdomain.xml file that grants access only the specific, trusted, domains the SWF needs to connect from.
For example, consider a SWF whose domain of origin is sometimes foo.example.com, and sometimes bar.example.com, but it always needs to call back to code on example.com. The policy file hosted at example.com should then look like this:
<cross-domain-policy> <allow-access-from domain="foo.example.com"/> <allow-access-from domain="bar.example.com"/> </cross-domain-policy>
This will allow the SWF to be hosted at either the foo or bar sub domains, but will not allow it to be hosted at the attacker’s site. Furthermore, it will not allow arbitrary domains access to the server through crossdomain requests.
More detail on crossdomain.xml policy files can be found here: http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html .
More information on development using Flash can be found at http://www.adobe.com/devnet/facebook/ .
Secure transport using SSL
The HTTPS protocol provides the ability to transport information securely over the network using public key cryptography. The protocol provides confidentiality and integrity guarantees. When communicating over HTTPS, one can have some confidence on who they are talking to and that the data sent cannot be successfully tampered with. Without using HTTPS there can be no such guarantee. Facebook does not serve its own content over HTTPS. However, it is still possible to leverage the security benefits of an HTTPS site using Facebook Connect. The following guide discusses how to use Facebook Connect with an SSL site: http://wiki.developers.facebook.com/index.php/Facebook_Connect_Via_SSL. Areas of an application which deal with financial transactions, such as online payments, must use HTTPS to protect their communications. If you are writing a Facebook application that has a payments component, consider the following recommendations for integrating securely with Facebook.
Ensure that all sensitive API calls use HTTPS endpoints for client side applications
When making sensitive API calls, ensure that they are sent over HTTPS by calling them from an HTTPS endpoint. For example, the function auth.getSession returns the user’s session secret, which can be used to make sensitive API calls on behalf of the user. For client side applications, the session secret is used in place of the application secret, and therefore must be guarded carefully. Calls to auth.getSession should be made to an HTTPS endpoint, so that it will be returned to the client application over a secure connection. The same applies for other sensitive server side APIs.
Ensure that sessions with the secure site are initiated over HTTPS
When a Facebook platform application which is served over HTTP needs to direct the user to a secure site (for example to start a financial transaction), it is crucial that the session be initiated over HTTPS. A common mistake is to direct the user to the secure site using HTTP, and then internally redirect to the HTTPS connection after, without changing the session identifier. This is dangerous as it reveals the session identifier in the clear, before redirecting to the HTTPS site. In the best case, the secure site should not be accessible over HTTP at all.
Setting the Secure flag on cookies tells the browser to only send the cookie over an HTTPS connection. This will keep sensitive cookies from being revealed to network attackers. Not setting the Secure flag severely undermines the protections provided by HTTPS, as the secure session can still be compromised.
Because the Facebook platform is different than traditional application platform, securing administrative functionality can be confusing, and some compromises have to be made. Developers of a Facebook application can set certain users to be administrators and moderators of the application. There are certain API functions that can only be called by administrators. These functions provide the ability to perform administrative actions for the Facebook application, such as banning and unbanning users, setting application properties, and retrieving information about the applications usage statistics. It is tempting to include these functions in the same application canvas as the normal user functionality. Unfortunately, this design goes against the principle of least privilege. It is a best practice to keep the administrative functionality as separate as possible from the normal user application. For Facebook applications, the following recommendations should be considered in order to secure administrative functionality.
Any administrative pages must be served only over HTTPS in order to protect from local network attackers. This should be followed even if the administrative portion of the application is served only internally, to protect from rogue insider attacks. The application can still use the Facebook API by using Facebook Connect with SSL to authenticate and then transferring the session to the server side in order to make admin API calls which require the application secret. The session transfer process is described in detail here: http://wiki.developers.facebook.com/index.php/Using_Facebook_Connect_with_Server-Side_Libraries.
Host administrative functionality on a different domain than the normal application
It can be tempting to host the administrative portion of the application on the same domain as the rest of the application. One common scenario is to check if the Facebook ID sent with the request is an administrator’s ID and then to display the corresponding administrative functionality in the same Facebook canvas page as the rest of the application. This is not recommended as it can allow for XSS attacks to have a more devastating effect, and can make it easier for an attacker to discover the administrative pages in order to perform CSRF attacks. Instead, the administrative functionality should be hosted on an entirely separate domain. The application can still use the Facebook API by using Facebook Connect and transferring the session to the server side API for calls which require the application secret.
Make endpoints available internally only
The application should only be available on the internal network. As a rule, administrative interfaces should never be available from the internet. Internal only hosting will greatly increase the difficulty of attacking the application, as the attacker will first have to gain access to the internal network.
Require additional authentication
The administrative portion of the application can use Facebook Connect to log into the application via Facebook credentials. However, Facebook sessions are not secured over HTTP, so there is a potential for hijacking an administrators session. If an administrator’s session is hijacked by an attacker, they may be able to use that session to access the administrative functionality. In order to provide further protection, require administrators to log into the application using separate credentials.