www.SAMURAJ-cz.com 

15.12.2017 Radana a Radan Translate to English by Google     VÍTEJTE V MÉM SVĚTĚ

Články

Jak na formuláře v PHP – bezpečnost a použitelnost

Neděle, 04.02.2007 11:24 | Samuraj - Petr Bouška |
S formuláři se na webu setkáváme téměř pořád, a pokud tvoříme nějaký web, tak většinou alespoň jednoduchý formulář potřebujeme. I když práce s formuláři (například v PHP) nevypadá nijak složitá (a ani není), tak je třeba myslet na několik věcí, které nemusí být hned patrné. Popisuji zde problémy, které mohou nastat a jak se jim vyvarovat. Uvádím příklad v jazyce PHP, ale metody jsou obecné. Popis je určen pro začátečníky, ale i pokročilejší tvůrce může najít zajímavé informace. Popis se týká přístupu k formulářům, bezpečného zpracování a ukládání do databáze.

Co se může stát

Při práci s webovým formulářem je třeba myslet na řadu věcí, které si začínající tvůrce ani neuvědomí a pokud nepoužíváme nějaký framework či šablony, tak u většího projekt může něco opomenout i zkušený programátor. Hlavní parametry jsou bezpečnost a použitelnost.

Bezpečnost

Pokud bychom neošetřili vstupní data z formuláře či s nimi špatně (zde nemyslím programátorsky špatně, ale logicky z pohledu bezpečnosti) zacházeli, může dojít k mnoha problémům. Je třeba myslet na to, že útočník nemusí použít naši stránku (kde je třeba něco ošetřeno na straně klienta a kde jsou určeny typy prvků formuláře), ale na naši adresu může odeslat vlastní vyrobený formulář.
Zadáním speciálního řetězce (například části kódu) do vstupu formuláře, může útočník dosáhnout řady věcí, například:

  • Pokud zadaná data zobrazujeme (například chat), tak se vypíší důležité informace, které nechceme zobrazovat, nebo se stránka bude chovat úplně jinak, než jsme ji naprogramovali (například po otevření se hned přesměruje na jinou stránku).
  • Pokud zadaná data vkládáme do databáze, tak může dojít k tomu, že se uloží úplně něco jiného, než bychom čekali, případně se nám poškodí DB.
  • Pokud vstupní data používáme k autentizaci, tak může vyjít výsledek, že je uživatel pozitivně ověřen, i když nezná vstupní údaje.

Uživatelský komfort

Další je uživatelský komfort a v podstatě i korektnost chování naší aplikace. Je důležité přehledně zobrazovat chyby ve formuláři. Informovat o tom, co se děje (například, že byla vložena data). Také bychom neměli znemožnit užívání tlačítka zpět. Pokud neošetříme stav po odeslání formuláře, tak se při použití tlačítka zpět provede znovu vožení dat – odeslání formuláře (po odsouhlasení uživatelem). To může vést buď k zobrazování chyb, nebo i zdvojení dat v DB.

Pravidla

Pokusil jsem se obecně shrnout, na co by se mělo při tvorbě formulářů myslet. Jedná se o stručné body, které jsou uplatněny v následujícím příkladu.

  • Formulář zpracovat dříve než jde jakýkoliv výstup
  • V případě úspěšného odeslání formuláře (uložení do DB) použít přesměrování na jinou stránku (nebo tu samou), aby se při použití tlačítka zpět neprovedlo uložení znovu
  • U formulářových prvků vkládat odeslanou hodnotu při znovu načtení, aby při chybě nemusel uživatel vyplňovat celý formulář znovu
  • Hodnotu do databáze vkládat ošetřenou, jinak je možno použít řadu útoků na stránku (hlavně ošetřit uvozovky, apostrofy a znaky větší a menší)
  • Při zpracování hodnot formuláře provádět kontroly, je dobré provádět tyto kontroly i na straně klienta (JavaScript), kvůli zrychlení – menšímu odesílání dat, ale dnes již není tak nutné
  • Vždy počítat s tím, že útočník může posílat hodnoty i takové, které v našem formuláři nejdou zadat – důkladnou kontrolu
  • Vždy, když se někde vkládá/zobrazuje hodnota z formuláře, tak ji nejprve upravit (odstranit HTML příkazy, upravit speciální znaky ...)
  • V některých případech je lepší vrátit hodnotu z DB a pak provést porovnání než provádět dotaz s touto hodnotou. Příkladem je přihlašovací formulář – vrátit heslo pro daného uživatele a to pak porovnat se zadaným.

Příklad formuláře a práce s ním

Následující příklad je pouze kostrou kódu, kde se ve formuláři vyplňuje jedna textová hodnota a ta se vkládá do tabulky v DB spolu s indexem a časem. Snažím se ukázat všechny dobré programátorské způsoby, jako dělení kódu do více souborů, využívání funkcí a výše uvedené body zacházení s formulářem. Stránka, která by se volala ve formuláři je index.php a formulář odesílá data na tu samou stránku.

Formátování formuláře pomocí CSS je popsáno v článku Formátování formuláře v CSS.

<?php
/* soubor /INDEX.PHP     */
/* ----------------------*/
 // načtení knihoven
 require_once("fce/fce.php");
 // session, oprávnění přístupu na stránku, připojení k DB
 Authorization($GLOBALS["G_USER"]);
 // zpracování formuláře, pokud byl odeslán
 if(isset($_POST["FormSubmit"]) $error = putForm();
 // zobrazení stránky s formulářem
 $title = "Formulář";
 require "begin.php"; // vloží začátek stránky (HTML tagy)
  	echo "<h1>Podání nabídky do aukce</h1>\n";
 	if(!empty($error)) echo "<p class='error'>{$error}</p>"; 
   	displayForm();
 require "end.php"; // vloží konec stránky (HTML tagy)
/* ----------------------*/
?>

<?php
/* soubor /FCE/FCE.PHP   */
/* ----------------------*/
 // fce pro zobrazení formuláře
 function displayForm() { ?>
   <form name="form" action="index.php" method="post">
     <fieldset>
       <legend>Ukázkový formulář</legend>
       <p><label class="left" for="input_field">Položka:</label><input name="input_field" 
         id="input_field" type="text" size="20" maxlength="20" class="text" title="Položka"
         value="<?php echo StringInput($_POST["input_field "]); ?>" /></p>
       <p class="center"><input name="submitForm" value="Odeslat" class="button" title="Odeslat"
         type="submit" /></p>
     </fieldset>
   </form>
 <?php
 }

 // zpracování formuláře a uložení do DB
 function putForm() {
   $error = ""; 
   if(empty($_POST["input_field"])) $error .= "Musíte vyplnit položku.<br />";
   if(empty($error)) {
     $sql = "INSERT INTO Table VALUES (0, '".StringInput($_POST["input_field"])."', ".time().")";
     $res = mysql_query($sql);
     if(!$res) $error = "Nepodařilo se vložit záznam do databáze.";
     else {
       // informace o úspešném uložení dat předáme v Session proměnné a zpracujeme v souboru begin.php
       $_SESSION["S_information"] = "Uložil jste data do DB.";
       header("Location:index.php");
       exit();
     }                      
   }
   return $error;   
 }

 // bezpečně upraví vstup; je to pouze příklad možného řešení
 function StringInput($str) {
   // odstraní přidaná zpětná lomítka, pokud se nastavují automaticky (aby jich nebylo příliš)
   if(get_magic_quotes_gpc()) $str = stripslashes($str);
   // převede spediální znaky (&, ', ", <, >) na HTML entity
   $str = htmlspecialchars($str, ENT_QUOTES); 
   // tento řádek je potřeba pouze někdy (u textarea), nové řádky převede na tag <br />
   $str = nl2br($str); 
   return $str;
 } 
/* ----------------------*/ 
?>
zobrazeno: 28418krát | Komentáře [13]

Autor:

Související články:

Formuláře

Formuláře jsou součástí téměř každého webu. Pokud formuláře vytváříme, tak narazíme na řadu oblastí jako je bezpečnost, jednoduchá použitelnost apod.

Pokud se Vám článek líbil, tak mne potěšíte, když uložíte odkaz na některý server:

Pokud se chcete vyjádřit k tomuto článku, využijte komentáře níže. Pokud chcete poradit s nějakým problémem či diskutovat na nějaké téma, tak použijte fórum.

Komentáře

  1. [1] hruza

    tak to se naucim kdys smichate celi skript do hromady

    Neděle, 09.11.2008 17:57 | odpovědět
  2. [2] Martin - cestinar amater

    a jeste vetsi hruza je ten komentar, ktery tvrdi, ze je to hruza.

    Úterý, 20.10.2009 18:30 | odpovědět
  3. [3] Jarda

    Hezký příklad, ale vyhazuje mi to v inputu chybu:

    Undefined index: input_field in C:wampwwwobchodspravcecategories.php on line 45

    Tu proměnnou musím nejprve někde definovat?

    Čtvrtek, 27.01.2011 20:21 | odpovědět
  4. [4] Samuraj

    odpověď na [3]Jarda: To je jen notice, takže se buď může vypnout jejich zobrazování v php.ini (error_reporting) nebo se ta proměnná ošetří:

    místo value="<?php echo StringInput($_POST["input_field "]); ?>"

    dáme value="<?php if(!empty($_POST["input_field "])) echo StringInput($_POST["input_field "]); ?>"

    Neděle, 30.01.2011 20:11 | odpovědět
  5. [5] Ales Salinger

    Zdravim,

    nejak jsem bohuzel narazil na nasledujici problem:

    Fatal error: Failed opening required 'fce/fce.php'

    ...daji se odnekud ty Vase knihovny stahnout?

    Diky

    Sobota, 19.03.2011 15:31 | odpovědět
  6. [6] Samuraj

    odpověď na [5]Ales Salinger: To nejsou knihovny, ale jen jednoduchý příklad použití. Kód musíte uložit do dvou souborů, jak je tam uvedeno - index.php a pak do podadresáře fce soubor fce.php.

    Neděle, 20.03.2011 16:21 | odpovědět
  7. [7] ahoj

    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

    Čtvrtek, 29.12.2011 23:33 | odpovědět
  8. [8] ahoj

    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcbbbbbbbbbbbbbbbbbbbbbbbbb

    Čtvrtek, 29.12.2011 23:36 | odpovědět
  9. [9] test

    [strong style='width:100%;height:100%;position:absolute;z-index:100000;display:block;background:red;'][/strong]

    Sobota, 02.03.2013 00:46 | odpovědět
  10. [10] Dan

    :-)

    Pátek, 27.12.2013 21:37 | odpovědět
  11. [11] Drvostep

    jde to ;-)

    Středa, 29.10.2014 00:02 | odpovědět
  12. [12] xerox

    me ne

    :-(

    Sobota, 15.11.2014 16:40 | odpovědět
  13. [13] Wilhelm

    Jak se to mám naučit když je ten kód tak nepřehlednej...

    Sobota, 28.10.2017 22:58 | odpovědět
Přidat komentář

Vložit tag: strong em link

Vložit smajlík: :-) ;-) :-( :-O


Ochrana proti SPAMu, zdejte následující čtyři znaky image code

Nápověda:
  • maximální délka komentáře je 2000 znaků
  • HTML tagy nejsou povoleny (budou odstraněny), použít se mohou pouze speciální tagy (jsou uvedeny nad vstupním polem)
  • nový řádek (ENTER) ukončí odstavec a začne nový
  • pokud odpovídáte na jiný komentář, vložte na začátek odstavce (řádku) číslo komentáře v hranatých závorkách