Przyjrzymy się prostej implementacji serwera proxy stworzonej w języku Ruby
:
class ProxyServlet < WEBrick::HTTPServlet::AbstractServlet
def do_GET (request, response)
open(request.query["url"]) do |http|
result = http.read
response.body = result
end
end
end
Co to jest serwer proxy?
Czasami w firmach niektóre strony są blokowane.
Filtry takie są proste w działaniu: sprawdzają z jakim adresem URL łączy się nasz komputer.
Jeżeli adres ten jest zablokowany - nie pozwala na wykonanie połączenia.
I tutaj z pomocą przychodzą serwery proxy. Jest ich wiele - łatwo znaleźć je w wyszukiwarce.
W takiej bramce podajemy adres z którym chcemy się połączyć.
Wtedy witryna ta pobiera treść strony przy pomocy swoich zasobów i zwraca ją nam w formacie tekstowym.
Ponieważ to nie my wchodzimy na dany adres - firewall nie jest świadomy że łączymy się z zablokowaną stroną.
Tutaj mam bardzo prosty przykład implementacji takiego serwisu w języku Ruby.
Wykorzystujemy tutaj moduł webrick
do szybkiego stworzenia serwera WWW.
Następnie przekazujemy parametr url
od użytkownika do funkcji open
i wyświetlamy treść jaką on zwróci.
Sprawdźmy jak działa ten przykładowy kod.

Jak widać otrzymałem treść zewnętrznej strony.
Teraz przejdźmy do znajdowania błędów. Ten kod zawiera dwie podatności.
Pierwsza nazywa się SSRF czyli Server Side Request Forgery.
Na tym samym serwerze posiadam również uruchomioną instancję narzędzia phpMyAdmin
, które służy do zarządzania bazą danych.

Jest ono skonfigurowane w taki sposób, że niemożliwy jest dostęp do tej podstrony z zewnątrz.
Jedynie używając localhosta możemy połączyć się z tym adresem.
Co się jednak stanie jeśli podamy ten adres jako parametr do naszej bramki?

Treść zostanie pobrana. Dlaczego? Ponieważ bramka i phpMyAdmin są dostępne na tym samym serwerze.
Jak zabezpieczyć się przed tym błędem?
Korzystając z zewnętrznych modułów, na przykład ssrf_filter
1, które sprawdzą, czy adres podawany przez użytkownika nie wskazuje czasem na zasoby na lokalnym komputerze.

Ale to nie wszystko. Funkcja open
posiada jeszcze jedną ciekawą funkcjonalność.
Jeśli parametr, który jest do niej przekazywany zaczyna się od kreski pionowej |
- czyli pipe nie jest on traktowany przez funkcję jako adres url a jako komenda, która ma zostać wykonana przy pomocy konsoli2.

Jeśli więc zamiast adresu url wpiszemy: |dir
- zamiast strony internetowej otrzymamy listę plików w obecnym katalogu.
Bardzo interesującą funkcjonalność o której zapewne niewiele użytkowników zdaje sobie sprawę.
Jak widać stworzenie bezpiecznego serwera proxy nie jest takie proste.