Cyber Security

PHP Serialisation Attacks

Are you ready to learn about fascinating topics in web development and security? Look no further, because today we’re going to build a simple web application to learn about serialization attacks. This is the first of (hopefully) many posts I will be creating.

First, let’s define what a serialisation attack is. In short, it’s when an attacker manipulates data that is being serialized (or converted into a format that can be stored or transmitted) in order to execute malicious code on the server.

For our application, we’re going to use PHP and a MySQL database. The first thing we need to do is set up our database. In this example, we’re going to create a simple “users” table with just a few fields: id, username, and password.

So lets create a simple table:

CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255), password VARCHAR(255) );

Next, we’ll create a PHP script to handle the serialization and deserialization of our data.

<?php
  $userInput = $_GET['data'];
  $deserializedData = unserialize($userInput);

  echo "Deserialized Data: <br>";
  print_r($deserializedData);
?>

Now, let’s introduce a vulnerability in our script. We’re going to insert user input directly into our unserialize() function without any validation. This is a major security risk, as it allows an attacker to insert malicious data into the serialized string.

<?php

  $userInput = $_GET['data'];
  $deserializedData = unserialize($userInput);

  echo "Deserialized Data: <br>";
  print_r($deserializedData);
?>

To test this vulnerability, we can send a serialized string with malicious code through the URL.

http://localhost/script.php?data=O:8:"stdClass":1:{s:11:"injection";s:29:"system("cat /etc/passwd");";}

As you can see, this can be very dangerous, as it allows an attacker to execute arbitrary code on the server. To protect against this type of attack, it’s important to properly validate user input before deserializing it.

But, how can we stop these attacks?

Here are a few ways to prevent serialization attacks:

  1. Input validation: One of the most effective ways to prevent serialization attacks is to validate user input before deserializing it. This can include checking the format of the serialized data, as well as ensuring that it only contains expected characters.
  2. Use a secure deserialization process: Instead of using the built-in PHP deserialization functions, consider using a library that provides a more secure deserialization process. This can include using a whitelist of allowed classes, or using a custom deserialization process that can validate the data before deserializing it.
  3. Keep software up to date: Serialization attacks often take advantage of vulnerabilities in the software being used. Keeping all software up to date, including the operating system, web server, and PHP, can help to mitigate the risk of these attacks.
  4. Use a firewall: A firewall can be set up to block any incoming request that contains malicious serialized data.
  5. Monitoring: Keep an eye on your application logs, network traffic, and other security-related data to detect any suspicious activity.

In addition to these steps, it is important to have a comprehensive security strategy in place and to regularly test your application for vulnerabilities. By following best practices and staying informed about the latest threats, you can help to protect your application from serialization attacks and other types of security threats.

So how do we actually do it?

Here is an example of how to validate user input before deserializing it:

<?php

  $userInput = $_GET['data'];

  //Validate the format of the serialized data

  if (!preg_match('/^[a-zA-Z0-9=+\/]+$/', $userInput))
  { 
    die("Invalid serialized data"); 
  }

  //Ensure that it only contains expected characters
  $data = @unserialize($userInput);

  if ($data === false) 
  { 
    die("Invalid serialized data"); 
  }

  echo "Deserialized Data: <br>";

  print_r($data);
?>

This code checks the format of the serialized data, and ensures that it only contains expected characters by using regular expressions and the unserialize function with an error control operator (@) to suppress the warning message.

Here’s an example of how to use a secure deserialization process:

<?php 
class MyDeserializer 
{ 
  public static function deserialize($data) 
  { 
    //Validate the data 
    if (!preg_match('/^[a-zA-Z0-9=+\/]+$/', $data)) 
    { 
     die("Invalid serialized data"); 
    } 
    //Use a whitelist of allowed classes 
    $allowedClasses = array("User", "Admin"); 
    $data = unserialize($data, array("allowed_classes" => $allowedClasses)); 
    return $data; 
   } 
} 

  $userInput = $_GET['data']; 
  $data = MyDeserializer::deserialize($userInput); 
  echo "Deserialized Data: <br>"; 
  print_r($data); 
?>

This example uses a custom class called MyDeserializer that validates the data and uses a whitelist of allowed classes before deserializing it.

It is important to note that these are just a few examples of how to prevent serialization attacks, and that a comprehensive security strategy should include multiple layers of protection. Additionally, it is always important to keep all software up-to-date and to regularly test your application for vulnerabilities.

Leave a Reply

Your email address will not be published. Required fields are marked *