PHP forms og sikkerhet

Zolic

Medlem
Om du kun ønsker å vaske inndata, så ja.

I løsninger som henter data ifra databaser og lignende, vil jeg ikke anbefale det. Der vile jeg nok heller ha validert inputen, før det sendes request til databasen...

Men si det er et søk, da kan du ikke vaske inndataen, da må alt med -> Validering. Så ønsker du å vise hva brukeren har søkt på også.

Men om brukeren skrev
Kode:
<script>alert('XSS');</script>
så ønsker du jo ikke at den skal fungere så da må output escaping inn i bilde også...

slik dette forumet gjør, så du får
Kode:
&lt;script&gt;alert(&quote;XSS&quote;);&lt;/script&gt;

Ikke quote meg direkte på resultatet output escaping gir... da jeg ikke husker aller htmlentitis i hode... men det gir et inntrykk av hva som skjer :)
 

Tonny Kluften

Administrator
Jeg har ikke full forståelse for problemet. Hvis koden under kan brukes som case (og du gidder). Hva vill du gjort for å sikre det?

<?php
include("global.inc.php");
$errors=0;
$error="Følgende feil skjedde:<ul>";
pt_register('POST','bok1');
pt_register('POST','antall1');
pt_register('POST','bok2');
pt_register('POST','antall2');
pt_register('POST','navn');
pt_register('POST','adresse');
pt_register('POST','postnummer');
pt_register('POST','poststed');
pt_register('POST','epost');
pt_register('POST','tlf');
pt_register('POST','kommentar');

$kommentar=preg_replace("/(\015\012)|(\015)|(\012)/","&nbsp;<br />", $kommentar);if($navn=="" || $adresse=="" || $postnummer=="" || $poststed=="" || $epost=="" || $tlf=="" ){
$errors=1;
$error.="<li>Du fyllte ikke ut et påkrevet felt eller et påkrevet felt inneholder ugyldige tegn. Du kan kun bruke tall og bokstaver. Klikk tilbake og prøv en gang til.";
}
if(!eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*" ."@"."([a-z0-9]+([\.-][a-z0-9]+)*)+"."\\.[a-z]{2,}"."$",$epost)){
$error.="<li>Ukorrekt epostadresse ble skrevet inn";
$errors=1;
}
if($errors==1) echo $error;
else{
$where_form_is="http".($HTTP_SERVER_VARS["HTTPS"]=="on"?"s":"")."://".$SERVER_NAME.strrev(strstr(strrev($PHP_SELF),"/"));
$message="Bestilling fra nettbutikken\n
boka: ".$bok1."
Antall boka: ".$antall1."
satt: ".$bok2."
Antall satt: ".$antall2."
Navn: ".$navn."
Adresse: ".$adresse."
Postnummer: ".$postnummer."
Poststed: ".$poststed."
Epost: ".$epost."
tlf: ".$tlf."
Kommentar: ".$kommentar."
";
$message = stripslashes($message);
mail("tonny@tonny12.no","Bestilling av materiale fra carspecial", utf8_decode($message),"From: Carspecial shop");
?>
 

Mr Vest

Sjefen over alle sjefer!
Jeg har ikke sett på linken du kommer med, men det ser jo ut til at du fortjente det ryktepoenget jeg nettopp gav deg. Skal se på linken i kveld. :)
 

skogtrollet

Medlem
Hvorfor trenger man egentlig å vaske inndata som settes inn i en database? Kan man ikke bare gjøre det på utdata? Da tenker jeg på html koder.

Tegn som kan manipulere en sql query må selvfølgelig vaskes før den brukes i en query.
 

Zolic

Medlem
@Tonny sin case

Etter en litt hurtig gjennomgang har jeg kommet frem til
<?php
/* Sikkerhetshull:
*
* $PHP_SELF // om servern ikke er konfigurert til å fjeren overflod her, så er den åpen for XSS
* E-post meldinger kan ikke vær mer enn 70chars, kan skape problemer.
* &nbsp;<br />
*
* E-post kan være litt vrient, da folk benytter forskjellige e-post lesere...
* Spesielt de nettbaserte, enkelte av dem kan tolker html tegn som HTML(selv om det er plain text e-post), med dem så går det fint å sende outputescape med htmlentitis( &gt; &lt; etc).
* Men i dem som leser det som plain text, vil jo da få opp &gt; isteden for > ....
* Derfor ville jeg ha validert inndataen, med whitelisting: kun enkelte tegn er lovlig.
*
* Globals er i hovedsak et sikkerhethull i seg selv. *
*/
include("global.inc.php");
$errors=0;
$error="Følgende feil skjedde:<ul>";
// opprettelse av de globale variablene til $_POST
// litt i tvil om dette er smart eller ikke...
pt_register('POST','bok1');
pt_register('POST','antall1');
pt_register('POST','bok2');
pt_register('POST','antall2');
pt_register('POST','navn');
pt_register('POST','adresse');
pt_register('POST','postnummer');
pt_register('POST','poststed');
pt_register('POST','epost');
pt_register('POST','tlf');
pt_register('POST','kommentar');

// i denne blir linjeskift og newline byttet til &nbsp;<br />
// form for vasking av inndata
// men blir feil om du ikke sender HTML e-post, linje skift skal være \n(\012)
$kommentar=preg_replace("/(\015\012)|(\015)|(\012)/","&nbsp;<br />", $kommentar);

// her blir alt sjekket så det ikke er empty fields
if($navn=="" || $adresse=="" || $postnummer=="" || $poststed=="" || $epost=="" || $tlf=="" ){
$errors=1;
$error.="<li>Du fyllte ikke ut et påkrevet felt eller et påkrevet felt inneholder ugyldige tegn. Du kan kun bruke tall og bokstaver. Klikk tilbake og prøv en gang til.";
}

// validere e-post, Eregi: This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged.
if(!eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*" ."@"."([a-z0-9]+([\.-][a-z0-9]+)*)+"."\\.[a-z]{2,}"."$",$epost)){
$error.="<li>Ukorrekt epostadresse ble skrevet inn";
$errors=1;
}
if($errors==1){
echo $error;
}else{
$where_form_is="http".($HTTP_SERVER_VARS["HTTPS"]=="on"?"s":"")."://".$SERVER_NAME.strrev(strstr(strrev($PHP_SELF) ,"/"));
$message="Bestilling fra nettbutikken\n
boka: ".$bok1."
Antall boka: ".$antall1."
satt: ".$bok2."
Antall satt: ".$antall2."
Navn: ".$navn."
Adresse: ".$adresse."
Postnummer: ".$postnummer."
Poststed: ".$poststed."
Epost: ".$epost."
tlf: ".$tlf."
Kommentar: ".$kommentar."
";

// fjerner slasher fra meldingen
// form for output escaping
$message = stripslashes($message);
mail("tonny@tonny12.no","Bestilling av materiale fra carspecial", utf8_decode($message),"From: Carspecial shop");

?>

Med en utestet rettelse, men den tar for seg de problemene jeg så i farten.

<?php
//uskadeligjør php_self
if (!empty ($_SERVER['PATH_INFO']) && strpos ($_SERVER['PHP_SELF'], $_SERVER['PATH_INFO']) !== false) {
$_SERVER['PHP_SELF'] = substr ($_SERVER['PHP_SELF'], 0, -(strlen ($_SERVER['PATH_INFO'])));
}

include("global.inc.php");
$errors=0;
$error="Følgende feil skjedde:<ul>";
// opprettelse av de globale variablene til $_POST
// litt i tvil om dette er smart eller ikke...
pt_register('POST','bok1');
pt_register('POST','antall1');
pt_register('POST','bok2');
pt_register('POST','antall2');
pt_register('POST','navn');
pt_register('POST','adresse');
pt_register('POST','postnummer');
pt_register('POST','poststed');
pt_register('POST','epost');
pt_register('POST','tlf');
pt_register('POST','kommentar');

// i denne blir linjeskift og newline byttet til \n(\012)
// form for vasking av inndata
$kommentar=preg_replace("/(\015\012)|(\015)|(\012)/","\n", $kommentar);

// her blir alt sjekket så det ikke er empty fields
// denne og genVal sjekken burde deles opp så brukeren får vita spesifikt hav som er galt.
if($navn=="" || $adresse=="" || $postnummer=="" || $poststed=="" || $epost=="" || $tlf=="" ){
$errors=1;
$error.="<li>Du fyllte ikke ut et påkrevet felt eller et påkrevet felt inneholder ugyldige tegn. Du kan kun bruke tall og bokstaver. Klikk tilbake og prøv en gang til.";

// se genVal($str) neders
if(!genVal($navn) || !genVal($adresse) || !genVal($postnummer) || !genVal($poststed) || !genVal($tlf) || !genVal($kommentar))
{
$errors=1;
$error.="<li>Enkelte av feltene du har fylt inn inneholder ugyldige tegn";
}
}

// validere e-post, Eregi: This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged.
if(!eregi("^[a-z0-9]+([_\\.-][a-z0-9]+)*" ."@"."([a-z0-9]+([\.-][a-z0-9]+)*)+"."\\.[a-z]{2,}"."$",$epost)){
$error.="<li>Ukorrekt epostadresse ble skrevet inn";
$errors=1;
}
if($errors==1){
echo $error;
}else{
$where_form_is="http".($HTTP_SERVER_VARS["HTTPS"]=="on"?"s":"")."://".$SERVER_NAME.strrev(strstr(strrev($PHP_SELF) ,"/"));
$message="Bestilling fra nettbutikken\n
boka: ".$bok1."
Antall boka: ".$antall1."
satt: ".$bok2."
Antall satt: ".$antall2."
Navn: ".$navn."
Adresse: ".$adresse."
Postnummer: ".$postnummer."
Poststed: ".$poststed."
Epost: ".$epost."
tlf: ".$tlf."
Kommentar: ".$kommentar."
";

$message = wordwrap($message, 70); //maks 70chars per linje
mail("tonny@tonny12.no","Bestilling av materiale fra carspecial", utf8_decode($message),"From: Carspecial shop");

function genVal($str=NULL)
{
//forenklet validerings funksjon
if(empty($str))
{
return false;
}
// vanlig quote er ikke med her
$TryggeChars = addslashes('.!?.\'*|$[]<>%#^/:;').'\\w\\pL \\(\\)\\&-';
if(preg_match('^['.$TryggeChars.']\\z/um', $str)) // /u = UTF-8 encodedcheck - krever at dokumentet er UTF-8 /m er multiline, så den ikke stopepr på linjeskift(\n)
{
// om ikke noe matcher noe annet enn hva som er lov
return $str;
}
return false;
}
?>

Poenget er at sikkerhet er en prosess som må tas med når applikasjonene skrives, da slipper en mange "fikser" i etterkant, som kanskje åpner for nye hull... Ja utviklingstiden blir lengre, men for all del det er verdt det!

Hvorfor trenger man egentlig å vaske inndata som settes inn i en database? Kan man ikke bare gjøre det på utdata? Da tenker jeg på html koder.

Prøvd å putte tegn og bokstaver i en rad som skal ha int(heltall)?
Og det er da ingen som har navn med for eksempel <> i seg, derfor er det heller ingen vits i å tillate dette:)
 
Sist redigert av en moderator:

skogtrollet

Medlem
Ah den ser jeg. En ulempe med å vaske innput blir da at informasjonen i databasen blir større og tar mer plass. Og det kan skape problemer hvis et felt har maks grense på f.eks 10 bokstaver, og vaksingen fører til at strengen blir lengre enn 10 tegn.
 

Zolic

Medlem
Det virker det bortsett fra at når et påkrevet felt ikke blir fyllt å så kommer beskjeden på neste side:

Fatal error: Call to undefined function genval() in /home/ladfgo/public_html/sdfgia.no/nettbutikk/process.php on line 50

putt
Kode:
function genVal($str=NULL)
{
//forenklet validerings funksjon
if(empty($str))
{
return false;
}
// vanlig quote er ikke med her
$TryggeChars = addslashes('.!?.\'*|$[]<>%#^/:;').'\\w\\pL \\(\\)\\&-';
if(preg_match('^['.$TryggeChars.']\\z/um', $str)) // /u = UTF-8 encodedcheck - krever at dokumentet er UTF-8 /m er multiline, så den ikke stopepr på linjeskift(\n)
{
// om ikke noe matcher noe annet enn hva som er lov
return $str;
}

i en egen fil, så kjører du require_once('denfila.php'); på alle side hvor det blir benyttet :) husk at det er case-sensitivt hva funksjonsnavnet heter!


@skogtrollet og hansvh: det er viktig å skille imellom input-vasking, input-validering og output-escaping. Input-vasking gjør ikke data større, da den fjerner det som ikke hører til.
Input-validering vil heller ikke gjøre det noe større, da den vil gi en feilmelding om det ikke blir godtatt.
Output-escaping, kan gjøre data noe lengre ja... dette må tas med i bereiningen når database strukturen lages(men nå er det bare meta-tegn til database som skal escapes før det sendes dit, så er ofte minimal øknik i lengde)...

Og utdata til browser skal i utganspunktet ikke vaskes, men escapes;)
 
Sist redigert:

Tonny Kluften

Administrator
Takk igjen Zolic. Den er god.

Da henter jeg inn dette.

<?php
function genVal($str=NULL)
{
//forenklet validerings funksjon
if(empty($str))
{
return false;
}
// vanlig quote er ikke med her
$TryggeChars = addslashes('.!?.\'*|$[]<>%#^/:;').'\\w\\pL \\(\\)\\&-';
if(preg_match('^['.$TryggeChars.']\\z/um', $str))
// /u = UTF-8 encodedcheck - krever at dokumentet er UTF-8 /m er multiline, så den ikke stopper på linjeskift(\n)
{
// om ikke noe matcher noe annet enn hva som er lov
return $str;
}
return false;
}
?>

(Skal vel ha med
PHP:
return false;
}
på slutten selv om du ikke hadde tatt med den i koden over?)

Så får jeg en ny feilmelding:

Warning: preg_match() [function.preg-match]: Unknown modifier '/' in ... /incbutikk.php on line 11 on line 11
 
Sist redigert:

Zolic

Medlem
Yes, den skal med, den gikk bare glipp av merkingen ;)
Jeg var litt rask i svingen tydeligvis, det skal være(endre hele linja:

$TryggeChars = addcslashes('.!?.\'*|$[]%#^/:;', '.!?.\'*|$[]<>%#^/:;').'\\w\\pL \\(\\)\\&-';


notat: $tryggechars, det som står inne addcslashes('dette er lovlige tegn', 'dette er tegn som må escapes for preg motoren').
 

erlinglothe

New Member
Er vel fortsatt bom?

Denne er vel bedre

$TryggeChars = addcslashes(".!?.\'*|$[]%#^/:;", ".!?.\'*|$[]<>%#^/:;').'\\w\\pL \\(\\)\\&-");
 
Topp