Having covered the security assessment of Windows Phone applications in some detail, this chapter discusses important coding practices for writing secure apps in the first place. Where appropriate, we’ve given code examples for use in apps that generally need to be “secure.”
You should consider several points when designing and analyzing the security of an app. These can be summarized as follows:
Considering these general questions should make analyzing your app’s security and identifying areas that may require attention or further analysis easier to do.
When applications deal with sensitive data and need to store it for later use (or transmit it across a network), storing this data securely, using tried-and-tested crypto algorithms that are widely accepted as being secure, is important. The following subsections cover secure file storage and secure database storage, and we give examples of how we recommend applying encryption to data being stored in databases and flat files.
For storing data (or transmitting it), we recommend the use of AES-128 (Advanced Encryption Standard) at minimum (though preferably AES-256), not in ECB mode. CBC mode is a sensible choice.
We also advise against using ciphers such as Data Encryption Standard (DES); sticking to the (at the time of writing) industry-standard AES algorithm is sensible and recommended, and being required to use anything else is rare.
Hard-coded IVs should not be used with CBC; IVs are not supposed to be secret, but they should be a unique, per-app instance.
Cryptographic keys must be generated securely. This means that non- cryptographically secure APIs such as System.Random
should not be used. For generating securely random keys, see the later section in this chapter, “Secure Random Number Generation.”
To generate keys based on a user-supplied secret, that is, a password, a recommendable choice is Password-Based Key Derivation Function 2 (PBKDF2). Basically, PBKDF2 generates a key from a password, which may be considered secure as long as the password is of sufficient length and the iteration count used is sufficiently high (10,000, for example).
.NET provides an API for PBKDF2; namely Rfc2898DeriveBytes
, for which you can find the full documentation at the following URL: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes%28v=vs.110%29.aspx
.
After keys have been generated, they should not be stored to the app’s local storage, because the compromise of a device (with or without full disk encryption) could result in disclosure of the crypto key. If the crypto keys are generated randomly and stored to the device, they should be “wrapped” (that is, encrypted) with a PBKDF2-generated key derived from a user-known secret. If keys are generated directly from PBKDF2, no need exists to store them.
As we said in “Safe Encryption Ciphers and Modes”, above, when applications need to store sensitive data to the device as files, such data should be stored in encrypted form; we recommend using AES-256 in CBC mode.
The following code shows sample code for AES-256 CBC encrypt()
and decrypt()
functions, using the AesManaged
API:
public byte[] encrypt(byte[] dataIn, byte[] cryptoKey, byte[] iv)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
aes = new AesManaged();
aes.Key = cryptoKey;
aes.IV = iv;
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream,
aes.CreateEncryptor(), CryptoStreamMode.Write);
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
cryptoStream.Write(dataIn, 0, dataIn.Length);
cryptoStream.FlushFinalBlock();
// return encrypted data
return memoryStream.ToArray();
}
finally
{
if (cryptoStream != null)
cryptoStream.Close();
if (memoryStream != null)
memoryStream.Close();
if (aes != null)
aes.Clear();
}
}
public string decrypt(byte[] dataIn, byte[] cryptoKey, byte[] iv)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
try
{
aes = new AesManaged();
aes.Key = cryptoKey;
aes.IV = iv;
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream,
aes.CreateDecryptor(), CryptoStreamMode.Write);
// decrypt Data
cryptoStream.Write(dataIn, 0, dataIn.Length);
cryptoStream.FlushFinalBlock();
byte[] decryptBytes = memoryStream.ToArray();
//Dispose
if (cryptoStream != null)
cryptoStream.Dispose();
//Retval
return decryptBytes;
}
finally
{
if (memoryStream != null)
memoryStream.Dispose();
if (aes != null)
aes.Clear();
}
}
Each of the functions accept input data, a key, and an IV, all as byte arrays, and return the data resulting from the encryption or decryption as a byte array as well.
After encryption by the encrypt()
method, the resulting data can be stored using the standard file I/O APIs: StorageFolder
or IsolatedStorage
, and StreamReader
.
Applications may also use the standard Data Protection API (DPAPI) for data that will be stored locally. (If the data is transmitted to a remote host, the host would not be able to decrypt it, because only the local device knows the key.) However, there are certain cases against using it for apps requiring high levels of security, which were outlined in the Chapter 12 section, “Data Protection API Misuse on Windows Phone.” You can find the documentation for DPAPI at the following MSDN article: http://msdn.microsoft.com/en-us/library/windows/apps/hh487164%28v=vs.105%29.aspx
.
If you use DPAPI, we highly recommend using the optionalEntropy
parameter with a secret that only the app user knows.
Two database types find common usage in Windows Phone applications: Windows Phone native databases and SQLite-based databases. We cover how to apply crypto to each of these main types.
Creating encrypted local databases in a Windows Phone applications is fortunately very easy; you may simply use the Password
property in your database’s connection string:
string connectionString = "Data
Source='isostore:/ToDo.sdf';Password='myDatabasePassword'";
Developers should not, of course, hard-code the password; secure credential and key management principles should be adhered to. Applying database crypto in this way results in the database’s being encrypted via AES-128 in CBC mode. The key used is the SHA-256 hash of the password specified in the connection string’s Password
property.
A detailed discussion of Windows Phone local databases is beyond the scope of this section, but a short introduction appears in Chapter 12.
You can also consult MSDN’s introduction to local databases for a general example on implementing local database storage: http://msdn.microsoft.com/en-us/library/windows/apps/hh202860%28v=vs.105%29.aspx
.
The documentation at the previous URL also provides information on applying crypto to a database, as we’ve also done in this short section (http://msdn .microsoft.com/en-us/library/windows/apps/hh202860%28v=vs.105%29.aspx#BKMK_DatabaseSecurity
).
The two main options for applying crypto to databases that are SQLite in nature are SQLite’s SQLite Encryption Extension (SEE) and SQLCipher.
Each of these options is almost as simple to use as the standard Windows Phone SQLite options, although SEE requires some setup, including compilation of the distribution.
For general information on obtaining and using encrypted SQLite-like databases in your applications, consult SQLCipher’s or SEE’s documentation at https://www.zetetic.net/sqlcipher/
and https://www.sqlite.org/see/doc/trunk/www/readme.wiki
.
We’ve looked at how random numbers can be badly generated in some detail in Chapter 12’s section, “Insecure Random Number Generation.” In particular, we focused on how the .NET non-cryptographically secure random number generator—System.Random
—may introduce security bugs into apps that are supposed to be secure.
In the context of mobile applications, arguably the most common use case for random number generation is in the generation of crypto keys. In modern mobile computing, mobile apps often rely on data held in an app’s isolated storage as being secure, and as such, recovery of this data by attackers may potentially have very serious consequences.
System.Random
is not fit for generating cryptographically secure crypto keys. This short section gives positive examples showing how the RNGCryptoServiceProvider
API can instead be used for generating crypto keys. Of course, the same method may be used for generating random data for any other purposes.
RNGCryptoServiceProvider
does not have the same problems with predictability of outputted data that System.Random
does. Fortunately, as well, using RNGCryptoServiceProvider
is straightforward. Consider the following example for generating a 256-bit crypto key:
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] cryptoKey = new byte[32];
rng.GetBytes(cryptoKey);
// cryptoKey now holds 32 random bytes!
Although the RNGCryptoServiceProvider
API is significantly slower (some benchmarks estimate around 300 times slower), in the context of mobile applications, generation of crypto keys and other random data is generally a rare occurrence, hence the cryptographic security of the outputted data versus the speed of its generation is a trade-off that is absolutely worth it for apps that need to be secure.
The full documentation for the RNGCryptoServiceProvider
class appears on the API’s MSDN page at http://msdn.microsoft.com/en-us/library/system .security.cryptography.rngcryptoserviceprovider%28v=vs.110%29.aspx
.
When you’re handling sensitive data in memory, being able to wipe the memory when it is no longer immediately needed is sometimes desirable. Having sensitive memory secured is also desirable to lessen the chances of memory analysis attacks from gaining access to sensitive data in a process’s memory space. An example of such a piece of data would be a crypto key.
We advise that crypto keys be wiped from memory when they are not needed. Example scenarios for when to wipe a crypto key include:
In such cases, overwriting all elements of the byte array holding the crypto key is recommended. For example:
for(int i = 0; i < 32; i++) {
cryptoKey[i] = 0;
}
Of course, most Windows Phone applications are running in a runtime, and in theory the runtime might create additional copies of any objects, so clearing a byte array to rid the process of the data should be considered a “best effort” attempt.
One possible solution to this problem is to implement all crypto code as a native library and call into it from your C# code. The native library would deal with all crypto-related tasks, and then memset_s()
crypto keys and other sensitive data after its tasks are complete. (The _s()
prevents compiler optimization from removing the memset()
call.) The following URL provides a sample project for calling into a native library (written in C++) via managed C# code: https://code.msdn.microsoft.com/windowsapps/Windows-Phone-8-JumpStart-108965b9
.
If, however, your app is actually written as a native app, using memset_s()
on your sensitive crypto keys should be sufficient to ensure their deletion from your process’s memory space.
Bear in mind that string
objects are immutable, hence after values are held in these objects, the value cannot be cleared; the disposal of the object’s contents is at the discretion of the CLR’s garbage collector. Unfortunately, no secure equivalent, such as SecureString
, is currently supported on the Windows Phone platforms. Wherever possible, then, developers should attempt to use byte[]
and char[]
arrays instead of string
s, for storing particularly sensitive data such as passwords.
Removing sensitive data from the process’s memory is a best-effort attempt on the developer’s part. However, the object’s immediate removal is not guaranteed (that is, via garbage collection). When developers must use string
objects and want to have the content’s garbage collected and removed, they may consider setting the reference to null
, at which point they would call the garbage collector manually:
s = null; // set ref to null
GC.Collect(); // invoke GC
Note, however, that this does not guarantee that the object’s contents will be disposed of immediately, but it’s about the best a developer can do when using immutable objects.
When apps use Windows Phone local databases for storing their data in database format, there is no risk of SQL injection, because developers interact with the database via a LINQ-to-SQL layer, rather than talking to the database directly using SQL queries.
There may be risk of SQL injection, however, when SQLite databases are used; SQL injection is possible in Windows Phone apps when developers use SQLite (such as via sqlite-net) or SQLCipher. The following APIs are prone to being misused for SQL injection attacks:
db.CreateCommand()
db.Execute()
db.ExecuteScalar()
db.Query()
db.Query<T>()
db.DeferredQuery()
db.DeferredQuery<T>()
When developers want to execute raw queries instead of using abstraction layers to handle SQL statement construction, SQL injection bugs occur due to direct inclusion of attacker-controlled data into queries, instead of using parameterization for construction of the query.
For example, the following code fragment is vulnerable to SQL injection, assuming an attacker is in control of the attackerInput
string:
var db = new SQLiteConnection(Path.Combine(ApplicationData.Current.LocalFolder.
Path,
"test.db"));
[ ... ]
SQLiteCommand cmd = db.CreateCommand("select * from Stock where Symbol = '" +
attackerInput + "'");
// get all stock items with name in question
List<Stock> stockList = cmd.ExecuteQuery<Stock>();
In the preceding snippet, the attackerInput
string is included into the raw query by concatenation, thus any data in the attackerInput
string simply becomes part of the query itself, allowing the attacker to change the structure of the actual query.
Developers needing to construct raw queries for operations on their SQLite database should use the API’s parameterization features. The following code snippet shows how to construct the same query as earlier, without being vulnerable to SQL injection:
var db = new SQLiteConnection(Path.Combine(ApplicationData.Current.
LocalFolder.Path,
"test.db"));
[ ... ]
SQLiteCommand cmd = db.CreateCommand("select * from Stock where Symbol = ?",
attackerInput);
// get all stock items with name in question
List<Stock> stockList = cmd.ExecuteQuery<Stock>();
The emboldened "?"
character instructs the CreateCommand()
API to include attackerInput
as a parameter to the query, and as such, any data in attackerInput
will be correctly treated as data, rather than as part of the query syntax itself.
In general, however, we recommend that you use a data model approach, instead of constructing raw SQL queries if possible. Sqlite-net’s github README gives a simple example of how to do this at https://github.com/praeclarum/sqlite-net/blob/master/README.mdown
. The example is also applicable to SQLCipher, given the deliberate similarity of its API to other SQLite layers.
As with any application that requires secure network communications, mobile apps should also use secure communications channels for their network-based interactions. This section offers guidelines for secure network communications.
Using SSL/TLS for all network traffic that has the potential to contain sensitive information is now standard. In general, though, we recommend using SSL/TLS for all network communications, because interference on non-sensitive communications can also end up having security consequences; consider as-of-yet unknown parsing vulnerabilities, or HTML/JavaScript injection that facilitates phishing attempts, for example.
For carrying out any kind of web-based interaction, we recommend using https://
URLs, as opposed to http://
URLs, which result in traffic transmitted in unencrypted form.
When apps use WebBrowser
or WebView
components, pages should be loaded via https://
,
webBrowser.Navigate(new Uri("https://www.myapp.co.uk", UriKind.Absolute));
and never via http://
, as in this insecure example:
webBrowser.Navigate(new Uri("http://www.myapp.co.uk", UriKind.Absolute));
The same principles apply when making API requests using, for example, the WebRequest API; use SSL—as in,
string requestUri = "https://www.myapp.co.uk/webapi/getPost= + postId;
HttpWebRequest request =
(HttpWebRequest)HttpWebRequest.Create(requestUri);
[ ... ]
request.BeginGetResponse(GetPostCallback, request);
and not via the equivalent http://
URL.
SSL connections should be used for network interactions that are not HTTP-based. The following MSDN documentation details how to enable SSL/TLS for connections being made via Windows.Networking.Sockets
: http://msdn.microsoft.com/en-us/library/windows/apps/hh780595.aspx
.
Although it’s arguable that requests that do not deal with sensitive information do not need to be made via SSL/TLS sessions, data encryption is not the only security advantage of using encrypted tunnels. Use of SSL/TLS for non-sensitive communications should be encouraged because SSL/TLS guarantees the integrity of data being sent and received, guarantees the identity of the remote peer, and can prevent unanticipated attacker vectors that could occur as a result of an attacker’s being able to inject into a non-SSL/TLS’d stream (that is, phishing attempts or exploiting a bug in a library being used by an app, either directly or indirectly).
We therefore recommend the use of SSL/TLS for all network communications made by mobile apps, especially given that using smartphones on untrusted networks such as open Wi-Fi networks in coffee shops, bars, and in hotels has become very common. Some standard cell phone protocols, such as General Packet Radio Service (GPRS), also have known problems relating to forcing phones to connect to an attacker-controlled base station (http://blog.mdsec .co.uk/2014/11/44con-2014-greedybts-hacking-adventures.html
).
In general, the only sensible reason for disabling certificate validation in applications is that the application is in development, because many development environments do not have certificate authority (CA)-signed certificates installed on their infrastructure. In production, generally no good reasons exist for having SSL/TLS certificate validation disabled.
In Windows Phone 8, the HTTP APIs expose no documented way to disable certificate validity checks, thus ensuring that certificate validation is enabled is not generally a concern in Windows Phone 8 apps.
Windows Phone 8.1, however, does allow certificate validation to be turned off in Windows.Web.Http.HttpClient
objects, via use of an HttpBaseProtocolFilter
object. Code like the following disables certificate validation:
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
[ ... ]
var httpClient = new Windows.Web.Http.HttpClient(filter);
Developers preparing their applications for build and release should ensure that no HttpBaseProtocolFilter
object is being instantiated and used for disabling SSL/TLS certificate validation. Failure to ensure that certificate validation is turned on in production builds may endanger the data of app users, thus adding such checks to an engineer’s build checklist is highly encouraged.
In Chapter 12, we discussed how injection attacks into WebBrowser
and WebView
components could have serious security consequences. In particular, cross-site scripting attacks by suitably positioned attackers (that is, unencrypted Wi-Fi in coffee shops and hotels) could result in attacks such as cookie theft and phishing attacks. Because guarding against these attacks is important for secure smartphone apps, we offer guidelines for minimizing the risk of cross-site scripting in WebBrowser
and WebView
components.
When WebBrowser
and WebView
components fetch and render data via HTTP (and not HTTPS), the risk always exists of a suitably positioned attacker injecting data into the session. Such data could include JavaScript and HTML that sets up a phishing attempt, or JavaScript that attempts to steal a user’s session cookies could be introduced. Injected HTML and JavaScript could also attempt to exploit parsing vulnerabilities in the HTML and JavaScript engines themselves.
As mentioned earlier in this chapter, using SSL/TLS sessions for all communications, whether traffic is deemed to be sensitive or not, is advisable.
If a WebBrowser
control does not specifically require JavaScript to provide the app’s functionality, not enabling it is advisable. WebBrowser
components actually require JavaScript to be explicitly enabled for JavaScript to be executed in the first place.
JavaScript may be enabled via the IsScriptEnabled
property, either programmatically or in the appropriate XAML markup. The default is False
, but copying and pasting code examples from sites such as StackOverflow may result in some developers shipping apps that enable JavaScript without that particular intention.
If your app’s WebView
or WebBrowser
does not explicitly require JavaScript to be enabled, ensure that the app does not contain the following (on a non–case-sensitive basis), in any XAML pages, or in its codebase:
IsScriptEnabled="True"
Setting the IsScriptEnabled
property to False
explicitly for your WebBrowser
instances may be advisable, if you don’t need JavaScript, in case Microsoft changes the default to True
in the future. JavaScript can be explicitly disabled in the XAML page markup that the WebBrowser
component is contained within, i.e.,
<phone:WebBrowser Name="browser"
IsScriptEnabled="False"
ScriptNotify="browser_ScriptNotify"
Source="https://www.myapp.com"/>
Alternatively, the setting can be set programmatically on the object in question:
myWebBrowser.IsScriptEnabled="False"
Currently no documented way exists to disable JavaScript on a WebView
object, so a developer who does not require the use of JavaScript may consider using WebBrowser
in place of WebView
.
Some apps may construct HTML and JavaScript dynamically, often using data that is influenced or controlled by an attacker. For example, consider the following code fragment:
string someHtml = "<html><head><img src="attackerInfluencedValue"></html>";
[ ... ]
myWebView.NavigateToString(someHtml);
In such situations, developers must ensure that attacker-influenced values being inserted into dynamically-generated HTML and JavaScript code is sanitized so that attackers cannot control the syntax of the resulting code.
To prevent many cases of malicious content from being injected into HTML/JavaScript strings, use the HttpUtility.HtmlEncode()
API:
string someHtml = "<html><head><img src="" +
HttpUtility.HtmlEncode(attackerInfluencedValue) +" "></html>";
In such cases, the attacker’s string would be unable to break out of the src="..."
parameter, thus preventing scripting injection attacks.
Developers must also be careful in passing attacker-controlled values as JavaScript function parameters, however. Consider the following case:
string someHtml = "<html><head><script>someFunction(" +
attackerControlledString + ")</script><html>";
In this case, an attacker could, for example, pass alert(1)
in as attackerControlledString
, which would result in alert(1)
being executed before control is passed to someFunction()
.
To prevent such cases, enclose the attacker-controlled value in double-quotes, and also escape it to prevent escape from the double quotes:
string someHtml = "<html><head><script>someFunction("" +
HttpUtility.HtmlEncode(attackerControlledString) + "")</script><html>";
In the Chapter 11 we described how opening files in WebBrowser
and WebView
controls from the local filesystem could result in the theft of files from the app’s sandbox. In particular, this is possible because the same-origin policy allows access to documents that are from the same origin; in the context of a file loaded locally, this is the local filesystem.
Therefore, avoiding the construction or offline saving of web pages for future loading from the filesystem is advisable, unless you’re very careful in ensuring that their contents are safe.
It’s well understood in the computer security industry that the main risks around XML parsing is the resolution of Document Type Definitions DTDs)—particularly DTDs that refer to external entities such as local files and other URLs. External entity attacks can result in theft of files from the filesystem and may allow internal web services to be hit via URLs being resolved as external entities; both cases are obviously undesirable from a security perspective. Expanding DTDs can also result in denial-of-service (DoS) attacks, often called the “billion laughs” attack.
As we discussed in some detail in the Chapter 11 section, “Attacking XML Parsing”, the standard API for XML processing in Windows Phone apps is XDocument
and associated classes.
Fortunately for the Windows Phone developer, XDocument
objects do not parse DTDs by default, and as such, a developer must manually set an attribute on the object to enable such parsing. This, however, is possibly more common than expected, given that developers often copy and paste code from community contribution sites such as StackOverflow.
Developers and security testers should ensure that apps do not have code similar to the following, which enables DTD parsing:
var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse };
XmlReader xmlReader = XmlReader.Create("someFile.xml", settings);
// parse the XML file
XDocument xmlDoc = XDocument.Load(xmlReader);
If a device is compromised, an attacker may be able to gain access to cookies and the web cache that was acquired via the app’s web-based interactions. Compromising cookies may allow access to a user’s web session, and compromising the cache may result in disclosure of sensitive information to the would-be attacker.
From a security perspective, clearing cookies and the web cache when they are no longer needed, such as when an app’s screen lock is enabled, or when the user logs out of the app or the web interface it’s talking to, is therefore good practice. We’ll discuss here how you can do that.
Remove cookies from the device when they are no longer needed, because they may otherwise still be present in the app’s INetCookies
directory. The WebBrowser
control allows cookies to be deleted using the ClearCookiesAsync()
API:
await new WebBrowser().ClearCookiesAsync();
Note that the ClearCookiesAsync()
API may simply be called on any WebBrowser
component instantiated by the app, or statically, as in the previous code snippet.
There is also a way to delete cookies when WebView
is being used:
Windows.Web.Http.Filters.HttpBaseProtocolFilter myFilter = new
Windows.Web.Http.Filters.HttpBaseProtocolFilter();
var cookieManager = myFilter.CookieManager;
HttpCookieCollection myCookieJar = cookieManager.GetCookies(new
Uri("https://www.targeturi.com"));
foreach (HttpCookie cookie in myCookieJar)
{
cookieManager.DeleteCookie(cookie);
}
Here https://www.targeturi.com
is the URL for which cookies are to be deleted.
The most full-proof way of ensuring that none of your application’s web interactions result in cache storage to its INetCache
folder is to ensure that the web server being interacted with specifies appropriate non-caching directives in its HTTP(S) responses. For example, the following headers in HTTP(S) responses should be sufficient to prevent WebView
, WebBrowser
, WebRequest
(and other such classes) from caching data from any responses:
Cache-Control: no-store
Pragma: no-cache
The previous snippet represents our general advice for prevention of data caching.
When applications use a WebBrowser
control, you can programmatically delete that WebBrowser
’s cache, using the ClearInternetCacheAsync()
API. Refer to the API’s MSDN documentation at the following URL: http://msdn.microsoft .com/library/windows/apps/jj571213(v=vs.105).aspx
.
Unfortunately, at the time of writing, there is no documented way to programmatically clear a cache put in place by use of a WebView
. See the appropriate section at the following MSDN blog post: http://blogs.msdn.com/b/wsdevsol/archive/2014/04/03/ten-things-you-need-to-know-about-webview-_2d00_-an-update-for-windows-8.1.aspx#AN7
.
Because native code does not have the safety features of the Common Language Runtime (CLR) to protect it, Windows Phone applications written in native code (C, C++), or those calling into native modules, need to be carefully written to avoid native code vulnerabilities.
Native code components containing such vulnerabilities as memory corruption bugs (heap overflows, stack overflows, and so on), format string bugs, uninitialized variable use, and so on, may all fall prey to classic native code attacks.
Developers should therefore review their native codebases for dangerous API misuse and other insecure coding practices.
We recommend consulting the following resources for information on security coding guidelines for native code development, which are provided by CERT: C secure coding guidelines at https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Coding+Standard
and C++ secure coding guidelines at https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=637
.
We also recommend consulting Microsoft’s banned API list, which is offered as a C and C++ header file. You may obtain the file directly via the following URL: http://download.microsoft.com/download/2/e/b/2ebac853-63b7-49b4-b66f-9fd85f37c0f5/banned.h
.
Consider inserting #include
to place the file into your code for analysis purposes. The following resource discusses how to use banned.h
to analyze whether your codebase is misusing potentially dangerous APIs: http://blogs.microsoft .com/cybertrust/2012/08/30/microsofts-free-security-tools-banned-h/
.
Otherwise, you can manually analyze your app’s usage of APIs listed in banned.h
to ensure no API misuse could result in classic native code vulnerabilities.
As we already discussed in Chapter 10 and Chapter 11, Windows Phone supports several exploit mitigation features, including:
/GS
protections (stack cookies and other stack overflow protections such as variable reordering)NXCOMPAT
(DEP)/DYNAMICBASE
(ASLR)As per Visual Studio’s default settings, all of these are enabled on native binaries built from Visual Studio, hence unless these settings have been changed, your application’s native components should have these. Having exploit mitigation features significantly reduces the ease with which native code vulnerabilities may be exploited in vulnerable apps. Enabling them on all native binaries that are part of your app is highly recommended.
Microsoft released a useful tool named BinScope, available at http://www .microsoft.com/en-gb/download/details.aspx?id=11910
, for the purpose of analyzing native binaries to ensure that the recommended exploit mitigation technologies are enabled on the binary in question.
We recommend that developers run BinScope on all native binaries distributed as part of their applications. In any case, it appears that for Windows Phone 8.1 apps, Microsoft insists upon BinScope’s catalog of tests passing. See the following resource for further details: http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn629257.aspx#binscope
.
In this chapter, we’ve aimed to offer some key guidelines for implementing secure Windows Phone apps. We recommend following the guidelines when trying to implement Windows Phone applications with security requirements:
RNGCryptoServiceProvider
).18.216.239.46