24-04-2020 / Od 0 do pentestera

Bezpieczeństwo sklepu Internetowego. Jak testować sklep internetowy?

Ilość i cena

 Wykorzystanie dziwnych liczb w koszyku

Każdy sklep Internetowy pozwala na zakupy. Zazwyczaj kupujemy jeden bądź dwa produkty. Ale przecież niektóre z nich (chociażby jabłka) można kupować na wagę. Wtedy fajnie byłoby móc kupić np. 40 dekagramów a nie pełen kilogram.

Sprawdź jak sklep reaguje na „dziwne” liczby:

  • 0.1
  • -1
  • NaN
  • Null
  • 2147483647
  • false
  • 9e90
  • 1e-50
  • undefined

Czy wartość koszyka spadnie poniżej zera? Co w przypadku produktów cyfrowych (gier, kursów online)? Czy można kupić ułamkową część takiego produktu?

 Gdzie sklep przechowuje cenę produktu

Gdzie sklep przechowuje cenę produktu? Może kwota, jaką ma zapłacić klient - znajduje się w ukrytym polu formularza?

Czy tą wartość można zmienić? Czy serwis weryfikuje przesłaną przez klienta wartość?

 Zaszyfrowane pole z ceną

Pole z ceną może zawierać niezrozumiały ciąg znaków. W takim wypadku najprawdopodobniej cena jest zaszyfrowana. Nie znamy sekretu, jaki został wykorzystany do zaszyfrowania tych informacji, ale możemy spróbować skopiować wartość z tańszego produktu i użyć jej w droższym.

 Dodanie nowych produktów przed zapłatą

Jak sklep reaguje na dodanie nowych produktów do koszyka w ostatecznej fazie zakupów? Czy dodaje należną kwotę do wartości brutto?

Aby to sprawdzić wykonaj kilka prostych kroków:

1. Dodaj produkt do koszyka

2. Otwórz sklep w nowej karcie przeglądarki

3. Przejdź do ostatniej fazy zakupów - zaraz przed płatnością

4. W poprzednio otwartej karcie przeglądarki - dodaj do koszyka nowy produkt

5. Powróć do poprzedniej karty i spróbuj zapłacić. Zobacz czy finalna kwota zamówienia została zaktualizowana, a może produkt pojawił się na fakturze, ale nie został doliczony do rachunku

Płatności

 Integracja z operatorem płatności

Rzadko który sklep obsługuje płatności samemu. Zazwyczaj zleca to zewnętrznej firmie. Płatność odbywa się więc na stronie pośrednika, który musi w jakiś sposób powiadomić sklep, że transakcja się powiodła.

Zazwyczaj robi to poprzez przesłanie danych na temat płatności poprzez parametry w adresie URL. Aby użytkownik nie mógł zmodyfikować tych danych (czyli samemu powiadomić sklep, że zapłacił – pomimo, że tego nie zrobił), są one w odpowiedni sposób podpisane.

Zazwyczaj łączy się odpowiednie parametry transakcji w jeden długi ciąg, który to następnie podpisuje się przy użyciu sekretnej wartości (która to jest znana jedynie pośrednikowi i właścicielowi sklepu).

W bardzo uproszczonym przykładzie może to wyglądać tak jak na ilustracji powyżej - gdzie łączy się identyfikator transakcji wraz z kwotą i taką to wartość podpisuje się przy użyciu algorytmu HMAC_SHA256.

Może to prowadzić do pewnych problemów. Weź pod uwagę dwie, różne transakcje:

  • ?id=123&kwota=34,56
  • ?kwota=4,56&id=1233

Jeżeli połączymy te dane zgodnie z algorytmem: ID + kwota otrzymamy:

  • HMAC_SHA256(sekret, 12334,56)
  • HMAC_SHA256(sekret, 12334,56)

Uzyskaliśmy taki sam ciąg wyjściowy z różnych danych wejściowych. To może prowadzić do replay attack. Atakujący może bowiem zamówić (i zapłacić) raz za zamówienie, a następnie zapisać wyliczony kod transakcji, który jest przekazywany przez pośrednika płatności.

Taki kod - może następnie zostać użyty w kolejnej, pasującej do schematu operacji. Podpis jest bowiem wyliczany z tych samych danych. Jego wynik będzie zatem taki sam.

 Obsługa wielu walut

Jeżeli sklep obsługuje różne waluty - można wykorzystać to do zmniejszenia kwoty zamówienia. Gdy sklep otrzymuje potwierdzenie płatności od pośrednika - powinien sprawdzić co najmniej 3 rzeczy:

  • jakiego zamówienia dotyczy płatność
  • ile pieniędzy zostało zapłacone
  • jaka była waluta transakcji

Może bowiem dojść do sytuacji, że atakujący poprosi sklep o pobranie kwoty - ale w innej walucie.

Dla przykładu - sklep operuje w złotówkach, ale płatność wykonano przy pomocy rubli.

Ta waluta jest dużo tańsza niż złotówka. Jeżeli sklep tego nie sprawdzi - może sporo stracić. Bo przecież końcowa kwota (ilościowo) się zgadza – ale wartościowo – już nie.

 Testowe płatności

Pośrednicy pozwalają na włączenie trybu testowego, w którym nie płaci się fizycznymi pieniędzmi. Zazwyczaj w dokumentacji określa się numery testowych kart kredytowych, które działają w takich przypadkach.

Jest to sposób na przetestowanie całego mechanizmu - bez wydawania pieniędzy – podczas testów sklepu internetowego. Należy sprawdzić, czy właściciel nie zapomniał o wyłączeniu tego mechanizmu.

Może sklep dostępny jest pod inną domeną (chociażby test.sklep.local) gdzie taki mechanizm jest włączony?

Błędy i ukryte pliki

 Informacje o błędach

Jeżeli wystąpił jakiś nieoczekiwany błąd - informacja zwracana klientowi powinna być bardzo ogólna.

Klient nie powinien widzieć żadnego kodu źródłowego, wartości stacktrace lub innych elementów, przydatnych podczas testowania oprogramowania.

Spróbuj podać dane w innym formacie niż są oczekiwanie bądź też wyślij dane w inne miejsce niż to wynika z formularza. Dane przesyłane są w formacie JSON? Wyślij ciąg znaków, który nie jest prawidłowo sformatowany i zobacz co się stanie.

 Głębokie ukrycie

Głębokie ukrycie polega na umieszczaniu plików w trudnej do odgadnięcia ścieżce. Dla przykładu, chcę podzielić się plikiem ze swoim kolegą - kopiuję go więc na swój serwer do katalogu plikidlakolegi1234.

Tylko osoba, która zna ten adres może je zobaczyć. Problem polega na tym, że jeżeli ktoś odgadnie ten adres - ma pełen dostęp do plików, które się tam znajdują.

W programowaniu często widuje się ukryte katalogi .git i .svn. Są one wykorzystywane przez systemy kontroli wersji - czyli narzędzia, pozwalające na wspólną pracę nad projektem przez wielu użytkowników równocześnie.

Jeżeli programiści przez nieuwagę skopiują taki katalogu na produkcyjny serwer - może dojść do wycieku danych. To samo tyczy się innych potencjalnie niebezpiecznych plików (chociażby takich, w których znajdują się hasła do bazy danych czy też innych serwisów).

 .DS_Store

W systemie Linux - jeżeli nazwa pliku rozpoczyna się od kropki - plik ten w standardowej konfiguracji jest ukryty. Ciekawostką może być plik .DS_Store, który tworzony jest na systemach Mac.

Znajdują się w nim potencjalnie interesujące dane, które mogą być odczytane specjalnym oprogramowaniem.

Numer zamówienia i faktura

 Czy można sprawdzić swoje zamówienie

Gdy coś zamawiamy - chcemy być na bieżąco informowani o zmianach statusu naszej paczki. Zazwyczaj odbywa się to poprzez wiadomości email, bądź też z poziomu panelu użytkownika - po zalogowaniu się do sklepu.

Nie każdy użytkownik chce tworzyć konto w sklepie, stąd też niektóre systemy pozwalają na sprawdzenie statusu poprzez dedykowany formularz. Wystarczy znać numer zamówienia, a zostaną wyświetlone pełne informacje na jego temat.

Co zamawialiśmy, oraz jaki jest adres dostawy. Czy numer zamówienia jest losowy? A może to kolejna liczba? Czy da się taki numer odgadnąć? Ile kombinacji prawdziwych numerów istnieje?

Jak poważny może to być problem? Wyobraź sobie sklep erotyczny, który cechuje się dyskrecją. Jeżeli numer zamówienia to liczba zwiększająca się o jeden - atakujący może pobrać wszystkie dane klientów a następnie szantażować ich zdobytymi w taki sposób informacjami.

Numer zamówienia powinien być losowy i odpowiednio skomplikowany (długi).

 Jak generowane są faktury

Podobna sytuacja dotyczy faktur. Kto ma do nich dostęp? Czy znajdują się w jakimś ogólnodostępnym katalogu? Jaki jest format nazwy pliku? Czy ma do niego dostęp jedynie zalogowany użytkownik?

Jest to analogiczna sytuacja jak z numerem zamówienia. Pobierając fakturę zdobywamy potencjalnie wrażliwe dane na temat użytkownika - co kupował oraz jaki jest jego adres i numer telefonu.

 HTML to PDF

Inną sprawą jest implementacja generowania faktur po stronie sklepu. Częstą praktyką jest używanie oprogramowania html-to-pdf.

Tworzy się szablon faktury jako stronę internetową. Następnie odpowiednia biblioteka zamienia tak przygotowaną stronę na gotowy plik pdf, który można wysłać do klienta.

Jest to rozwiązanie szybkie, proste i skuteczne - bywa jednak niebezpieczne.

 Błędy w generatorach plików PDF

Od czasu do czasu w oprogramowaniu tego rodzaju znajdowane są błędy. W większości przypadków pozwalają one na odczytanie dowolnego pliku z naszego serwera. Błędy te zazwyczaj pojawiają się ponieważ:

1. Dane od użytkownika są umieszczane w treści pliku HTML - czyli w naszej fakturze (na przykład imię i nazwisko czy też adres)

2. Są one traktowane jako kod HTML oraz czasami kod JS

3. Niektóre elementy języka pozwalają na pobieranie danych (i plików) z innych serwerów (oraz plików lokalnych)

4. Jeżeli twórcy biblioteki, która konwertuje plik odpowiednio nie zabezpieczą tych miejsc - może dojść do wycieku tajnych danych

Przykład. Użytkownik jako swój adres może podać następujący kod:

<div id='file'></div>
<script>
  const el = document.getElementById('file');
  function reqListener () {
    el.innerHTML = this.responseText;
  }
  var oReq = new XMLHttpRequest();
  oReq.addEventListener('load', reqListener);
  oReq.open('GET', 'file:///dowolny/plik/z/dysku');
  oReq.send();
</script>

Pobiera on treść pliku dowolny/plik/z/dysku i umieszcza w dokumencie. Ponieważ ten dokument jest następnie zamieniany na plik pdf - tajne dane mogą zostać odczytane przez konsumenta.

Morał: aktualizować oprogramowanie, które zamienia dokumenty HTML na PDF.

 Doładowanie konta

Niektóre większe sklepy mogą pozwalać na doładowanie swojego konta. Zamiast za każde zakupy płacić kartą bądź przelewem - doładowujemy konto raz - kartą zdrapką kupioną w kiosku.

Wtedy (gdy coś kupujemy) odpowiednia kwota jest odejmowana z naszego konta. Należy sprawdzić czy procedura dodawania środków do konta jest prawidłowa. Wykorzystuje się tutaj atak race condition.

W skrócie: przy pomocy odpowiedniego narzędzia próbujemy wykorzystać ten sam kod wiele razy. Wysyłamy do serwera informacje o wykorzystaniu kodu 100 razy - w praktycznie tym samym momencie czasowym.

Jeżeli sklep nie jest odpowiednio zabezpieczony - otrzymując tak dużą liczbę żądań może okazać się, że nie doładuje naszego konta raz (tak jak to było przewidziane) - ale wiele razy.

 Czy karta kredytowa jest sprawdzana podczas dodawania jej do konta

Powracający klient może być znudzony ciągłym podawaniem swojego numeru karty kredytowej podczas płatności. Może więc chcieć dodać ją do swojego konta. Gdy taka karta zostanie dodana - nigdy nie powinniśmy wyświetlać ponownie jej pełnego numeru.

Widoczne powinny być jedynie ostatnie cztery cyfry karty - reszta zamieniona na gwiazdki.

Promocje

 Promocje 2+1

Co z promocjami, gdzie sprzedaje się kilka produktów w jednym zestawie? Na przykład 2+1. Za które produkty klient płaci? Czy pod uwagę brany jest najdroższy przedmiot z koszyka, a może najtańszy? Czy można dodać bezpłatne produkty? Czy można usunąć pojedynczy produkt z zestawu? Czy rabat jest wtedy usuwany, a może zostaje na swoim miejscu?

 Nie wyświetlaj adresów email

Jeżeli sklep prosi klientów o recenzję produktów i jakości obsługi - wyświetlana powinna być tylko treść recenzji. Adres email powinien zostać ukryty (i nie być zwracany w ukrytych polach formularza bądź przez interfejs API).

Wysyłka plików

 Możliwość personalizacji produktów

Specjalną troską należy obdarzyć elementy systemu, w którym użytkownik może przesyłać swoje pliki graficzne (które są następnie wykorzystywane do personalizacji produktu).

Należy odpowiedzieć na pytania:

  • gdzie te pliki są przechowywane
  • kto ma do nich dostęp
  • kiedy są usuwane
  • czy akceptujemy jedynie obrazki (a może też pliki svg oraz html)
 Zip Slip

Może to być powiązane z obsługą archiwów - zwłaszcza, jeżeli klient przesyła więcej niż jeden plik na raz. Zamiast wysyłać je pojedynczo - może chcieć spakować je do jednego archiwum (zip, bądź rar) i przesłać go nam w takiej formie.

Serwis musi takie archiwum rozpakować i przetworzyć każdy z przesłanych plików. Jak zazwyczaj wygląda algorytm?

1. Program tworzy nowy, tymczasowy katalog

2. Archiwum jest otwierane i każdy plik (jego nazwa) jest łączona ze ścieżką tymczasowego katalogu

3. Plik jest zapisywany w nowej lokalizacji

Problem zip slip pojawia się, jeżeli potencjalny klient w nazwach plików w archiwum użył kombinacji ../. W systemie operacyjnym oznacza to przejdź katalog wyżej.

Rozważmy to na przykładzie:

 Algorytm wypakowywania plików

Załóżmy, że w archiwum znajduje się plik o nazwie ../../zly_plik.txt, a katalog tymczasowy to /home/kacper/ghost/template/. Algorytm połączy to więc w jedną całość:

/home/kacper/ghost/template/../../zly_plik.txt

Następnie system pozbędzie się zbędnych znaków ../.

/home/kacper/zly_plik.txt

W konsekwencji plik zamiast do katalogu template zostanie zapisany do katalogu kacper. Odpowiednio modyfikując nazwę plików - można więc doprowadzić do zapisania plików w dowolnym miejscu na serwerze - a to jest groźne.

Template Injection

 Template Injection

Nowoczesne aplikacje starają się rozdzielać kod aplikacji od jej wyglądu. Dzięki temu kod źródłowy jest bardziej czytelny dla programisty. Do tego celu używa się systemów szablonów. Ich działanie można opisać na prostym przykładzie:

1. Definiujemy wygląd strony - gdzie wyświetlają się obrazki, tabelki i inne elementy. W miejscach, które mają zostać pobrane z bazy danych lub pochodzą od użytkownika używamy markerów - specjalnych oznaczeń, które będą rozpatrywane przez system szablonów. Dla przykładu może to być coś pokroju {{ imie }}.

2. W kodzie aplikacji ustalamy, który szablon ma być wykorzystany oraz jakie dane mają zostać do niego przekazane. Chcemy bowiem, żeby na stronie pojawiło się nasze imię.

3. Biblioteka sprawdza cały szablon w poszukiwaniu markerów. Wie, że wartość {{ imie }} ma zostać zamieniona na Kacper (bo tak zdefiniował programista).

Oczywiście w rzeczywistości programista może zdefiniować bardziej skomplikowane operacje niż tylko podmiana tekstu. Problem pojawia się wtedy, gdy kod od użytkownika jest traktowany jako kod szablonu.

W takich przypadkach potencjalny atakujący może wykorzystać pełną moc i funkcjonalność danego systemu. Czyli chociażby wykonać dowolny kod na naszym serwerze.

Atak ten nazywa się SSTI - Server-Side Template Injections. Więcej na ten temat można znaleźć w dedykowanym materiale.

 Panel administratora

Panel administratora to twierdza każdego sklepu. Jeżeli atakującemu uda się tam włamać - może zmienić ceny produktów, usunąć zamówienia, bądź też całą bazę. Ale najpierw musi znaleźć adres, pod jakim można znaleźć sklep.

Standardowo będzie to /admin bądź /administrator. Ale nie zawsze jest tak łatwo. Ukrytych adresów można próbować szukać w plikach JavaScript. Interesującym posunięciem może być skorzystanie z Web Archive.

Jest to serwis, który zapisuje historyczne wersje stron internetowych. Można więc sprawdzić jak wyglądało Google 5 lat temu. Jeżeli mamy szczęście (i sklep, który testujemy jest popularny) - mogły się tam zachować stare wersje plików, używanych przez aplikację.

Sklep to żywy organizm, więc się zmienia. W plikach JS możemy znaleźć adresy, które mogą już nie istnieć w nowszych wersjach. Pytanie jednak, czy dostęp do nich został zablokowany po stronie serwera? A może dalej są otwarte i można próbować znaleźć w nich błąd?

Blind XSS

 Blind XSS

XSS to jedna z najpopularniejszych podatności, jakie można znaleźć na stronach internetowych. Więcej na ten temat możesz znaleźć:

Problem w tym, że zazwyczaj widzimy co się dzieje na naszym ekranie. Czyli:

  • znajdujemy podatny parametr
  • wykorzystując go przekazujemy do serwera złośliwy ciąg znaków
  • sprawdzamy czy atak zadziałał - to znaczy, czy złośliwy ciąg został prawidłowo zinterpretowany przez przeglądarkę

W przypadku błędów typu blind nie mamy takiej możliwości - bo to nie my wyświetlamy kod, który uruchomi tą podatność. Załóżmy, że XSS znajduje się w panelu administratora na stronie podsumowania zamówienia - adres podany przez klienta może zawierać kod HTML.

My (jako atakujący) nie możemy tego sprawdzić. Można jednak zastosować pewne rozwiązanie.

 Blind XSS z wykorzystaniem obrazka

Każda strona może wyświetlać obrazki, które mogą znajdować się gdziekolwiek. Służy do tego tag img:

<img src="http://serwer.local/losowy_numer" width="1" height="1">

Kiedy przeglądarka napotka na taki znacznik - wyśle żądanie do serwer.local aby pobrać treść obrazka. Następnie wyświetli go w kwadracie o wielkości 1x1px.

Tak stanie się w przypadku Blind XSS w panelu administratora. Kiedy zalogowany użytkownik wejdzie w odpowiednie miejsce - jego przeglądarka automatycznie wykona opisane wyżej kroki. My (jako właściciele serwera serwer.local) możemy sprawdzić logi naszego serwera - poszukując tam próby pobrania pliku o nazwie losowy_numer.

Jeżeli znajdziemy taki wpis - wiemy, że atak XSS się powiódł. Wystarczy więc przypisać inne numery do innych stron, chociażby:

  • 123 to strona X
  • 234 to strony Y

Dzięki temu wiemy gdzie wykonywał się nasz atak.

 Automatyzacja blind XSS

Na podobnej zasadzie działa BurpCollaborator. Serwer generuje unikalne adresy w domenie burpcollaborator.net, które możemy wykorzystać w naszych atakach. Kiedy tylko ktokolwiek (lub cokolwiek) wyśle żądanie pod taki adres - otrzymamy powiadomienie.

 Burp Collaborator

Jest to część Burp Suite w wersji profesjonalnej (płatnej).

Jakie inne sposoby istnieją, aby spróbować zostać administratorem? Weźmy pod uwagę formularz zmiany danych użytkownika w sklepie. Mamy więc imię, nazwisko i adres.

Mass assignment

 Mass assignment

Każde z tych pól odpowiada kolumnie w bazie danych. Zazwyczaj wiec tworzy się formularz, gdzie każdemu polu nadajemy odpowiednią nazwę:

<input type="text" name="imie">
<input type="text" name="nazwisko">
<input type="text" name="adres">

Ale proces ten można próbować zautomatyzować. Używamy wtedy jednego obiektu user i nawiasów kwadratowych:

<input type="text" name="user[imie]">
<input type="text" name="user[nazwisko]">
<input type="text" name="user[adres]">

Tworzenie takiego formularza można zautomatyzować. Aplikacja sprawdza jakie pola znajdują się w bazie danych i dla każdego z nich tworzy osobny wpis w formularzu.

Podczas zapisywania skrypt iteruje po wszystkich wpisach user i aktualizuje odpowiadające im wpisy w bazie danych. Problem pojawia się jednak, jeżeli niektóre kolumny posiadają specjalne znaczenie.

Wyobraźmy sobie bowiem, ze kolumna is_admin oznacza czy dany użytkownik ma uprawnienia administracyjne. Normalnie wartość ta nie jest wyświetlana w formularzu (po programista zdefiniował to pole jako wyjątek).

Ale czy pomyślał o tym samym przy zapisywaniu danych do bazy? Wystarczy, że atakujący doda dodatkowe pole do formularza i spróbuje go wysłać:

<input type="text" name="user[is_admin]" value="1">

Jeżeli zapomniano o tej kolumnie - może ustawić swoje konto jako konto administratora.

 Image Tragick

Jeżeli serwis pozwala na przesyłanie grafik - to najprawdopodobniej tworzy z nich jakieś miniaturki w różnych formatach graficznych. Do tworzenia zmniejszonych zdjęć korzysta się z różnych bibliotek - jedną z nich jest Image Magick.

W przeszłości biblioteka ta posiadała błąd, który mógł być użyty do wykonania kodu na atakowanym serwerze. Tak jak na zdjęciu wyżej - jeżeli stworzyliśmy plik o takiej treści, podczas jego konwersji na format png dochodziło do wykonania kodu (w tym wypadku komendy ls).

Błąd ten ma już swoje lata - nie zaszkodzi jednak upewnić się, że na atakowanym serwerze znajduje się poprawiona wersja tej biblioteki.

 Programy lojalnościowe

Utrzymanie klienta to klucz do sukcesu. Jak można to robić? Oferując rabaty oraz punkty lojalnościowe, które otrzymuje się za zakupy. Te punkty można następnie wymienić na gadżety lub kupno innych dóbr w sklepie.

Pytanie co w przypadku zwrotu towaru? W Polsce - w przypadku zamówień Internetowych - klient ma prawo zwrócić towar w przeciągu 14 dni bez podawania przyczyny. Czy w przypadku takiego zwrotu - punkty są odejmowane z konta?

A może trafiają na konto użytkownika dopiero po 14 dniach? Jeżeli nie - można to wykorzystać:

1. Osoba kupuje drogie przedmioty i otrzymuje za nie sporo punktów

2. Otrzymane przedmioty zwraca w przeciągu 14 dni

3. Otrzymuje zwrot środków na kartę/konto

4. Punkty pozostają na koncie - może je wykorzystać do kupna nowych przedmiotów za darmo

Podczas tworzenia tego materiału wykorzystałem dokument Common Security Issues in Financially Oriented Web Applications.