Zabezpieczamy nasz kontent przed hotlinkowaniem

Czym jest hotlinkowanie? Najprostsze wytłumaczenie tego popularnego zjawiska to osadzanie elementów (grafika, skrypty js, css) na swojej stronie linkując je bezpośrednio z innej. Bardzo często możemy spotkać się z takim procederem na aukcjach Allegro, gdzie sprzedający umieszcza zdjęcia sprzedawanego przedmiotu podlinkowane bepośrednio z zewnętrznej strony, której właścicielem nie jest.

Czy takie hotlinkowanie może nieść ze sobą jakieś niebezpieczeństwa? Oczywiście, że tak. Przede wszystkim zarówno dla holinkującego jak hotlinkowanego. Hotlinkowany traci wykupione pasmo w usłudze hostingu, jego elementy strony są wykorzystywane na zewnętrznych serwisach bez jego wiedzy, a tego przecież nikt nie chce. Hotlinkujący natomiast, może któregoś dnia zamiast zdjęć przedmiotu na swojej aukcji zobaczyć treści obraźliwe, lub żartobliwe (w najlepszym wypadku), taki sposób zniechęcania hotlinkujących jest niezwykle skuteczny, chociaż powiedziałbym, agresywny.

Jak możemy się zabezpieczyć? Możemy wykorzystać kilka metod, najprostsza z nich to weryfikowanie nagłówka HTTP REFERER wysyłanego przez przeglądarkę przy każdym requeście. Metoda ta opiera się w pełni na wykorzystaniu właściwości protokołu HTTP, który nakazuje umieszczać adres strony z której odwołujemy się do obiektu, adres ten jest umieszczany w nagłówku REFERER. Jeśli wykorzystujemy serwer Apache do serwowania naszych stron, możemy stworzyć konkretne reguły Rewrite (mod_rewrite) i sprawdzać, czy dane żądanie przychodzi z Refererem zawierającym naszą stronę, jeśli tak to obiekt jest podawany, jeśli Referer zawiera inny adres to zwracamy odpowiedź z kodem 403 (forbidden).

Przykładowy plik .htaccess

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www.)?naszastrona.pl/ [NC]
RewriteRule .(gif|jpg|png)$ - [F]

  • nasz HTTP_REFERER nie jest pusty
  • nasz HTTP_REFERER jest różny od http://naszastrona.pl lub http://www.naszastrona.pl/
  • jeśli żądanie dot. plików gif, jpg, png - zablokuj takie żądanie [F]

Czyli jeśli ktoś podlinkuje obiekty graficzne na swojej stronie bezpośrednio z naszej to taki request zostanie wyłapany i zablokowany.

W przypadku serwera lighttpd możemy podmienić obrazek na inny również wykorzystując zestaw reguł mod_rewrite:

Przykład podmiany obrazka w przypadku wykrycia hotlinkowania:

$HTTP["referer"] =~ ".*naszastrona.pl.*" {
url.rewrite = ("(?i)(/.*.(gif|jpg|png))$" => "/anty_hotlink.png" )
}

  • anty_hotlink.png - jest obrazkiem który wyświetla się hotlinkującemu zamiast oryginalnej grafiki.

Zupełnie innym sposobem zniechęcającym do hotlinkowania jest blokowanie zasobów poprzez generowanie tymczasowych adresów do obiektów. Gotowym takim rozwiązaniem jest moduł  mod_secdownload, zaimplementowany w serwerze lighttpd. Zasada działania tego modułu opiera się o generowanie adresów do konkretnych obiektów w oparciu o klucz i czas (wymagane jest napisanie prostego skryptu PHP). Adres do konkretnych zasobów będzie zawierał unikalny, dodatkowy ciąg znaków, który po przekroczeniu limitu czasowego zmieni się i dotychczasowy URL przestanie być aktywny.

Przykładowy skrypt PHP do generowania URLi:

<?php
$secret = "klucz";
$uri_prefix = "/pliki/";
$f = "/tajny.txt";
$t = time();$t_hex = sprintf("%08x", $t);
$m = md5($secret.$f.$t_hex);
printf('<a href="%s%s/%s%s">%s</a>',
$uri_prefix, $m, $t_hex, $f, $f);
?>

Nasz URL to teraz md5-składanka z czasu, nazwy pliku oraz słowa klucza, wygląda mniej więcej tak: http://serwer/pliki/db66551e129600d9b4483d223dea8a9e/4aae9666/tajny.txt, sama konfiguracja modułu wygląda następująco:

secdownload.secret          = "klucz"
secdownload.document-root   = "/Site/katalog_z_plikami"
secdownload.uri-prefix      = "/pliki/"
secdownload.timeout         = 10

  • secdownload.document-root - prawdziwy katalog z plikami,
  • secdownload.uri-prefix - pseudo katalog, tak naprawdę istnieje tylko w URI,
  • secdownload.timeout - czas ważności URL’a,

W przypadku kiedy mamy np. flashowy player pobierający jakąś mp3 i request generowany przez flash będzie praktycznie chwilę po wygenerowaniu URL’a timeout taki powinien być możliwie niski (2 sek).

Wdrożenie powyższych metod nie powinno zająć dużo czasu administratorowi stron WWW, a rezultat może przynieść miłe zaskoczenie, także DO BOJU! ;-)