# Небезопасная десериализация

## Описание уязвимости
Суть уязвимости заключается в том, что в любом языке программирования присутствует механизм восстановления объектов для дальнейшего их использования в алгоритме.
## Причины возникновения уязвимости
Механизм пересборки данных был разработан для универсальности использования приложений. И не было заложено никаких механизмов защиты.
Поэтому здесь, как в XML парсерах, злоумышленник использует прямой функционал механизма.
## JSON/XML и Binary сериализация
Объекты языка программирования, которые должны пройти процедуру восстановления, могут быть в различных форматах. Обычно формат определяется той функцией, которая используется для сборки объекта.
Пример XML объекта:
```xml
$ ./ysoserial.exe -p DotNetNuke -m run_command -c calc.exe
<profile>
<item key="foo" type="System.Data.Services.Internal.ExpandedWrapper`2[[System.Web.UI.ObjectStateFormatter, System.Web, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<ExpandedWrapperOfObjectStateFormatterObjectDataProvider xmlns:xsd=" [http://www.w3.org/2001/XMLSchema](http://www.w3.org/2001/XMLSchema) " xmlns:xsi=" [http://www.w3.org/2001/XMLSchema-instance](http://www.w3.org/2001/XMLSchema-instance) ">
<ExpandedElement/>
<ProjectedProperty0>
<MethodName>Deserialize</MethodName>
<MethodParameters>
<anyType xsi:type="xsd:string">base</anyType>
</MethodParameters>
<ObjectInstance xsi:type="ObjectStateFormatter">
</ObjectInstance>
</ProjectedProperty0></ExpandedWrapperOfObjectStateFormatterObjectDataProvider>
</item></profile>
```
Пример JSON объекта:
```JSON
{
'$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
```
https://portswigger.net/web-security/all-labs
## Последствия эксплуатации уязвимости
Уязвимость считается одной из самых разрушительных, потому что результат работы зависит напрямую от того, что выберет сам злоумышленник.
Все действия будут выполняться как часть работы алгоритма приложения, хотя в большинстве случаев после работы команд злоумышленника приложение или перезагрузится или выйдет из строя.
## Примеры уязвимого кода
PHP:
```php=
class ViewFile { public $filename = '';
public function __toString()
{ include $this->filename; return ""; } }
if (isset($_GET['page']))
{ $pdfobject = unserialize(base64_decode($_GET['page'])); }
else { $pdfobject = new File(); } ?>
```
nodeJS:
```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);
```
Python:
```python=
class Vault(object):
'''R/W an ansible-vault yaml file'''
def __init__(self, password):
self.password = password
self.vault = VaultLib(password)
def load(self, stream):
'''read vault steam and return python object'''
return yaml.load(self.vault.decrypt(stream)) [0]
```
Java:
```java=
// Vulnerable class
class LogFile implements Serializable
{
public String filename;
public String filecontent;
// Function called during deserialization
private void readObject(ObjectInputStream in)
{
System.out.println("readObject from LogFile");
try
{
// Unserialize data
in.defaultReadObject();
System.out.println("File name: " + filename + ", file content: \n" + filecontent);
// Do something useful with the data
// Restore LogFile, write file content to file name
FileWriter file = new FileWriter(filename);
BufferedWriter out = new BufferedWriter(file);
System.out.println("Restoring log data to file...");
out.write(filecontent);
out.close();
file.close();
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
}
}
```
## Способы защиты
- отказ от использования механизма
- использование только классов, где есть параметры, без функций
- использовать фильтры от платформы языка программирования