Pokaż wyniki od 1 do 10 z 10

Wątek: Formularze - słabe punkty

  1. #1
    Zarejestrowany
    Dołączył
    Mar 2008
    Posty
    374

    Domyślnie Formularze - słabe punkty

    Witam, w tym krótkim artku chciałbym zwrócić uwagę na najsłabsze punkty formularzy, czyli elementy select i radio. Wielu początkujących programistów sądzi, że niebezpieczeństwo stwarzają jedynie inputy typu text, czy textarea i zajmują się jedynie ich zabezpieczaniem, często nie zwracając uwagi na inne elementy fromularza.

    Dla PHP nie ma różnicy, jaki jest typ danego inputa, wszystkie są traktowane tak samo - w tablicy $_POST są tylko ich nazwy i wartości. Wielu myśli, że jeśli wysyłają userowi formularz składający się z inputów radio, które mają sztywno przypisane value, user ma pole manewru jedynie wśród podanych wartości. Może lepiej wyjaśnię to na poniższym przykładzie.

    Mamy tutaj prosty skrypt, który umożliwia graczowi pracę w zamian za złoto. Gracz ma do wybory trzy różne opcje, różniące się kosztem w postaci punktów akcji:

    Kod php:
    <form method="post" action="">
        <input type="radio" name="wariant" value="3" /> Poświęć 3 PA, aby zyskać 30 sztuk złota<br />
        <input type="radio" name="wariant" value="6" /> Poświęć 6 PA, aby zyskać 60 sztuk złota<br />
        <input type="radio" name="wariant" value="9" /> Poświęć 9 PA, aby zyskać 90 sztuk złota<br />
        <input type="submit" value="Pracuj" />
    </form>

    <?php

    // Połączenie z jakąś bazą
    mysql_connect'host''user''pass' );
    mysql_select_db'nazwa_bazy' );

    // Jeśli formularz został wysłany
    if ( $_POST['wariant'] )
    {
        
    // Pobieramy dane o graczu o ID 1
        
    $gracz mysql_fetch_arraymysql_query'select * from `players` where `id` = 1' ) );
        
        
    // Sprawdzamy, czy gracz ma wystarczającą ilość punktów akcji
        
    if ( $gracz['pa'] < $_POST['wariant'] )
            exit( 
    'Nie masz tyle punktów akcji' );
            
        
    // Aktualizujemy rekord gracza o ID 1
        
    mysql_query'update `players` set `pa` = `pa` - ' $_POST['wariant'] . ', `gold` = `gold` + ' . ( $_POST['wariant'] * 10 ) );
        
        echo 
    'Wykonano zapytanie:<br /><br />update `players` set `pa` = `pa` - ' $_POST['wariant'] . ', `gold` = `gold` + ' . ( $_POST['wariant'] * 10 );
    }

    ?>
    Formularz wygląda tak:



    Z pozoru niewinnie, prawda? Wygląda jakby nie było możliwości ingerencji w jego strukturę. Ale to tylko złudzenie, najprostszą drogą do edycji kodu formularza jest posiadanie przeglądarki Opera, chociaż może też być Firebug, a w ostateczności zapis strony na dysku. Najpierw jednak zobaczmy jak to działa. Oto stan rekordu gracza przed użyciem formularza:



    Teraz odpalimy zwykłą akcję:



    Wszystko gra - user stracił 9 PA, a zyskał 90 golda:



    Teraz pokażę, jak zmienić wartość inputa na przykładzie Opery. Tak właśnie atakujący może wykorzystać słabość zabezpieczeń. Wciskamy F5 i pokaże nam się ??ródło strony, które powinno wyglądać tak:



    Znajdujemy fragment value="9" i zmieniamy go na:

    Kod:
    value="-9, gold = 99999999999 -- "
    Klikamy w przycisk "Zapisz zmiany" i wracamy do naszego formularza. Zaznaczamy opcję trzecią, za 9 PA i wysyłamy. Oto wynik:



    Rezultat w bazie:



    Niezły bajzel, co? Przeanalizujmy zapytanie, które przeszło:

    update `players` set `pa` = `pa` - -9, gold = 99999999999 -- , `gold` = `gold` + -90

    Chyba nie muszę tłumaczyć - warty uwagi jest jednak znak komentarza w MySQL, czyli --, który powoduje, że dalsza część zapytania jest ignorowana (szara część).

    Formularz, który podałem, można też zastąpić takim:

    Kod:
    <form method="post" action="">
        <select name="wariant">
            <option value="3" > Poświęć 3 PA, aby zyskać 30 sztuk złota</option>
            <option value="6" > Poświęć 6 PA, aby zyskać 60 sztuk złota</option>
            <option value="9" > Poświęć 9 PA, aby zyskać 90 sztuk złota</option>
        </select>
        <input type="submit" value="Pracuj" />
    </form>
    Też wygląda niewinnie, a można go równie łatwo zedytować...

    Jak się bronić? Traktować wszystkie rodzaje inputów tak samo. Jeśli ma przybierać wartości liczbowe, to filtrujcie go, aby przepuszczało tylko liczby. Z pomocą przychodzi także funkcja in_array. Oto jak można jej użyć:

    Kod php:
        if ( ! in_array$_POST['wariant'], array( 36) ) )
            exit( 
    'Nie wybrałeś opcji z zakresu 3,6,9!' ); 
    Za wszelkie niedociągnięcia przepraszam, mam nadzieję, że komuś się to przyda
    Ostatnio edytowane przez Zoran ; 23-06-2009 o 14:08

  2. #2
    Zasłużony Awatar karer
    Dołączył
    Apr 2008
    Posty
    2,554

    Domyślnie

    Rozwiazanie jest banalne ale niektorzy nie wiedza jak uzywac inputow.

    Radio button powinien byc traktowany przez CASE poniewaz jest to wybor. Mozna spokojnie pomijac inne wartosci co spowoduje ze nie bedzie dalo sie tego obejsc w ZADEN sposob.
    selecta trzeba traktowac jako pole w ktorym wybieramy jedna z dostepnych opcji. Trzeba zrobic liste dostepnych opcji. Pola tekstowe to wiadomo-pelna filtracja danych.

    Ale to sa raczej tylko ogolne warunki bezpieczenstwa formularzy. Jesli sie je spelnia to jedynym niebezpieczenstwem moze okazac sie zle filtrowanie tekstow ale to jest niezalezne od radio/select input.

  3. #3
    Zarejestrowany Awatar Imperator_Edi
    Dołączył
    Dec 2008
    Posty
    614

    Domyślnie

    Szczerze, to nie zwróciłem na to uwagi. Teraz będę się bardziej przyglądał bezpieczeństwu formularza.
    Notatnik nie jest przeznaczony do programowania!
    Jak sama nazwa wskazuje, jest on do trzymania notatek.

  4. #4
    Zarejestrowany
    Dołączył
    Oct 2007
    Posty
    450

    Domyślnie

    Tak, radio i select są często piętą achillesową formularzy. Najłatwiejsze do sprawdzenia (bo mają ściśle ustalone wartości) a zarazem często się o nich zapomina.

    Co lepsze? case czy in_array? Osobiście polecam filtrację poprzez case (jak wspomniał karer) jeżeli dla każdej z wartości musisz wykonać inne operacje. Wtedy można to zrobić od razu "na miejscu" (np pole odpowiada za rodzaj działania jaki chcemy wykonać choćby jak usuwanie, dodawanie, edycja).
    Jeśli jednak operacje będą takie same dla różnych wartości to polecam pomysł Zorana z in_array. Jest on bardziej zwięzły.
    in_array sprawdzi się szczególnie dobrze wtedy, gdy zapiszemy sobie wszystkie możliwości w tablicy i na jej podstawie wygenerujemy formularz jak i pó??niej sprawdzanie. Panujemy wtedy nad danymi z jednego miejsca. Przykład:
    Kod php:
    $arrDane = array('Wartosc 1' => 'val1',
                     
    'Wartosc 2' => 'val2',
                     
    'Wartosc 3' => 'val3');

    $wygenerowane '<select>';
    foreach(
    $arrDane as $opcja => $dane)
    {
      
    $wygenerowane .= '<option value="'.$dane.'">'.$opcja.'</option>';
    }

    $wygenerowane .= '</select>'
    A sprawdzenie? Mając tą tablicę nic prostszego:
    Kod php:
    if ( ! in_array$_POST['opcja'], $arrDane ) )
            exit( 
    'Wartosci nie znaleziono!' ); 
    Pierniki górą!

  5. #5
    Zarejestrowany
    Dołączył
    Mar 2008
    Posty
    374

    Domyślnie

    Kasyx bardzo mądrze prawisz Najwygodniej jest właśnie kontrolować dostępne opcje z poziomu tablicy, wtedy jest to naprawdę rozwiązanie elastyczne. Ja swojego czasu stosowałem system, w którym wszystkie dostępne klasy postaci trzymałem w tablicy w oddzielnym pliku, a przy rejestracji jedynie includowałem i generowałem z tego formularz :P

    PS. Kiedyś był taki mod do Vallheru, gdzie kupowało się kamienie ulepszające itemki :P Był tam właśnie formularz radio i niezłe wałki się robiło przez to :P

  6. #6
    Zarejestrowany
    Dołączył
    Oct 2007
    Posty
    450

    Domyślnie

    No ten system można rozbudować w zależności od potrzeb. Można np serializować odpowiednie tablice i w ramach potrzeb je deserializować, albo wrzucać do tablicy odpowiednio spreparowane dane z bazy (np jak wybieramy rasę, to można ją wybrać tylko z dostępnych a nie ma sensu ich ręcznie przepisywać).
    Różne są sposoby automatyzujące pracę z select / radio. Kiedyś nawet myślałem nad jakimś systemem wspomagającym pracę z formularzami w postaci 'serializowalnych' obiektów, które przechowywały wszystko co było nam potrzebne do pracy nad danym formularzem i dziedziczyły z klasy matki obsługującej te formularze... ale niestety nie skończyłem
    Pierniki górą!

  7. #7
    Zarejestrowany
    Dołączył
    Mar 2008
    Posty
    374

    Domyślnie

    Warto pamiętać przy tym o ciekawej właściwości PHP, mianowicie to, że pliki mogą zwracać wartości Bardzo to fajne w użyciu:

    plik.php:
    Kod php:
    <?php

    return array
    (
       
    'banan',
       
    'jabłko',
       
    'gruszka'
    )

    ?>
    Inny plik:
    Kod php:
    <?php

    $data 
    = require( './plik.php' );
    echo 
    $data[0]; // banan :P

    ?>

  8. #8
    Zasłużony Awatar Kemsan
    Dołączył
    Oct 2007
    Posty
    805

    Domyślnie

    Zoran widzę że się przykładasz to pisania tutków Niedługo będzie trzeba wykombinować nową rangę lub dać ci Programista Good Job Podklejam

  9. #9
    Grupa MmoCenter Awatar Smoker
    Dołączył
    Dec 2008
    Posty
    475

    Domyślnie

    warto sobie to wszystko zapamietac ^^ ja sam nie uzywam opery i nie wiedzialem o takiej mozliwosci az jeden graczy poszedl w grze do pracy na 10 godzin (gdzie do 8 było możliwe ^^)
    Ps dzieki meares za info

  10. #10
    Grupa MmoCenter Awatar Kiri
    Dołączył
    Sep 2007
    Posty
    1,741

    Domyślnie

    Warto też pamiętać że in_array jako igłę może mieć tablicę, np kiedy mamy selecta z możliwością wybrania większej ilości opcji, bąd?? też checkboxy, patrzeć przykład 3 na manualu -> http://pl.php.net/manual/pl/function.in-array.php
    Sio, nie pomagam via PM !



Informacje o wątku

Użytkownicy przeglądający ten wątek

Aktualnie 1 użytkownik(ów) przegląda ten wątek. (0 zarejestrowany(ch) oraz 1 gości)

Podobne wątki

  1. [FORMULARZE] Lista
    Przez Kedar w dziale HTML / CSS
    Odpowiedzi: 10
    Ostatni post / autor: 27-01-2010, 15:26
  2. Punkty
    Przez Nie zarejestrowany w dziale Pytania dotyczące silnika Xnova
    Odpowiedzi: 3
    Ostatni post / autor: 10-01-2010, 19:31
  3. Punkty
    Przez Nixsior w dziale Pytania dotyczące silnika Xnova
    Odpowiedzi: 5
    Ostatni post / autor: 23-06-2009, 13:44
  4. Punkty
    Przez plazmatix w dziale Pytania dotyczące silnika Xnova
    Odpowiedzi: 2
    Ostatni post / autor: 23-06-2008, 09:39
  5. Punkty na ADV
    Przez BaiL w dziale Support Ugameli
    Odpowiedzi: 4
    Ostatni post / autor: 14-12-2007, 13:44

Zakładki

Uprawnienia umieszczania postów

  • Nie możesz zakładać nowych tematów
  • Nie możesz pisać wiadomości
  • Nie możesz dodawać załączników
  • Nie możesz edytować swoich postów
  •