17/04/2014

PHP Source Code Chunks of Insanity (Delete Post Pages) Part 4

Intro 

This post is going to talk about source code reviewing PHP and demonstrate how a relatively small chunk of code can cause you lots of problems.

The Code

In this article we are going to analyze the code displayed below. The code displayed below might seem innocent for some , but obviously is not. We are going to assume that is used by some web site to delete posts from the logged in users securely.
 <?php  
 require_once 'common.php';   
 validatemySession();   
 mydatabaseConnect();  
  $username = $_SESSION['username'];// Insecure source  
 $username = stripslashes($username);// Improper filtering  
 $username = mysql_real_escape_string($username);//Flawed function  
 // Delete the post that matches the postId ensuring that it was created by this user  
  $queryDelete = "DELETE FROM posts WHERE PostId = " . (int) $_GET['postId']. " AND Username = '$username'";  
  if (mysql_query($queryDelete))// Bad validation coding {  
       header('Location: myPosts.php'); }  
  else {  
      echo "An error has occurred.";   
      }  
 ?>  

If you look carefully the code you will se that the code is vulnerable to the following issue: SQL Injection!!
    
Think this is not accurate , think better.

The SQL Injection

An adversary in order to exploit this vulnerability would not have to script custom tools, would only have to have good knowledge of SQL injections methodologies and exposure to PHP coding.

Vulnerable Code:

1st Code Chunk 
 $username = $_SESSION['username'];// Insecure source  
 $username = stripslashes($username);// Improper filtering 
 $username = mysql_real_escape_string($username);//Flawed function  
2nd Code Chunk: 
 $queryDelete = "DELETE FROM posts WHERE PostId = " . (int) $_GET['postId']. " AND Username = '$username'";  
3rd Code Chunk:    
 if (mysql_query($queryDelete))  

The mysql_real_escape_string function is based in the black list mentality. What it does is that escapes special characters in the un-­‐escaped string, taking into account the current character set of the connection so that it is safe to place it in a mysql_query. More specifically mysql_real_escape_string calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters:

1. \x00 
2. \n
3. \r
4. \
5. '
6. “

7. \x1a.

Due to this odd behavior characters such as the % and SQL keywords are not being affected, so queries that have the form of e.g. SELECT BENCHMARK(50,MD5(CHAR(118))) would be executed normally. A realistic scenario would be to use a query such as the one below:

Step1: SQL Payload that would cause the post to delete without the postId be known. 
 LIKE %’s’  

Note1: At this point we assume that the attacker knows the format of the username e.g. its user plus a two-­‐digit number. 

Step2: SQL Payload mutated in order to bypass the filters.
 LIKE CHAR(37, 8217, 115, 8217)  

Note2: Further expanding on the attack if the Web App does not have a standard format for the usernames then the adversary can brute-­‐force the username first latter e.g. try out all English letters e.g. LIKE %’a’, LIKE %’b’, LIKE %’c’ ... etc. and eventually execute the query with a valid first username letter. Translating that to an obfuscated SQL Payload would be LIKE CHAR(39, 97, 37, 39), LIKE CHAR(39, 98, 37, 39) etc.

Note3: The mysql_real_escape_string function is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. Alternatives to this function include: mysqli_real_escape_string and PDO::quote. The mysql_query() function sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier. In this specific code example the query returns true if a record is found (any record). This obscure behavior introduces the vulnerability combined of course with the above code. The function used in the mysql_query statement should return a record set only if the correct record set is returned and not just any match.

Note4: This extension is deprecated as of PHP 5.5.0.

Remedial Code:

Provide Server Side filters filter for remediating the vulnerability. Make use of strongly typed parameterized queries (using the bind_param).
 // Using prepared Statements.  
 if ($stmt = $mysqli-­‐>prepare("DELETE FROM posts WHERE PostId = ? AND Username = ? LIMIT 1"))  
 {  
 $stmt-­‐>bind_param('s', $ username); // Bind "$ username" to parameter. 
 $stmt-­‐>execute(); // Execute the prepared statement.  
 ...  
 }  

15/04/2014

PHP Source Code Chunks of Insanity (Post Pages) Part 3

Intro 

This post is going to talk about source code reviewing PHP and demonstrate how a relatively small chunk of code can cause you lots of problems.

The Code

In this article we are going to analyze the code displayed below. The code displayed below might seem innocent for some , but obviously is not. We are going to assume that is used by some web site to post the user comments securely.
<?php require_once 'common.php'; validateMySession(); ?> <html> <head> <title>User Posts</title> </head> <body> <h1>Showing current posts</h1> <form action='awsomePosts.php'>
<p>MySearch: <input type='text'  value='<?php if (isset($_GET['search'])) echo htmlentities($_GET['search'])?>'></p> <p><input type='submit' value='MySearch'></p>
</form> <?php showAwsomePosts();?> </body>
</html>
If you look carefully the code you will se that the code is vulnerable to the following issue: Stored XSS!!
    
Think this is not accurate , think better.

The Stored XSS

An adversary would need to have very good knowledge of encoding/XSS attacks to exploit this vulnerability. This vulnerability is based on a well known UTF-­‐7 encoding attack that is considered to be old. Other filter bypassing techniques can be used to bypass htmlentities such as JavaScript events.

Vulnerable Code: 
1:  <p>MySearch: <input type='text' value='<?php if (isset($_GET['search'])) echo htmlentities($_GET['search'])?>'></p>// Vulnerable to XSS UTF-­‐7 attack  
The page that the potential XSS resides on doesn't provide a page charset header (e.g. header('Content-­‐ Type: text/html; charset=UTF-­‐8'); or <HEAD><META HTTP-­‐EQUIV="CONTENT-­‐TYPE" CONTENT="text/html; charset=UTF-­‐8">), any browser that is set to UTF-­‐7 encoding can be exploited with the following XSS input (she don't need the charset statement if the user's browser is set to auto-­‐ detect and there is no overriding content-­‐types on the page in Internet Explorer and Netscape rendering engine mode). This does not work in any modern browser without changing the encoding type.

Example1 UTF-­‐7 Encoding

Input Payload :

1:  <script>alert(1)</script>  

Output (UTF-­‐7): 
1:  +ADw-­‐script+AD4-­‐alert('XSS')+ADw-­‐/script+AD4APA-­‐/vulnerable+AD4-­‐  

Example2 JavaScript Events

Injecting also JavaScript events to the htmlentities function of php will also by pass the filter.

The code before injection:     
1<p>MySearch: <input type='text' value='<?php if (isset($_GET['search'])) echo htmlentities($_GET['search'])?>'></p>  

The code after injection:
<p>MySearch: <input type='text' value='onerror='alert(String.fromCharCode(88, 83, 83))'></p>  


Note: This example needs further testing to see if it is applicable.

Remedial Code:

Provide Server Side filters for the vulnerability. Make use of regular expressions and html encode the variables whether displayed back to the user or not.

1st Layer of defense 
1:  //XSS filter the value because this value might be printed later on back in the user. if preg_match ("/[a-­‐zA-­‐Z]+/", "", $search){  
2:  showPosts();  
3:  }  
Note: Using regular expressions to replace parts of the input and proceed with further processing the input is not recommended, once a malicious input is identified should be rejected (e.g. using preg_match instead of preg_replace).

2nd Layer of defense 
1:  header('Content-­‐Type: text/html; charset=UTF-­‐8');  
2:  // This function will convert both double and single quotes. mb_convert_encoding($search, 'UTF-­‐8');  


Countermeasures Summarized
  1. Specify charset clearly (HTTP header is recommended)
  2. Don't place the text attacker can control before <meta>
  3. Specify recognizable charset name by browser.
  4. Apply regular expressions based on the white list mentality.
Note: mb_convert_encoding converts the character encoding of the input string to the desired encoding. 

References:

1. https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#UTF-­‐7_encoding 
2. http://php.net/manual/en/function.mb-­‐convert-­‐encoding.php
3. http://shiflett.org/blog/2005/dec/google-­‐xss-­‐example
4. http://www.motobit.com/util/charset-­‐codepage-­‐conversion.asp
5. http://openmya.hacker.jp/hasegawa/security/utf7cs.html 
6. http://wiremask.eu/?p=tutorials&id=10 


PHP Source Code Chunks of Insanity (Logout Pages) Part 2

Intro 

This post is going to talk about source code reviewing PHP and demonstrate how a relatively small chunk of code can cause you lots of problems.

The Code

In this article we are going to analyze the code displayed below. The code displayed below might seem innocent for some , but obviously is not. We are going to assume that is used by some web site to de-validate the user credentials and allow the users to logout securely.

1:  <?php  
2:  require_once 'common.php';  
3:  if (isset($_SESSION['username']))//Insecure source  
4:  {  
5:  session_unset();// In properly destroyed session.  
6:  }  
7:  header('Location: index.php'); ?>  


I you look carefully the code you will se that the code is vulnerable to the following issues:
  1. NULL De-­Authentication Bypass    
  2. No Proper Session Termination    
Think this is not accurate , think better.

NULL De-­Authentication Bypass 

Exploitation:

An adversary may on purpose exploit this vulnerability possibly without the need of developing any costume tools (but needs a good understanding of PHP design flaws). More specifically an adversary can manipulate the cookie parameter and de-­‐validate the logout process by injecting a NULL value in the begging of the username (after the authentication). This would result into maintaining the user Web resources available for the specific session-­‐id even after the logout is performed. 

Vulnerable Code:    
if (isset($_SESSION['username']))// Malicious de-­validation cancel  
Assuming that the target username is user12 potential malicious payloads that could exploit the vulnerability displayed above would be user[space]12 , %4e%55%4c%4c,user12, user12[space], %20user12, [space] [space]user12 [space],user12 , user12, user12,, user12NULL NULLuser12 etc. This is applicable due to the fact that if multiple parameters are supplied then the isset will return TRUE only if all of the parameters are set. Evaluation goes from left to right and stops as soon as an unset variable is encountered. The attack should occur after the user successfully authenticates her self.

Note1: At this point it should be noted that when on, register_globals (which is on by default in PHP < 5.3.0), will allow an adversary to populate the cookie username variable from various user input such request variables from HTML hidden form fields, Web Application URL’s etc. which translates into working as a vulnerability amplifier! Also this might lead into allowing POST to GET interchanges, promoting CSRF like attacks (e.g. the web app does not distinguish POST from GET).

Note2: This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0. 

Remedial Code:
1:  //the filter makes sure the username has no spaces. if (strpos($username, " ") !== false){  
2:  // De-­‐validate the session  
3:  }  

2nd Code Chunk:
1:  trim("^$", $username)//Not recommended to process malicious payloads, only identify.  

Note: The NULL value translates into an empty string when validations come. 

No Proper Session Termination

An adversary may on purpose exploit this vulnerability without the need of developing any costume tools. This attack might be used to perform vertical/horizontal user escalation (e.g. the cookie session-­‐ id is assigned to a new user, and the new user automatically gains access to previous user Web resources, assuming that the Web Apps makes access control decisions by using only the session-­‐id. Another attack scenario would be that the session is leaked though a blog post and the adversary makes use of the non de-­‐validated leaked session to gain access to the Web Application user resources etc.).

Vulnerable Code: 
1:  session_unset(); // Improper handling of the session.  
Note1: The function shown above does not properly de-­‐validate the session. The session_unset function just clears the $_SESSION variable. It’s equivalent to doing $_SESSION = array(); So this does only affect the local $_SESSION variable instance, but not the session data in the session storage, everything else remains unchanged (including the session identifier). In this occasion the session_unset is used to destroy/reset the session instead of the session_destroy function in the logout page. The session_destroy() function destroys all of the data associated with the current session.

Note2: The variable session_unset is considered to be deprecated code that does not use $_SESSION.

Remedial Code: 
1:  function destroySession() {  
2:  $params = session_get_cookie_params(); setcookie(session_name(), '', time() -­‐ 42000,  
3:  $params["path"], $params["domain"],  
4:  ... );  
5:  session_destroy(); }  




References:

1. http://php.net/manual/en/security.globals.php
2. https://www.owasp.org/index.php/Unvalidated_Input
3. http://php.net/manual/en/function.isset.php
4. http://php.net/manual/en/function.trim.php 

14/04/2014

PHP Source Code Chunks of Insanity (Logins Pages) Part 1

Intro 

This post is going to talk about source code reviewing PHP and demonstrate how a relatively small chunk of code can cause you lots of problems.

The Code

In this article we are going to analyze the code displayed below. The code displayed below might seem innocent for some , but obviously is not. We are going to assume that is used by some web site to validate the credentials and allow the users to login.

 <?php  
     require_once 'commonFunctionality.php';  
        if (validateCredentials($someUsername, $somePassword)) {  
           header('Location: myIndex.php'); }  
        else {  
           header('Location: wrong_login.php'); }  
 ?>  

If you look carefully the code you will se that the code is vulnerable to the following issues:
  1. Reflected/Stored XSS
  2. Session Fixation/Session Hijacking 
  3. Lock Out Mechanism Not In Place
Think this is not accurate , think better.

Session Fixation/Session Hijacking

An adversary may on purpose exploit this vulnerability without the need of developing any costume tools (e.g. the session gets exposed in a blog post or within the same application or is passed in the http referrer and gets cached in a Web Proxy controlled by an adversary). Also this attack might be used to abuse user privileges (e.g. escalate privileges of one user by manipulating the session identifier, perform vertical and horizontal privilege escalation etc.). It should be noted at this point that the issues described above are possible only if the web application makes decisions based only on the session identifier.

Vulnerable Code:
session_unset(); // Improper handling of the session.  

Explanation:

The function shown above does not properly handle the session. The session_unset function just clears the $_SESSION variable. It’s equivalent to doing $_SESSION = array(); So this does only affect the local $_SESSION variable instance, but not the session data in the session storage, everything else remains unchanged, including the session identifier. In this occasion the session_unset is used to clear the session from user information, instead of the session_destroy function in the login page (instead of the logout page), which translates into not logging out properly the previous user (e.g. the next user will possibly again access to the account of the previous user).The Web Application makes decisions without evaluating other cookie parameters to give access to Web Resources (e.g. the decision making process is the username, a variable called logged_in and the session id). Ideally this should partly be fixed by using also another variable e.g. $_SESSION[‘logged_in’] = true (see code below). 

Exploitation:

An adversary may on purpose exploit this vulnerability without the need of developing any costume tools (e.g. the session gets exposed in a blog post or within the same application or is passed in the http referrer and gets cached in a Web Proxy controlled by an adversary). Also this attack might be used to abuse user privileges (e.g. escalate privileges of one user by manipulating the session identifier, perform vertical and horizontal privilege escalation etc.). It should be noted at this point that the issues described above are possible only if the web application makes decisions based only on the session identifier.

Business Impact:

The possibility of this vulnerability going public (e.g. blog posts start appearing in the internet revealing the issue) would cause severe costumer reputation and revenue loss; this vulnerability allows an adversary to potentially launch personalized phishing attacks (e.g. deceive a user in clicking a link with a fixed session etc.) abuse web application user privileges and possibly allow phishing campaigns. 

Remedial Code: 
 function init_session() { ...  
 session_start(); // Start the php session  
 session_regenerate_id(true); // regenerated the session, delete the old one. $_SESSION['logged_in'] = true;  
 ... }  
Regenerate the session ID anytime the session's status changes. That means any of the following:
  1. User authentication (e.g. in the login page, other multiple authentication stages etc.).
  2. Storing privilege level information in the session (e.g. temporary random variables, valid only
    for the current session etc.)
  3. Regenerate the session identifier whenever the user's privilege level changes. 
Lock Out Mechanism Not In Place

An adversary may on purpose exploit this vulnerability without the need of developing any costume tools (e.g. make use of Burp Intruder or Hydra to perform online password cracking attacks etc.).

Vulnerable Code:

 $username = $_POST['username']; $password = $_POST['password'];  
Note: The Web Application should implement server side controls in the login page to prevent password brute forcing attacks.

Remedial Code:


 function lockout($username, $password) { $now = time();  
 $counter = 0  
 if (validateCredentials){  
 $counter = $counter+1// Save that in database, retrieve login attempt times and compare the  
 times ...  
 } }  

The Web Application should take the following actions to prevent online dictionary attacks:
  1. Make use of login attempt counters (e.g. allow 3 failed attempts within 30 minutes).
  2. Associate the user IP with the session (e.g. generate proper audit trails to later on ban that ip).
    Include the user's IP address from $_SERVER['REMOTE_ADDR'] in the session. Store it in
    $_SESSION['remote_ip'].
  3. Run integrity checks of the session (although this functionality might be included in another
    function).
  4. Include the user agent from $_SERVER['HTTP_USER_AGENT'] in the session. Store it in a session
    variable $_SESSION['user_agent']. Then, on each subsequent request check that it matches (Note: The user agent can be very easily spoofed). 
Note: It should also be noted that since the session parameters are also populated with sensitive information such as the username, further actions should be performed to remove all this information (e.g. replace username with temporary user-­‐id). Gaining access to the username can significantly reduce a brute-­‐force login attempt. 

Reflected/Stored XSS

An adversary can exploit this vulnerability without the need of developing any costume tools. Point and click tools are available in the Internet and might be used to exploit this vulnerability (e.g. Social Engineering Tool etc.). Further escalating on the issue an adversary might use this attack to compromise multiple company sites (e.g. make use of it as an XSS proxy).

Note: This might also lead into unrestricted redirection attacks. Due to limited amount of time in my disposal no further investigation was conducted (e.g. load the login page to an Apache as and see if the variable username is passed the URL or the location header field.) 

Vulnerable Code:
 $_SESSION['username'] = $username;  

Note: Even though we don’t have access to the rest of the Web App code, it is highly likely that the username value might be displayed back to the user and the Http header fields. 

Remedial Code: 

Provide Server Side filters for the vulnerability. Make use of regular expressions and html encode the variables whether displayed back to the user or not (for providing security in depth and making sure that the Set-­‐Cookie header field or other fields cannot be abused).

1st Layer of defense

 $username = preg_match ("/[^a-­‐zA-­‐Z0-­‐9_\-­‐]+/", "", $username)  

Note: Ideally the username should be replaced with a temporary user id (preferable random that expires along with the cookie session). Using regular expressions to replace parts of the input and proceed with further processing the input is not recommended, once a malicious input is identified should be rejected (e.g. using preg_replace instead of preg_match). Also note that this functionality should ideally be also part of the validateCredentials function or the input should be processed before used by the validateCredentials function. 

2nd Layer of defense


1. // This function will convert both double and single quotes. 
2. htmlentities($username , ENT_QUOTES);  

Input: 
 <script>alert(1)</script>   

Output:
 &#x3c;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;&#x61;&#x6c;&#x65;&#x72;&#x7 4;&#x28;&#x31;&#x29;&#x3c;&#x2f;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;  


Note: With htmlentities, all characters which have HTML character entity equivalents are translated into these entities (displayed above). 

References:

  1. https://www.owasp.org/index.php/Account_lockout_attack
  2. http://stackoverflow.com/questions/17217777/difference-­‐between-­‐unset-­‐and-­‐session-­‐unset-­‐ in-­‐php
  3. http://shiflett.org/articles/session-­‐fixation
  4. http://shiflett.org/articles/session-­‐hijacking 

06/04/2014

Clickalicious Candies...

Introduction

This articles is written by me to show that Clickjaking should not be underestimated as a vulnerability, especially when combined with other vulnerabilities. Clickjaking (User Interface redress attack) is a malicious technique of tricking a Web user into clicking on something different from what the user perceives they are clicking on, thus potentially revealing confidential information or taking control of their computer while clicking on seemingly innocuous web pages. That is good in theory , but how can someone do that in practice? The answer is simple , ridiculously easy...



Even a script kiddy can become a "hacker" con-artist when combining  vulnerabilities. In this post I am going to show how a simple CSRF attack can actually be combined with a clickjaking attack, of course the same think can happen with vulnerabilities such as session fixation and XSS.

The Clickalicious Attack

In order to perform the attack we would have to be based in the following assumptions:
  1. We identified a website that is vulnerable to Clickjaking (e.g. is missing the X-Frame-Options) .
  2. The same Web Site is also vulnerable to CSRF (e.g. the CSRF is a simple html form). 
  3. The CSRF attack exploits a vulnerability that a malicious user can actually submit the form with polluted hidden form fields (for simplicity I am going to use a simple html form for the demo).   
Step 1: Frame the vulnerable web site to our iframe, in our example I am going to use www.w3sschools.com (such a lovely site).

 <iframe src="http://www.w3schools.com"></iframe>  

The visual outcome of this code wold be:


Note: The picture above displays only the iframe and not the whole page. In this particular example the html page was loaded from my hard disk.

Step 2: Project the CSRF to the vulnerable web site within the iframe created in Step 1. The simple source code to do that would be:

 <html>  
 <body>  
 <head>  
 <style>  
 form  
 {  
 position:absolute;  
 left:30px;  
 top:100px;  
 }  
 </style>  
 </head>  
 <form>  
 First name: <input type="text" name="firstname"><br>  
 Last name: <input type="text" name="lastname">  
 </form>  
 <iframe src="http://www.w3schools.com"></iframe>  
 </body>  
 </html>  

See the CSS absolute element? The CSS 2.1 defines three positioning schemes:
  1. Normal flow
  2. Absolute positioning
  3. Position: top, bottom, left, and right
Out of these three CSS features we are interested in the Absolute positioning feature. An absolutely positioned feature has no place in, and no effect on, the normal flow of other items. It occupies its assigned position in its container independently of other items.The visual outcome of this code wold be:


Note: The same exploit can be build using a stored XSS. The only difference would be that you would have to project the vulnerable CSRF within the space controlled by the XSS (without taking advantage of a Clickjaking vulnerability).

Tools such as NoScript would be able to detect the Clickjaking attack:


Note: See the icon stating that the script was blocked.

Epiloge

Next time you run a penetration test , think again before you characterize a Clickjaking as low!! especially if it is a login page. And be aware of the Script Kiddies.


The moto of this article is going to be think before you click...

References:
  1. http://www.w3schools.com/cssref/pr_class_position.asp 
  2. http://en.wikipedia.org/wiki/Cascading_Style_Sheets#Positioning

21/09/2013

The Hackers Guide To Dismantling IPhone (Part 3)

Introduction

On May 7, 2013, as a German court ruled that the iPhone maker must alter its company policies for handling customer data, since these policies have been shown to violate Germany’s privacy laws.

The news first hit the Web via Bloomberg, who reports that:

"Apple Inc. (AAPL), already facing a U.S. privacy lawsuit over its information-sharing practices, was told by a German court to change its rules for handling customer data.
A Berlin court struck down eight of 15 provisions in Apple’s general data-use terms because they deviate too much from German laws, a consumer group said in a statement on its website today. The court said Apple can’t ask for “global consent” to use customer data or use information on the locations of customers.
While Apple previously requested “global consent” to use customer data, German law requires that customers know in detail exactly what is being requested. Further to this, Apple may no longer ask for permission to access the names, addresses, and phone numbers of users’ contacts."

Finally, the court also prohibited Apple from supplying such data to companies which use the information for advertising. But why does this happen?

More Technical on privacy issues


Every iPhone has an associated unique device Identifier derived from a set of hardware attributes called UDID. UDID is burned into the device and one cannot remove or change it. However, it can be spoofed with the help of tools like UDID Faker.

UDID of the latest iPhone is computed with the formula given below:

UDID = SHA1(Serial Number + ECID + LOWERCASE (WiFi Address) + LOWERCASE(Bluetooth Address))

UDID is exposed to application developers through an API which would allow them to access the UDID of an iPhone without requiring the device owner’s permission. The code snippet shown below is used to collect the UDID of a device, later which can used to track the user’s behavior.

NSString *uniqueIdentifier = [device uniqueIdentifier]

With the help of UDID, it is possible to observe the user’s browsing patterns and trace out the user’s geo location. As it is possible to locate the user’s exact location with the help of a device UDID, it became a big privacy concern. More possible attacks are documented in Eric Smith-iPhone application privacy issues whitepaper. Eric’s research shows that 68% of applications silently send UDIDs to the servers on the internet. A perfect example of a serious privacy security breach is social gaming network Openfient.

OpenFeint was a social platform for mobile games Android and iOS. It was developed by Aurora Feint, a company named after a video game by the same developers. The platform consisted of an SDK for use by games, allowing its various social networking features to be integrated into the game's functionality. OpenFeint was discontinued at the end of 2012.

Openfient collected device UDID’s and misused them by linking it to real world user identities (like email address, geo locations latitude & longitude, Facebook profile picture) and making them available for public access, resulting in a serious privacy breach.

While penetration testing, observe the network traffic for UDID transmission. UDID in the network traffic indicates that the application is collecting the device identifier or might be sending it to a third party analytic company to track the user’s behavior. In iOS 5, Apple has deprecated the API that gives access to the UDID, and it will probably remove the API completely in future iOS releases. Development best practice is not to use the API that collects the device UDIDs, as it breaches the privacy of the user. If the developers want to keep track of the user’s behaviour, create a unique identifier specific to the application instead of using UDID. The disadvantage with the application specific identifier is that it only identifies an installation instance of the application, and it does not identify the device.

Apart from UDID, applications may transmit personal identifiable information like age, name, address and location details to third party analytic companies. Transmitting personal identifiable information to third party companies without the user’s knowledge also violates the user’s privacy. So, during penetration testing carefully observe the network traffic for the transmission of any important data.
Example: Pandora application was used to transmit user’s age and zip code to a third party analytic company (doubleclick.net) in clear text. For the applications which require the user’s geo location (ex: check-in services) to serve the content, it is always recommended to use the least degree of accuracy necessary. This can be achieved with the help of accuracy constants defined in core location framework (ex: CLLocationAccuracy kCLLocationAccuracyNearestTenMeters).

Identifying UUID transmission

Identifying if the UUID of the Iphone is transmitted is easy. It can be done through a Man In The Middle attack or a sniffer such as Wireshark. For example by using Wireshark to sniff traffic you can very easily identify if the UUID is transmitted if you follow the tcp stream.

Local data storage security issues

IPhone stores the data locally on the device to maintain essential information across the application execution or for a better performance or offline access. Also, developers use the local device storage to store information such as user preferences and application configurations. As device  theft is becoming an increasing concern, especially in the enterprise, insecure local storage is considered to be the top risk in mobile application threats.  A recent survey conducted by Viaforensics revealed that 76 percent of mobile applications are storing user’s information on the device. 10 percent of them are 
even storing the plain text passwords on the phone.

Sensitive information stored on the iPhone can be obtained by attackers in several ways. A few of the ways are listed below -

From Backups

When an iPhone is connected to iTunes, iTunes automatically takes a backup of everything on the device. Upon backup, sensitive files will also end up on the workstation. So an attacker who gets access to the workstation can read the sensitive information from the stored backup files.

More specifically backed-up information includes purchased music, TV shows, apps, and books; photos and video in the Camera Roll; device settings (for example, Phone Favorites, Wallpaper, and Mail, Contacts, Calendar accounts); app data; Home screen and app organization; Messages (iMessage, SMS, and MMS), ringtones, and more. Media files synced from your computer aren’t backed up, but can be restored by syncing with iTunes.

iCloud automatically backs up the most important data on your device using iOS 5 or later. After you have enabled Backup on your iPhone, iPad, or iPod touch in Settings > iCloud > Backup & Storage, it will run on a daily basis as long as your device is:

  • Connected to the Internet over Wi-Fi
  • Connected to a power source
  • Screen locked

Note:You can also back up manually whenever your device is connected to the Internet over Wi-Fi by choosing Back Up Now from Settings > iCloud > Storage & Backup.

Physical access to the device

People lose their phones and phones get stolen very easily. In both cases, an attacker will get physical access to the device and read the sensitive information stored on the phone. The passcode set to the device will not protect the information as it is possible to brute force the iPhone simple passcode within 20 minutes. To know more details about iPhone passcode bypass go through the iPhone Forensics article available at – http://resources.infosecinstitute.com/iphone-forensics/.

Malware

Leveraging a security weakness in iOS may allow an attacker to design a malware which can steal the files on the iPhone remotely. Practical attacks are demonstrated by Eric Monti in his presentation on iPhone Rootkit.

Directory structure

In iOS, applications are treated as a bundle represented within a directory. The bundle groups all the application resources, binaries and other related files into a directory. In iPhone, applications are executed within a jailed environment (sandbox or seatbelt) with mobile user privileges. Unlike Android UID based segregation, iOS applications runs as one user. Apple says “The sandbox is a set of fine-grained controls limiting an application’s access to files, preferences, network resources, hardware, and so on. Each application has access to the contents of its own sandbox but cannot access other applications’ sandboxes. When an application is first installed on a device, the system creates the application’s home directory, sets up some key subdirectories, and sets up the security privileges for the sandbox“. A sandbox is a restricted environment that prevents applications from accessing unauthorized resources; however, upon iPhone JailBreak, sandbox protection gets disabled.

When an application is installed on the iPhone, it creates a directory with a unique identifier under /var/mobile/Applications directory. Everything that is required for an application to execute will be contained in the created home directory. Typical iPhone application home directory structure is listed below.


Plist files

A property List (Plist file) is a structured binary formatted file which contains the essential configuration of a bundle executable in nested key value pairs. Plist files are used to store the user preferences and the configuration information of an application. For example, Gaming applications usually store game
levels and game scores in the Plist files. In general, applications store the Plist files under [Application's Home Directory]/documents/preferences folder. Plist can either be in XML format or in binary format.

As XML files are not the most efficient means of storage, most of the applications use binary formatted Plist files. Binary formatted data stored in the Plist files can be easily viewed or modified using Plist editors (ex: plutil). Plist editors convert the binary formatted data into an XML formatted data, later it can be edited easily. Plist files are primarily designed to store the user preferences & application configuration; however, the applications may use Plist files to store clear text usernames, passwords and session related information.

ICanLocalize

ICanLocalize allows online translating plist files as part of a Software Localization project. A parser will go through the plist file. It will extract all the texts that need translation and make them available to the translators. Translators will translate only the texts, without worrying about the file format.

When translation is complete, the new plist file is created. It has the exact same structure as the original file and only the right fields translated.

For example, have a look at this plist file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
  <key>Year Of Birth</key>
  <integer>1965</integer>
  <key>Photo</key>
  <data>
    PEKBpYGlmYFCPAfekjf39495265Afgfg0052fj81DG==
  </data>
  <key>Hobby</key>
  <string>Swimming</string>
  <key>Jobs</key>
  <array>
    <string>Software engineer</string>
    <string>Salesperson</string>
  </array>
  </dict>
</plist>

Note: It includes several keys and values. There’s a binary Photo entry, an integer field calls Year of Birth and text fields called Hobby and Jobs (which is an array). If we translate this plist manually, we need to carefully watch out for strings we should translate and others that we must not translate.

Of this entire file, we need to translate only the items that appear inside the <string> tags. Other texts must remain unchanged.

Translating as plist info

Once you’re logged in to ICanLocalize, click on Translation Projects -> Software Localization and create a new project.

Name it and give a quick description. You don’t need to tell about the format of plist files. Our system knows how to handle it. Instead, explain about what the plist file is used for. Tell about your application, target audience and the preferred writing style. Then, upload the plist file. You will see a list of texts which the parser extracted.


Note: Manipulating and altering the plist files can be done through the iExplorer. Simple download iExplorer open plist files, modify them and then insert them back again.

Keychain Storage 

Keychain is an encrypted container (128 bit AES algorithm) and a centralized SQLite database that holds identities & passwords for multiple applications and network services, with restricted access rights. On the iPhone, keychain SQLite database is used to store the small amounts of sensitive data like usernames, passwords, encryption keys, certificates and private keys. In general, iOS applications store the user’s credentials in the keychain to provide transparent authentication and to not prompt the user every time for login.

iOS applications use the keychain service library/API:

  • secItemAdd
  • secItemDelete
  • secItemCopyMatching & secItemUpdate methods

Note: These keywords can be used for source code reviews (identifying the location of the data)

These keywords are used to read and write data to and from the keychain. Developers leverage the keychain services API to dictate the operating system to store sensitive data securely on their behalf, instead of storing them in a property list file or a plaintext configuration file. On the iPhone, the keychain SQLite database file is located at – /private/var/Keychains/keychain-2.db.

Keychain contains a number of keychain items and each keychain item will have encrypted data and a set of unencrypted attributes that describes it. Attributes associated with a keychain item depend on the keychain item class (kSecClass). In iOS, keychain items are classified into 5 classes – generic passwords (kSecClassGenericPassword), internet passwords (kSecClassInternetPassword), certificates (kSecClassCertificate), keys (kSecClassKey) and digital identities (kSecClassIdentity, identity=certificate + key). In the iOS keychain, all the keychain items are stored in 4 tables – genp, inet, cert and keys (shown in Figure 1). Genp table contains generic password keychain items, inet table contains Internet password keychain items, and cert & keys tables contain certificates, keys and digital identity keychain items.

Keys hierarchy

Here is the keychain stracture:

  • UID key : hardware key embedded in the application processor AES engine, unique for each device. This key can be used but not read by the CPU. Can be used from bootloader and kernel mode. Can also be used from userland by patching IOAESAccelerator.
  • UIDPlus key : new hardware key referenced by the iOS 5 kernel, does not seem to be available yet, even on newer A5 devices.
  • Key 0x835 : Computed at boot time by the kernel. Only used for keychain encryption in iOS 3 and below. Used as "device key" that protects class keys in iOS 4.
  • key835 = AES(UID, bytes("01010101010101010101010101010101"))
  • Key 0x89B : Computed at boot time by the kernel. Used to encrypt the data partition key stored on Flash memory. Prevents reading the data partition key directly from the NAND chips.
  • key89B = AES(UID, bytes("183e99676bb03c546fa468f51c0cbd49"))
  • EMF key : Data partition encryption key. Also called "media key". Stored encrypted by key 0x89B
  • DKey : NSProtectionNone class key. Used to wrap file keys for "always accessible" files on the data partition in iOS 4. Stored wrapped by key 0x835
  • BAG1 key : System keybag payload key (+initialization vector). Stored unencrypted in effaceable area.
  • Passcode key : Computed from user passcode or escrow keybag BagKey using Apple custom derivation function. Used to unwrap class keys from system/escrow keybags. Erased from memory as soon as the keybag keys are unwrapped.
  • Filesystem key (f65dae950e906c42b254cc58fc78eece) : used to encrypt the partition table and system partition (referred to as "NAND key" on the diagram)
  • Metadata key (92a742ab08c969bf006c9412d3cc79a5) : encrypts NAND metadata




iOS 3 and below

16-byte IV - AES128(key835, IV, data + SHA1(data))

iOS 4

version (0)|protection_class - AESWRAP(class_key, item_key) (40 bytes)|AES256(item_key, data)

iOS 5

version (2) protection_class len_wrapped_key AESWRAP(class_key, item_key) (len_wrapped_key) AES256_GCM(item_key, data) integrity_tag (16 bytes)

Keychain tools


  1. https://github.com/ptoomey3/Keychain-Dumper/blob/master/main.m
  2. https://code.google.com/p/iphone-dataprotection/downloads/detail?name=keychain_dump


Notes

In the recent versions of iOS (4 & 5), by default, the keychain items are stored using the kSecAttrAccessibleWhenUnlocked data protection accessibility constant. However the data protection is effective only with a device passcode, which implies that sensitive data stored in the keychain is secure only when a user sets a complex passcode for the device. But iOS applications cannot enforce the user to set a device passcode. So if iOS applications rely only on the Apple provided security they can be broken if iOS security is broken.

Epiloge

iOS application security can be improved by understanding the shortcomings of the current implementation and writing one’s own implementation that works better. In the case of the keychain, iOS application security can be improved by using the custom encryption (using built-in crypto API) along with the data protection API while adding the keychain entries. If custom encryption is implemented it is recommended to not to store the encryption key on the device.

References:

  1. http://appadvice.com/appnn/tag/privacy-issues
  2. http://resources.infosecinstitute.com/pentesting-iphone-applications-2/
  3. http://cryptocomb.org/Iphone%20UDIDS.pdf
  4. http://en.wikipedia.org/wiki/OpenFeint
  5. http://resources.infosecinstitute.com/iphone-forensics/
  6. http://support.apple.com/kb/HT1766
  7. http://stackoverflow.com/questions/6697247/how-to-create-plist-files-programmatically-in-iphone
  8. http://www.icanlocalize.com/site/tutorials/how-to-translate-plist-files/
  9. http://www.macroplant.com/iexplorer/
  10. http://resources.infosecinstitute.com/iphone-penetration-testing-3/
  11. http://sit.sit.fraunhofer.de/studies/en/sc-iphone-passwords-faq.pdf