天天看點

Securely Developing on Mobile

More than ever, people are using their mobile device as their primary means of accessing the Internet. This provides not only unparalleled access to information, but also millions upon millions of applications built by third party developers. This platform

approach enables users to experience great apps built by developers both large and small. However, this decentralized platform approach only works if there are strong, industry-wide best practices around important app basics such as security. For this reason,

we applaud the Federal Trade Commission for hosting its Public Forum on Threats to Mobile Devices and thank them for including Facebook in this important meeting.

For everyone who couldn’t make the forum yesterday, we have documented some of the best practices for developing on Android and iOS, and we're excited to share them with other developers.

From the outset, it is important to note that making apps that are secure on Android and iOS is hard. When your application behaves in manner that is unintended, it creates security and privacy implications for the end user, and this might not be restricted

to the confines of your app, but potentially across the device. 

Top risks include malware installed on the phone alongside your app, tools that allow malicious actors to snoop on device activity, and even malicious websites that can trigger actions in your app using custom URL schemes.

The only way to ensure that your application is secure is to engineer your application for security from the ground up.

Here are some recommendations to reduce vulnerabilities in your application:

1. Use HTTPS in a secure way

HTTPS can help you protect the privacy of user data against a man-in-the-middle attack, which could manifest as snooping on data and stealing user sessions on the network. 

Android

Instead of using the SSLSocketFactory classes, you should use APIs like HttpsURLConnection, which are simpler to use and perform the correct verification steps on your behalf. HttpsURLConnection also adds features (including TLS tickets and SNI headers,

which only work correctly after Jellybean) to the HTTPS connection that gives you better performance than using raw SSL sockets. It should always be better to use this API. 

iOS

Similarly, on iOS it is preferable to always use the high level API NSURLConnection for network requests. Lower level APIs such as CFStream need explicit and often error-prone configuration of SSL.

Android and iOS

<a href="https://www.facebook.com/notes/facebook-security/securely-developing-on-mobile/10151408888270766#"></a>

2. There are No Client Secrets

Often, developers will spend time trying to obfuscate secrets in the application, which will be used to either authenticate their app to their server or to perform a client-side OAUTH flow.

a. Authenticating an app to your server

is an example of a large scale two-factor authentication solution that millions of people use daily.

b. OAUTH

Do not expose your OAUTH secrets to the world via your client application. Store the OAUTH secrets on your server so that they are indeed secret. To obtain an OAUTH token, the client would then request an end-point on your server that could proxy the token

request to the OAUTH provider with the secret, and then, return the token to the client. Once the client obtains the OAUTH token, it can directly make requests to the OAUTH provider.

3. WebViews

Some applications use Android WebViews and store cookies in the WebViews to access the remote servers. 

You should restrict the web-pages that can load inside your WebView with a whitelist. If you are only going to open pages from your domain in the WebView you should restrict those. 

In the simple case, a UIWebView is just a web browser tab sharing its cookie storage with the app. However, more complex interactions are often needed between the embedded JavaScript and the app. This is usually done by having the app catch and interpret

URLs of a special scheme in the outgoing requests of the WebView.

These interactions must be carefully reviewed. In particular,

a. if the webview is meant to browse the web, it should not be given large privileges over the native app;

b. if they include user-controlled strings (this typically includes the initial URL and any string injected in the Javascript environment using stringByEvaluatingJavaScriptFromString) make sure to sanitize the native inputs of webviews

4. Tap-Jacking

Other applications can overlay content over your application, and fool users into clicking buttons on your app underneath.

property to true in your views. This will prevent your application from getting touches when another application is obscuring it.

although this issue should concern only jailbroken devices.

5. Race Conditions onInstalling Apps

Permission stealing [Android]

Other apps that are installed before your app, could steal android permissions (including signature level permissions) that you have declared in your manifest by declaring them before you.

Your app will function normally, but as a result of this, malware that steals permissions could snoop into all of your app's content providers and other components. 

To prevent this, reduce both the exposure of components and also explicitly authenticate the callers of your components. 

Stealing of URL schemes [iOS]

Except for a core subset managed by iOS, URL schemes are registered on first-come, first-served basis.

6. Controlling Exposed Features

Activities, services and broadcast receivers  [Android]

You should aim to expose as little of your application as possible to other applications that are potentially malicious. Not setting intent-filters on components, or explicitly setting "exported=false," will cause components to be local to your application.

This is the most effective way of protecting components.

Make sure that before any action that changes the state of your app is taken, the user performs a UI action like clicking a button (this is analogous to CSRF protection in web applications). It is dangerous to perform a write action based on an intent extra

passed into a component.

Exposed URL schemes [iOS]

Similarly, iOS apps should not perform state-changing actions on processing URLs without asking for confirmation from the user.

7. Watch Out for Internal URL Schemes.

In addition to exposed URL schemes, it is common to define custom URL schemes internally to an iOS or Android app so as to let trusted sources trigger specific actions.

When using custom URL schemes in intent filters, be cognizant of the fact that they can be triggered by not only apps installed on the device, but also malicious websites that the user opens in the browser by simply clicking on a link. This triggers an ACTION_VIEW

intent for the URL that was clicked, so that the user does not need to install malware for the malware to exploit a particular component if it has another vulnerability.

Make sure to distinguish internal URLs created by trusted sources from public URLs callable by external apps or made clickable in user contents. The library class NSDataDetector does not restrict the schemes of URLs detected in user contents.

8. Authenticating Callers of Components

a. Activities

Consider calling activities that need to know their caller using startActivityForResult(). The calleeActivity can then enforce the identity of the caller using getCallingPackage()and ensures that is non-null and the package that it expects. A signature check

using PackageManager is the most effective way of ensuring the caller is from the same app family as the callee.

b. Content Providers

The user id of the caller can be obtained using Binder.getCallingUid(), and can be used for permission enforcement via signature checks.

c. Broadcast Receivers

There is no current way to get the identity of the initiator of the broadcast. For system broadcasts, ensure that you check the action string of the incoming intent to make sure an intent is coming from the system. 

d. Services

Services can enforce the callerusing Binder.getCallingUid() and using signature checks. However services using the messaging IPC mechanism cannot get the caller uid in the handleMessage() callback. Consider using AIDL-based service calls for exposed services.

Rather than UIApplicationDelegate:application:handleOpenURL:, you may want to implement UIApplicationDelegate:application:openURL:sourceApplication:annotation: and use the sourceApplication to authenticate a URL caller over time. To mitigate spoofing of

callers' URL schemes, the Facebook SDK also lets callers to the main app choose an encryption key for their response.

9. Use explicit intents andIntent hijacking [Android]

If private data is being transmitted in an intent, use explicit intents. Explicit intents ensure that the callee receiving the intent will be the one that the caller intended to receive the intent. 

Android provides ways to call components using implicit intents, however, keep in mind implicit intents could allow a malicious application to hijack the intent.

If using implicit intents, you should dynamically resolve the receivers of the intent and perform signature checks before sending the intent. "setPackage" is also an option, which restricts the package that can receive an intent. However, this works only

after Ice Cream Sandwich.

10. Open redirects

You could protect all your components with permissions and checks, however if there exists even one component in your application that takes a component as an input and redirects to that component, this could be used to circumvent all checks. Avoid this

practice at all costs.

11. SQL injection

SQLLiteQueryBuilder is a standard way of building SQL queries for Android. However even though it seems to be safe against SQL injection attacks, underneath the hood its imply concatenates strings. This allows attackers to insert arbitrary clauses into the

SQL statement.

You must carefully sanitize user input strings to content providers that are exposed.

You should refrain from constructing SQL query strings directly and instead use a more abstract framework such as EGODatabase or FMDB.

12. Language-Based Vulnerabilities[iOS]

Objective C is susceptible to a variety of programming errors that can be exploited:

* C fragments are vulnerable to the classical C vulnerabilities such as buffer overflows.

* Zombie objects may be exploited.

* User-dependent inputs occurring in format strings, selectors, or regular expressions may be exploited.

* It is important to keep in mind that static types appearing in the code are not enforced at runtime.

* Returning nil values on failures and unimplemented selectors is often ok. Yet, unexpected nil values can cause a crash with some library functions, and can yield unpredictable results in general (for instance [nil isEqualToString:nil] == 0).

繼續閱讀