PHP: Preventing Cross-Site Scripting Attacks

Fortunately, as easily as an XSS attack can carried out against an unprotected website, protecting against them are just as easy. Prevention must always be in your thoughts, though, even before you write a single line of code.

The first rule which needs to be “enforced” in any web environment (be it development, staging, or production) is never trust data coming from the user or from any other third party sources. This can’t be emphasized enough. Every bit of data must be validated on input and escaped on output. This is the golden rule of preventing XSS.

In order to implement solid security measures which prevents XSS attacks, we should be mindful of data validation, data sanitization, and output escaping.

Data Validation

Data validation is the process of ensuring that your application is running with correct data. If your PHP script expects an integer for user input, then any other type of data would be discarded. Every piece of user data must be validated when it is received to ensure it is of the corrected type, and discarded if it doesn’t pass the validation process.

If you wanted to validate a phone number, for example, you would discard any strings containing letters, because a phone number should consist of digits only. You should also take the length of the string into consideration. If you wanted to be more permissive, you could allow a limited set of special characters such as plus, parenthesis, and dashes which are often used in formatting phone numbers specific to your intended locale.

<?php
// validate a US phone number
if (preg_match('/^((1-)?\d{3}-)\d{3}-\d{4}$/'$phone)) {
echo $phone " is valid format.";
}

Data Sanitization

Data sanitization focuses on manipulating the data to make sure it is safe by removing any unwanted bits from the data and normalizing it to the correct form. For example, if you are expecting a plain text string as user input, you may want to remove any HTML markup from it.

<?php
// sanitize HTML from the comment
$comment strip_tags($_POST["comment"]);
?>

Sometimes, data validation and sanitization/normalization can go hand in hand.

<?php
// normalize and validate a US phone number
$phone = preg_replace('/[^\d]/'""$phone);
$len strlen($phone);
if ($len == 7 || $len == 10 || $len == 11) {
echo $phone " is valid format.";
}
?>

Output Escaping

In order to protect the integrity of displayed/output data, you should escape the data when presenting it to the user. This prevents the browser from applying any unintended meaning to any special sequence of characters that may be found.

<?php
// escape output sent to the browser
echo "You searched for: " . htmlspecialchars($_GET["query"]);

All Together Now!

To better understand the three aspects of data processing, let’s take another look at the file-based comment system from earlier and modify it to make sure it’s secure. The potential vulnerabilities in the code stem from the fact that $_POST["comment"] is blindly appended to thecomments.txt file which is then displayed directly to the user. To secure it, the$_POST["comment"] value should be validated and sanitized before it is added to the file, and the file’s contents should be escaped when displayed to the user.

<?php
// validate comment
$comment = trim($_POST["comment"]);
if (empty($comment)) {
 exit("must provide a comment");
}

// sanitize comment
$comment strip_tags($comment);
// comment is now safe for storage
file_put_contents("comments.txt"$comment, FILE_APPEND);
// escape comments before display
$comments file_get_contents("comments.txt");
echo htmlspecialchars($comments);

The script first validates the incoming comment to make sure a non-zero length string as been provided by the user. After all, a blank comment isn’t very interesting.

Data validation needs to happen within a well defined context, meaning that if I expect an integer back from the user, then I validate it accordingly by converting the data into an integer and handle it as an integer. If this results in invalid data, then simply discard it and let the user know about it.

Then the script sanitizes the comment by removing any HTML tags it may contain.

And finally, the comments are retrieved, filtered, and displayed.

Generally the htmlspecialchars() function is sufficient for filtering output intended for viewing in a browser. If you’re using a character encoding in your web pages other than ISO-8859-1 or UTF-8, though, then you’ll want to use htmlentities(). For more information on the two functions, read their respective write-ups in the official PHP documentation.

Bare in mind that no single solution exists that is 100% secure on a constantly evolving medium like the Web. Test your validation code thoroughly with the most up to date XSS test vectors. Using the test data from the following sources should reveal if your code is still prone to XSS attacks.

Advertisements

Helper class to manage HTTP POST requests in ANDROID

Its sometime needed to post certain data to the remote url via get or post method to send data for that we wrote some helper class to make that task easy

public class ServerCommunication { 
public static final String Logger = ServerCommunication.class.getName();
private static String slurp(InputStream in) throws IOException {
    StringBuffer out = new StringBuffer();
       byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1;) {
          out.append(new String(b, 0, n));
       }
     return out.toString();
 }
public static String post_string(String url, String urlParameters) throws IOException {
HttpURLConnection conn = null;
   try {
     conn = (HttpURLConnection) new URL(url).openConnection();
    } catch (MalformedURLException e) {
   Log.e(Logger, "MalformedURLException While Creating URL Connection - " + e.getMessage());
   throw e;
  } catch (IOException e) {
    Log.e(Logger, "IOException While Creating URL Connection - " + e.getMessage());
    throw e;
 }
  conn.setDoOutput(true);
  conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  conn.setRequestProperty("Content-Length", Integer.toString(urlParameters.length()));
  OutputStream os = null; 
  try {
      os = conn.getOutputStream();
  } catch (IOException e) {
     Log.e(Logger, "IOException While Creating URL OutputStream - " + e.getMessage());
     throw e;
  } 
  try { 
       os.write(urlParameters.toString().getBytes());
    } catch (IOException e) {
  Log.e(Logger, "IOException While writting URL OutputStream - " + e.getMessage());
  throw e; 
   }
  InputStream in = null; 
   try {
      in = conn.getInputStream();
   } catch (IOException e) {
     Log.e(Logger, "IOException While Creating URL InputStream - " + e.getMessage());
     throw e;
   }
    String output = null;
    try {
        output = slurp(in);
    } catch (IOException e) { 
      Log.e(Logger, "IOException While Reading URL OutputStream - " + e.getMessage());
      throw e;
    } finally {
     try {
      os.close();
      in.close();
      } catch (IOException e) {
      Log.e(Logger, "IOException While Closing URL Output and Input Stream - " + e.getMessage());
    }
  }
 conn.disconnect();return output;
}
}

Calling this method is easy

String url ="http://example.com/post/url/to/remote/server.php"
 Log.i(Logger, "URL : - " + url);
 TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
 String parameter = "userid=" + telephonyManager.getDeviceId(); // construct the parameter string
 String data = ServerCommunication.post_string(url, parameter);
 Log.i(Logger, "URL Result: - " + data);

It will return the url result as output so you can decide on server side which data to output, whether json or string or xml etc and proceed with reset things.

Enjoy the stuff

 

Android Save SD Card file to Remote server using PHP

In the previous post I explained about listing the specific extension files in Android list view. Now lets have a look to upload the file to remote server using a server side coding in PHP

private String SaveFileToServer() {
    String serverurl ="http://example.com/uploadfile.php"; // this is your server url to which you post the file contents
    String fileurl = "absolute_path_to_file_stored_on_sd_card"; // the path should be absoulute starting with /mnt/sdcard/filename.doc etc
  
    try {
      FileInputStream fis = new FileInputStream(new File(fileurl));
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      byte[] buf = new byte[1024];
      try {
        for (int readNum; (readNum = fis.read(buf)) != -1;) {
        bos.write(buf, 0, readNum); // no doubt here is 0
      }
   } catch (IOException ex) {
      ex.printStackTrace();
 }
 byte[] bytes = bos.toByteArray();
 byte[] filetosend = Base64.encode(bytes, Base64.DEFAULT);
 String fts = new String(filetosend);
 this.user.setBase_64_encoded_filestring(fts);
 String parameters = this.user.tofileString();
 try {
   this.message = ServerCommunication.post_string(serverurl, parameters); // this is custom function to post the data to post the remote url
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
 }
} catch (FileNotFoundException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
return this.message;
 }
}

After this lets have a look at server side php code that will accept the data save on server and in return give you full path for the file saved

<?php 
if(isset($_POST['filedata'])) $filedata=$_POST['filedata']; else $filedata=""; // check for filedata to save
if(isset($_POST['file_url'])) $filename=$_POST['file_url']; else $filename=""; // check for filename not empty
$filename=date("ymdhis")."-".$fname;// change the filename to append the timestamp to avoid overwrite
$location="../../files/".$filename;// decide the location
//now write the file
 $filedata1=base64_decode($filedata);
 $ftw=fopen($location,'wb');
 if(fwrite($ftw,$filedata1)) {
 $fileurl="http://www.example.com/files/".$filename;
 echo $fileurl;
 } 
 
 fclose($ftw);
 ?>

So on success it will give you full path as output which you can save in your ANDROID code for future refecence

The code was simple but I have done some modifications as per the requirement. Hope you find this useful, ENJOY the stuff.

Insert Multiple rows in SQLITE with Android

In past days i came across an issue in which i need to synchronize the local device database from the live database data for that I am using the traditional way to insert the data and then execute that statement in loop

At some times if the loop is longer then its creating an issue at some time.. means sometime its inserts 4 rows and then throws error for database connection failure, at sometime it inserts only a single row and throws error for database communication error, so the error is not predicted when and at which line it occur.

The after searching on google for specific keywords i found a good  example that explains how to use the insert helper provided by android to insert the data

 

Following are two code snippets that used first one is traditional way and another is using the insert helper

while(moreValuesToInsert) {
ContentValues values = new ContentValues();
 values.put(BMIDataSQLHelper.TIP_ID, json_data.getInt("id"));
 values.put(BMIDataSQLHelper.TIP_CONTENT, json_data.getString("message"));
 values.put(BMIDataSQLHelper.TIP_LOCATION, json_data.getString("location"));
 values.put(BMIDataSQLHelper.TIP_LIKE_COUNT, json_data.getInt("likecount"));
 values.put(BMIDataSQLHelper.TIP_SENDER_NAME, json_data.getString("name"));
 db1.insert(BMIDataSQLHelper.TABLE_TIPS, null, values);
}

The solution implemented as follows

 

import android.database.DatabaseUtils.InsertHelper; // import statement
InsertHelper ih = new InsertHelper(db, "TableToInsert"); initialize the helper with database object and table name
// Get the numeric indexes for each of the columns that we're updating
        final int col1 = ih.getColumnIndex("col1");
        final int col2 = ih.getColumnIndex("col2");
        //...
        final int col3 = ih.getColumnIndex("col3");
while (moreRowsToInsert) {
            // ... Create the data for this row (not shown) ...
 
            // Get the InsertHelper ready to insert a single row
            ih.prepareForInsert();
 
            // Add the data for each column
            ih.bind(col1, col1Data);
            ih.bind(col2, col2Data);
            //...
            ih.bind(col3, col3Data);
 
            // Insert the row into the database.
            ih.execute();
        }

So After implementing the solution the error for database communication error vanished away.