Wykryto działanie AdBlocka!

Prawdopodobnie masz właczonego Adblocka. Korzystanie z bloga jest całkowicie darmowe. Jeśli jednak chcesz docenić prace autora, wyłacz blokowanie reklam dla tej witryny, aby jeszcze bardziej zmotywowac autora do dalszej pracy oraz częstszej publikacji artykułów.

Dziękuje :)

Treść główna bloga

Artykuły

Security.class.php, czyli bezpieczeństwo to podstawa


Security.class.phpWielu programistów-amatorów nie zdaje sobie sprawy jak ważnym aspektem jest aby ich kod PHP był odporny na ataki typu: XSS, SQL Injection, czy też Session fixation. Programista, który nie zabezpieczy odpowiednio swojego skryptu, narażony jest na ataki, których skutkiem może być, np. usunięcie bazy danych. W tym artykule stworzyłem klasę, której zadaniem jest udostępnienie kilku prostych w użyciu metod, dzięki którym bezpieczeństwo witryny radykalnie się poprawi.

Kod na Githubie

Na początek tradycyjnie kod pliku security.class.php:

Podobnie do klasy do zarządania sesjami kod klasy security.class.php został napisany zgodnie z normą PSR-2 oraz PSR-4. Ponadto komentarze zostały napisanie zgodnie ze wskazaniami PHPdoc, dzięki czemu łatwo można przejrzeć dokumentację sporządzoną przez wspomniany system.

Klasa składa się z 11 metod:

  • __construct() – zwraca null
  • init() – zawiera podstawowe zabezpieczenia, sprawdza ustawienia systemowe oraz w przypadku wersji PHP <= 5.5 dołącza plik z klasą odpowiedzialną za manipulację hasłami
  • isAjax() – sprawdza czy request pochodzi z AJAXA
  • xssClean() – czyści ciąg na wypadek ataku typu XSS
  • request() – sprawdza jakim sposobem zostało wysłane zapytanie(POST, GET, itd)
  • clean() – podstawowe czyszczenie danych(trim, addslashes, htmlspecialchars)
  • cleanUrl() – usuwa z adresu URL niepożądane znaki
  • hashPassword() – generuje hash dla hasła
  • checkPassword() – sprawdza czy hash jest odpowiednikiem danego ciągu znaków
  • passwordNeedsRehash() – sprawdza czy hasło wymaga rehashingu
  • getPasswordInfo() – zwraca tablicę z informacją o haśle

Ponadto zadeklarowano 1 własnosność:

  • public $config – tablica zawierająca dane konfiguracyjne, które można dowolnie modyfikować
    • error_reporting – sposób wyświetlania błędów, aby zachować bezpieczeństwo, zmienna tak powinna wyglądać następująco: ‚error_reporting’ => [‚0’, 0]
    • path – ścieżka do pliku password.php, domyślnie plik znajduje się w tym samym folderze co klasa

Kod pliku index.php

Na początku skrypt sprawdza, czy wersja PHP jest wyższa od 5.4.0. Jeśli jest niższa wyświetla się odpowiedni komunikat i klasa nie będzie mogła być użyta. Następnie skrypt upewnia się, że plik o nazwie security.class.php istnieje i jego waga jest różna od 0 oraz załadowuje go do pliku index.php.

Potem tworzony jest obiekt klasy oraz następuje jego konfiguracja.

Konfiguracja następuje poprzez podanie jako argument do konstruktora tablicy z danymi konfiguracyjnymi. Na początku trzeba podać argumenty dla funkcji: error_reporting() oraz ini_set(), czyli powiadomić skrypt czy klasa ma wyświetlać błędy, a jeśli tak to na jakim poziomie. Domyślnie jest to ustawione na:

Aby na stronie nie pokazywały się błędy skryptu, które mogą pomóc potencjalnemu hakerowi dostać się, np. do naszej bazy danych. W fazie development’u, wyświetlanie błędów powinno być włączone, dlaczego w pliku index.php wartości error_reporting są ustawione odpowiednio E_ALL oraz 1. Kolejną rzeczą jest ścieżka do pliku password.php. Plik ten zawiera klasę, dzięki której można używać metod, dzięki którym mamy możliwość manipulacji hasłem, tj. hashowanie, sprawdzanie, rehashowanie.
Na końcu następuje wywołanie methody init(), która jest niezbędna do poprawnego działania klasy.

Poniżej przedstawiłem sposób w jaki poszczególne metody działają i można je zaimplementować w swoim skrypcie.
Jeśli chodzi o działania na hasłach, na ten temat można więcej dowiedzieć się tutaj.

  • >W fazie produkcji, wyświetlanie błędów powinno być włączone
    Raczej na odwrót: na produkcji błędy są wyłączone, na deve włączone

    Co do klasy:
    – fajnie, że masz zgodność z PSR-2… ale wypadałoby także zapewnić zgodność z PSR-0/PSR-4 – co jest o wiele ważniejsze

    – komenty dla Security::$config i Security::$result nie są zgodne z formatem PHPDoc

    – konstruktor mógłby brać obiekt ustawień (jak jest np w pluginach jQuery)

    – czemu konstruktor cokolwiek zwraca?

    – zapytanie regularne do wyciągania domeny jest daremne, bo wyłoży się choćby na https

    – wgl nie bardzo wiem przed czym miałoby chronić sprawdzanie adresu?

    if (ini_get('session.use_only_cookies') !== 0)
    A nie przypadkiem !== 1?

    ini_set('session.use_trans_sid', 1);
    A tu z kolei chyba 0?

    – empty zastąpi Ci isset. No i teraz taka mała szpileczka – a co jeśli żądanie nie prześle tego nagłówka, a jest ajaksowe? Czysty XMLHttpRequest tego nagłówka nie załącza. To konwencja, którą zapoczątkowało Prototype i którą później przejęła większość frameworków… większość, ale nie wszystkie http://stackoverflow.com/a/26245601

    return (strtolower($_SERVER['REQUEST_METHOD']) == strtolower($type) ? true : false);
    To można bez problemu skrócić do:
    return strtolower($_SERVER['REQUEST_METHOD']) === strtolower($type);

    – jak dla mnie drugi parametr w Security::clean jest niepotrzebny – funkcja powinna po prostu sama sprawdzać czy dostała string, czy tablicę

    – po co mi funkcja do filtrowania tego, co w URL, skoro nie działa dla stringu niebędącego poprawnym URL… przecież to oczywiste, że ta funkcja zawsze zwróci 1

    – jest pewna nieścisłość nazewnicza: XSSClean, ale cleanURL

    if ($this->result['password'] == true)
    return true;
    else
    return false;

    Ty chyba lubisz rozwlekać kod 😉

    Będziesz to rozbudowywał?

    • Poprawiłem skrypt zgodnie z Twoimi wytycznymi. Dodatkowo lekko go zoptymalizowałem. Mam nadzieję, że teraz kod będzie bliższy perfekcji 🙂

  • Dzięki za wszystkie uwagi dotyczące klasy, postaram się jak najszybciej wprowadzić poprawki do kodu.
    Co do rozwijania to jeszcze nie wiem czy wyjdzie kolejna wersja klasy

  • Mariusz

    Nie prościej użyć filter_var() ?