Avatar billede udvikler Nybegynder
03. februar 2006 - 21:27 Der er 92 kommentarer og
1 løsning

Et par tips til sikkerhed i php systemer

Jeg kunne godt tænke mig ca. 5 tips som er værd at vide når man skal forbedre sine php systemer sikkerhedsmæssigt.

Jeg tænker på ting som gør det svære at bryde ind i ens ting. Har hørt om "Session Hijacking" osv. Hvordan beskytter man sig mod sådanne ting?
Avatar billede jakobdo Ekspert
03. februar 2006 - 22:12 #1
session hijacking, kan du gøre svære ved at gemme session i en database sammen med ip.
På den måde skal en hijacker både overtage session'en og ip'en samtidig!
Ligeledes er det altid godt at bruge mysql_real_escape_string() når ting skal gemmes i DB.

Generelt kan du også læse en masse gode tips på denne side: http://dev.mysql.com/tech-resources/articles/guide-to-php-security.html
Avatar billede udvikler Nybegynder
03. februar 2006 - 22:20 #2
har også læst om mysql_real_escape_string() og kunne godt tænke mig kort sagt at høre hvad den gør. For der er mange sider der siger noget forskelligt :S

Er det ikke for at sikre at alt går som det skal i databasen når man indsætter?

skal man også bruge den ved UPDATE og DELETE, eller kun ved INSERT
Avatar billede jakobdo Ekspert
03. februar 2006 - 22:33 #3
Du skal bruge den når du tager input fra link eller brugeren.
F.eks.:
SELECT * FROM tabel WHERE id = $_GET['id']
eller
SELECT * FROM tabel WHERE id = $_POST['id']

Her kommer der data udefra, og bliver det ikke escapet, kan man lave det som hedder SQL injections.

Den gør det at tegn som \, ', ", NULL, og nogle andre escapes til: \\, \', \" og kan ikke lige huske NULL (det står garanteret under mysql_escape_real_string i php manualen)
Avatar billede udvikler Nybegynder
03. februar 2006 - 22:40 #4
aah ok, men skal man også benytte dem i UPDATE,INSERT og DELETE ? Eller er det kun SELECT

Kender du forresten flere sikkerheds tips ?
Avatar billede jakobdo Ekspert
03. februar 2006 - 22:46 #5
Ja, hver gang du har user-input i dine sql'er!
Så både: SELECT, UPDATE, DELETE, INSERT, REPLACE, CREATE og hvad de alle sammen hedder!
Har du læst hele linket fra før?
Og ellers tror jeg ikke lige jeg har nogle gode sikkerhedstips.
Avatar billede udvikler Nybegynder
03. februar 2006 - 22:49 #6
Ja nu forstår jeg, så dvs hvis jeg bruger:

$id = $_POST['id'];

mysql_query("SELECT * FROM database WHERE id = '$id'") or die(mysql_error());

så skal mysql_real_escape_string() ikke med?
Avatar billede udvikler Nybegynder
03. februar 2006 - 22:50 #7
når det er forklaret, så læg et svar ;-)
Avatar billede jakobdo Ekspert
03. februar 2006 - 22:51 #8
Jo, så skal du netop have mysql_real_escape_string() med!
På denne måde:

$id = mysql_real_escape_string($_POST['id']);

mysql_query("SELECT * FROM database WHERE id = '$id'") or die(mysql_error());

Og et svar!
Avatar billede polle007 Nybegynder
03. februar 2006 - 22:51 #9
det er ikke kun et spørgsmål om at benytte mysql_real_escape_string. Denne vil f.eks. ikke være beskytte mod injektion:

$id = mysql_real_escape_string($_GET['id']);
SELECT * FROM tabel WHERE id = $id

du er nødt til at kontrollere, at variablen rent faktisk er et tal
Avatar billede udvikler Nybegynder
03. februar 2006 - 22:53 #10
og det kan man gøre med hvilken funktion og hvordan?

- har nemlig aldrig hørt om at tjekke om given variabel indeholder tal eller bogstaver
Avatar billede polle007 Nybegynder
03. februar 2006 - 22:54 #11
Den nye jakobodo postede, har apostrof rundt om $id, og så vil det faktisk være nok med mysql_real_escape_string. Sql injection er et omfattende emne, som du nok bør google lidt på
Avatar billede polle007 Nybegynder
03. februar 2006 - 22:56 #12
En simpel test kan udføres med is_numeric funktionen
Avatar billede udvikler Nybegynder
03. februar 2006 - 23:00 #13
aha, tusinde tak.. Jeg smutter i seng nu, men i er mere end velkommne til at lægge flere tips! Så er i bare for gode :-)

Ha' det godt !
Avatar billede jakobdo Ekspert
03. februar 2006 - 23:08 #14
Takker for point!
Avatar billede johan.o Nybegynder
04. februar 2006 - 01:55 #15
Nu er der ikke så lang tid til det begynder at sne og blive rigtig koldt igen, og det er lige præcis det der skal til for at man kan sidde og 'hygge' sig med følgende link :)

http://www.owasp.org/index.html

Hvis du så, i menuen, vælger: Documentation --> Guide --> Downloads, kommer du til en side hvor du kan hente OWASP's (The Open Web Application Software Project) Guide to Building Secure Web Applications.

Den indeholder utrolig meget og god information om svagheder og løsninger på samme. Det er naturligvis en meget bredt favnene kilde men hvis du tager dig tid til at få overblik over indholdet kan du sagtens finde f.eks. information om database svagheder.

Og med hensyn til svagheder, så er det nærmest et mantra at det vigtigeste i forbindelse med f.eks. php scripts, er "ALTID CHECK UDEFRA KOMMENDE DATA.....ALTID !!", det anbefales faktisk at gå et lille skridt videre og istedet for at forsøge at rette/fjerne uhensigtsmæssige karaktere f.eks., så dropper man alt input som ikke passer ind i den syntaks der forventes/kræves.

F.eks. har du et input felt i en HTML form hvor en bruger kan skrive sit brugernavn. Du har ved oprettelsen af din application bestemt at brugernavne kun må indeholde store og små bogstaver fra a-å. Så vil det jo være en god ide at checke for dette når dit php script modtager indholdet fra dette input felt.

Kunne gøres således :

$user="";
if(isset($_POST['user']) && preg_match("/^[a-zæøå]+$/i", $_POST['user'])) {
$user=$_POST['user']; }

Nu er det jo ikke alle input felter der er lige så simple at checke som dette felt, men det vigtigeste er sådan set også blot at du i designet af din software bruger tid på at bestemme hvordan dit user input skal se ud, og derefter checker at det passer.

En anden ting er tilbage meldinger til brugeren om fejl i det indtastede. Personligt er jeg holdt op med at give sådanne tilbage meldinger. Hvis du f.eks. gør en bruger opmærksom på at han har skrevet et forkert brugernavn, gør du inddirekte også en hacker opmærksom på hvornår han har skrevet et rigtigt. Og jo mere en hacker ved om dit site jo mere sårbart er det.

En hacker vil altid snuse lidt rundt på dit site før han bestemmer sig for hvordan han vil angribe det. Hvis du sørger for at give ham så lidt information som muligt mens han snuser, er det sandsynligt at han vil opgive relativt hurtigt og istedet lede efter et nemmere offer, med mindre selvfølgelig at han decideret har udvalgt dit site.

Blandt snuse tingene er f.eks. læse dine tilbagemeldinger på forkerte indtastninger, lede efter password reset funktioner, skrive input som skal generer fejl meddelelser i f.eks. din sql database osv. osv.

Personligt gør jeg det at jeg laver en 'venlig' bruger validering i javascript. Den checker f.eks. om de felter der skal udfyldes er udfyldt og om der er 'ulovligt' indhold i nogle felter. I javascript delen gøres opmærksom på diverse fejl men på serveren er der ingen nåde. Hvis ikke det input der modtages stemmer overens med den forventede syntaks, droppes alt input og formen reset'es uden nogen fejl meddelelse fordi jeg kan med rimelig sikkerhed, gå ud fra at en bruger bevidst har omgået min javascript validering og derfor ikke er venlig sindet.

Det bringer mig hen på et andet tiltag du kan overveje. Du bør monitorere brugen af din software. F.eks. bør du logge alle mislykkede login forsøg og checke disse log's regelmæssigt for at se om der foregår noget usædvanligt. Er der f.eks. 2000 mislykkede logins med diverse underlige brugernavne og passwords ved du at du er under angreb og viden er magt :)

Nogle site's bruger f.eks. URL'en til sende filnavne på sider som skal inkluderes på deres index.php side således : http://www.domæne.dk/index.php?link=test hvor den side der skal inkluderes så hedder test.php. Når du laver check af variablen $_GET['link'], som du jo skal da det er en udefra kommende variabel, ved du jo at hvis det der står i $_GET['link'] ikke er en eksisterende fil på din server, så sidder en eller anden og prøver at snuse hvordan din software er brygget sammen. Derfor kan du roligt skrive en sådan hændelse i en fejl log og samtidig sende en mail til administrator om at der foregår noget lusk på dit site, samt fortælle hvad $_GET['link'] indeholdt da det skete.

Puha, der er bare meget man skal tænke på og overveje og det er umuligt at huske det hele og derfor er ovenstående link en rigtig god hjælp. God læselyst og skriv endelig hvis jeg skal forsøge at uddybe noget af det jeg har skrevet.

Mvh. Johan
Avatar billede johan.o Nybegynder
04. februar 2006 - 02:02 #16
Og en anden ting :), i forbindelse med sql query's. Hvis du ikke har mulighed for at checke 'hårdt' så kan du sørge for at visse sql keywords medfører at input valideringen bortkaster input'et. F.eks. SELECT, UPDATE, UNION, LIKE, DELETE, DROP, TRUNCATE osv. osv. så lammer du ihvertfald en evt. hackers muligheder for at lave L... i din db :)

Mvh. Johan
Avatar billede jakobdo Ekspert
04. februar 2006 - 08:12 #17
Godt indlæg Johan! :o)
Avatar billede udvikler Nybegynder
04. februar 2006 - 12:05 #18
Fantastisk indlæg!

Jeg forstod ikke den sidste ting du sagde, du skrev det kl 02:02:56

PS. http://www.eksperten.dk/spm/685268 ;-)
Avatar billede johan.o Nybegynder
04. februar 2006 - 12:15 #19
Jeg sidder lige på arbejdet, men jeg vender tilbage når jeg kommer hjem :)

Mvh. Johan
Avatar billede olebole Juniormester
04. februar 2006 - 14:35 #20
<ole>

Når en bruger forsøger at logge sig ind, så lav et delay på et sekund eller to, før brugeren logges ind eller afvises.
Det betyder intet for den enkelte bruger, der logger ind - men er en ulidelig pest for en 'hacker', der ved at teste med tusindvis af passwords forsøger at 'brute-force' sig vej ind på et beskyttet område  ;o)

Når man inkluderer side med den metode, johan.o viser ovenfor, så skal du altid sørge for at have en form for liste over de dokumenter, der må inkluderes på det pågældende sted - og at du efter en test mod den liste _kun_ inkluderer tilladte dokumenter

/mvh
</bole>
Avatar billede jakobdo Ekspert
04. februar 2006 - 14:49 #21
Olebole: Den slags delay, vil du lave på hvilken måde? sleep() i php f.eks.?
Avatar billede olebole Juniormester
04. februar 2006 - 14:54 #22
Ja, 'sleep' er helt fin til den salgs. Det er normalt en feature, man skal være varsom med at bruge (den må f.eks. _aldrig_ bruges til at simulere 'seamless streaming' i en chat) - men til dette formål virker den upåklageligt (der foretages jo sjældent ret mange logins pr. time)  =)
Avatar billede udvikler Nybegynder
04. februar 2006 - 15:51 #23
det var en god idé, men jeg har brugt en bedre (efter min menuen ;-))

jeg har gjort sådan at man bliver bannet i et bestemt stykke tid efter et vis antal mislykket forsøg.
Avatar billede udvikler Nybegynder
04. februar 2006 - 15:52 #24
og jeg ved ikke hvordan eller hvorfor men jeg har skrevet: "efter min menuen" og det skulle have været: "efter min mening"
Avatar billede olebole Juniormester
04. februar 2006 - 16:33 #25
Det er også en helt udmærket løsning - men et delay på et par sekunder 'banner' i realiteten automatisk brute-force forsøg, hvis en 'hacker' f.eks. skal igennem bare 10-20.000 passwords  ;o)
Avatar billede udvikler Nybegynder
04. februar 2006 - 20:56 #26
har OGSÅ lige indsat et delay på 1 sekund ved hjælp af sleep(1);

nu kan det næsten ikke blive bedre.

Nogle der kender andre sikkerheds tips ? :-)
Avatar billede johan.o Nybegynder
04. februar 2006 - 21:01 #27
Med hensyn til mit efternøler indlæg :)

I forbindelse med at man laver user input validering, kan man checke om det indtastede indeholder nogle af de mest alm. mySQL keywords f.eks. select, drop, update eller --. Hvis det brugeren skriver indeholder et eller flere af disse ord bør det mindst tænde en advarsels lampe eller simpelthen bevirke at brugerens input smides bort og formen reset'es.

Umiddelbart vil man måske tænke at det er jo ikke nødvendigt hvis jeg f.eks. bruger mysql_real_escape_string() men det er et andet vigtigt 'mantra', lad være med at vente på at en hacker finder hullerne, gør derimod alt hvad du kan for at forhindre ham i at 'arbejde' videre hvis han alligevel bryder igennem dine første forsvars mekanismer. Eller sagt på en anden måde, lad være med at tro at fordi du bruger mysql_real_escape_string() så er du home safe.......

Alt afhænger naturligvis af hvad det er man forsøger at 'gemme' for en hacker, er det en opskrift på sydfynsk landpølse eller er det følsomme personlige oplysninger. Dette afgør selvfølgelig antallet og omfanget af forsvars mekanismer man bør indføre. Men lad os bare for diskussionens skyld prøve at garderer os mod så meget som vi kan komme i tanke om :)

Så hvis et eller flere af de før nævnte keywords optræder i brugerens input bør input'et smides bort fordi, hvis vores første 'line of defence' ryger vil en hacker kunne bruge disse keywords til først og fremmest at ødelægge indholdet i vores tabeller, men derudover vil de også gøre ham istand til at få et overblik over hvordan tabellerne er bygget op og hvad de indeholder. Og da viden jo er magt, så kan det jo være han ved at have adgang til disse oplysninger kan finde frem til yderligere svagheder i vores database.

Og forresten så vil '--' afslutte en query, uanset hvad der følger efter, og det er jo meget brugbart for en hacker at kunne bestemme hvor en evt query skal afsluttes.

En anden ting jeg kom til at tænke på idag er risikoen ved at en bruger 'injektor' f.eks. javascript kode i din database, som så eksekveres på f.eks. andre brugeres computer. Her kan man bruge php's htmlentities(), denne metode omskriver f.eks. et <script> tag til &lt;script&gt; hvilket bevirker at det ikke tolkes som et tag, men derimod som ren tekst.

Nå nu river min hustru i computeren så jeg må hellere slutte så hun kan komme på hestenettet.....tsk tsk :)

Mvh. Johan
Avatar billede udvikler Nybegynder
04. februar 2006 - 21:10 #28
1. Hvordan kan jeg så lave en funktion som finder alle steder hvor der står INSERT,UPDATE,DELETE,DROP,SELECT osv. i en string/variabel ?

2. du siger at "-- vil afslutte en query" hvordan kan man så tjekke om en string/variabel indeholder -- ? og vil dette problem ikke være løst ved htmlentities ???
Avatar billede johan.o Nybegynder
04. februar 2006 - 22:25 #29
1.: f.eks. :

$str="";
if(!preg_match("/(insert|update|select|union|drop|delete|truncate|where|show|into|set|--)/i", $_POST['str'])) {
$str=$_POST['str']; }

2.:

'--' er inkluderet i ovenstående check, og htmlentities har ingen effekt på bindestreger.

Mvh. Johan
Avatar billede polle007 Nybegynder
04. februar 2006 - 22:32 #30
I mysql benyttes # til at markere start på kommentar
Avatar billede johan.o Nybegynder
04. februar 2006 - 23:56 #31
Med hensyn til min bemærkning om filnavne i URL som skal inkluderes, har jeg lavet dette script som måske kan ligge som grund for en diskussion.

<?php

function err_log($no, $err) {
$w_str=date("y.m.d H:i:s")." --> ".$no." : ".$err." - IP : ".$_SERVER['REMOTE_ADDR']."\r\n";
if(isset($_GET['link'])) { $w_str.="  Link : ".$_GET['link']."\r\n"; }
if($handle=fopen("err_log.txt", "a")) {
  if(is_writeable("err_log.txt")) {
  if(fwrite($handle, $w_str)) {
    $w_str.="Err log OK.\r\n"; }
  else {
    $w_str.="Err log failed !\r\n"; }
  fclose($handle); } }
mail("mail@domæne.dk", "domæne.dk - Error report.", $w_str);
return; }

function check_link($page) {
if(file_exists($page.".htm")) { return $page.".htm"; }
if(file_exists($page.".php")) { return $page.".php"; }
if(file_exists($page.".doc")) { header("location: ".$page.".doc"); exit; }
if(file_exists($page.".pdf")) { header("location: ".$page.".pdf"); exit; }
err_log("Hack attempt", "URL modification");
header("location: index.php"); exit; }

if(isset($_GET['link'])) {
if($_GET['link']!=preg_replace("/[^a-z0-9\/]/", "", $_GET['link'])) {
  err_log("Hack attempt", "URL modification");
  header("location: index.php"); exit; }
$filename=check_link($_GET['link']);
include($filename); }

?>

Hvis du vil teste så gem ovenstående som index.php og omskriv mail adressen i mail() funktionen til din egen mail. Derudover kan du gemme en simpel html fil og kalde den inc.htm

Prøv så at skrive index.php?link=inc så skulle din simple html fil gerne inkluderes men prøv så at skrive f.eks. index.php?link=inc.php eller index.php?link=ikkeenfil

Forhåbentlig sker der det at du får oprettet en fejl log (err_log.txt) og du modtager en mail om at der har været en 'hændelse' på dit domæne.

Mvh. Johan
Avatar billede olebole Juniormester
05. februar 2006 - 11:18 #32
johan >> jeg går udfra, vi kan være enige om, at forslaget (04/02-2006 22:25:10) ikke er videre anvendeligt i den virkelige verden.
Der er i hvertfald masser af fora, hvor man gerne skulle kunne skrive ord som 'show', 'drop', 'union', 'update' og 'set' uden at indlægget bliver afvist - og mange fora ville være direkte ubrugelige med den test  ;o)
Avatar billede jakobdo Ekspert
05. februar 2006 - 11:44 #33
Johan.o: Din funktion:
function check_link($page) {
if(file_exists($page.".htm")) { return $page.".htm"; }
if(file_exists($page.".php")) { return $page.".php"; }
if(file_exists($page.".doc")) { header("location: ".$page.".doc"); exit; }
if(file_exists($page.".pdf")) { header("location: ".$page.".pdf"); exit; }
err_log("Hack attempt", "URL modification");
header("location: index.php"); exit; }
Er den ikke skidt i længden?
Hvis en bruger har success med at uploade en fil, f.eks. filemanager.php så vil han jo stadig kunne åbne den fil med dit script.
Avatar billede olebole Juniormester
05. februar 2006 - 11:50 #34
jakobdo >> helt enig, hvorfor jeg i (04/02-2006 14:35:32) nævner, at man have en liste af 'lovlige' filer, der testes mod.
At teste på, om filen eksisterer, giver aller højst falsk tryghed ... der ligger absolut ingen sikkerhed i det  ;o)
Avatar billede jakobdo Ekspert
05. februar 2006 - 11:51 #35
Havde jeg faktisk godt læst, men glemt siden hen. Sorry! :o)
Avatar billede olebole Juniormester
05. februar 2006 - 12:04 #36
jakobdo >> Don't be!  =)
Det var absolut ikke for at give dig én over nallerne (tværtimod) - men mere for at understrege problematikken. Faktisk kan det ikke understreges tydeligt nok, at inkludering på baggrund af brugerinput er noget, man skal være hysterisk varsom med - og at evt. løsninger skal være nærmest 'tankemæssigt udkogt', før de implementeres  ;o)
Avatar billede jakobdo Ekspert
05. februar 2006 - 12:06 #37
Det er ved at være en ganske fornuftig tråd, jeg har faktisk lært en masse... (men man skal jo også lære så længe man lever)
Avatar billede olebole Juniormester
05. februar 2006 - 12:14 #38
Ak ja, kunne man bare blive ved med at leve, sålænge der var noget at lære  ;D
Avatar billede udvikler Nybegynder
05. februar 2006 - 13:04 #39
Hej igen :)

Hvad ville i så gøre med hensyn til at tjekke for alt bruger input der kommer?
I har jo lige sagt at 04/02-2006 22:25:10 ikke kan bruges i praksis.
Jeg har allerede brugt mysql_real_escape_string(); på ALLE inputs samt adslashes nogle steder. Det jeg prøver at beskytte mig mod er nok mest Sql injections, da jeg har læst at det er den mest normalle måde at blive hacket på.

Hvad vil i mene vi burde tage op nu? :-P
Session Hijacking?
Cross-site-scripting?

Der er massere, hvis i vil have point så sig til, jeg ved i er her for at hjælpe. Min mening er dog at der er en grænse, i skal have tak for hjælpen på en eller anden måde! :)
Avatar billede jakobdo Ekspert
05. februar 2006 - 13:16 #40
Altså ved at tjekke sider, kunne du f.eks. bruge:

switch($_GET['site'])
{
case "forside":
include("forside.php");
break;
case "nyheder":
include("nyheder.php");
break;
default:
//Forsøg på hack...
}

Og som der tidligere er nævnt, så er mysql_real_escape_string() ikke løsningen på alt.
Hvis du f.eks. skal have et ID, og det ID er et nummer, så tjek: is_numeric($_GET['id'])
og brug ellers regexp til f.eks. brugernavne.
Avatar billede olebole Juniormester
05. februar 2006 - 13:22 #41
Du kunne have et array i en fil, du selv inkluderer. I det array lægger du alle de dokumenter, en bruger må inkludere:

$allowedIncludes = array(
    "side1.php" => 1,
    "side2.php" => 1,
    "side3.php" => 1,
    "side4.php" => 1
);

Så kan du skrive:

if ( isset($_GET["link"]) ) {
    $filename = $_GET["link"];
    if ( $filename != preg_replace("/[^a-z0-9\/]/", "", $filename) ) {
        // Log evt. et hacker-forsøg her
        header("Location: index.php");
        exit;
    }
    if ( !$allowedIncludes[$filename] ) {
        // Log evt. et hacker-forsøg her
        header("Location: index.php");
        exit;
    }
    include($filename);
}
Avatar billede udvikler Nybegynder
05. februar 2006 - 13:24 #42
den med is_numeric($_GET['id']) er rigtig god ! Den tilføjer jeg straks til hele systemet! :)

skal man bare gøre sådan:

        if (is_numeric($_GET['id'])) {
                echo "ok";
        }else{
                echo "fejl";
        }

og hvad mener du med "brug regexp til f.eks brugernavne"
hvad skal da tjekkes ved brugernavne? det kan jeg ikke se noget "usikkert ved"
Avatar billede olebole Juniormester
05. februar 2006 - 13:28 #43
- måske det kan synes at ligen 'bukser og seler' at medsende filens extension, meeeeen ... det sikrer, man ikke behøver at frygte, man kommer til at lave en fil med én extension, som ikke må inkluderes - og en anden med samme navn, men en anden extension, som gerne må inkluderes.

Altså skal man i mit eksempel kalde siden med:
    http://www.domain.dk/sti/til/fil.php?link=side2.php
Avatar billede udvikler Nybegynder
05. februar 2006 - 13:28 #44
og forresten så bruger jeg ikke den der metode www.domain.com/index.php?page=site
så det behøver ikke at foreslå længere (bare sådan så jeg ikke spilder jeres dyrebare tid med det!!) ;-)
Avatar billede olebole Juniormester
05. februar 2006 - 13:29 #45
Hvad var det, jeg fik skrevet?  :D
  "- måske det kan ligne 'bukser og seler' ..."
Avatar billede udvikler Nybegynder
05. februar 2006 - 13:32 #46
Hehe, læs lige 13:24:12.. Var det sådan man skulle gøre?
Avatar billede jakobdo Ekspert
05. februar 2006 - 13:32 #47
OleBole: Jeg tror du mente, at man kan gå på line med bukser og seler! :o)
Avatar billede jakobdo Ekspert
05. februar 2006 - 13:33 #48
Aco: Ja, det er en mulighed! (det er jo også det sjove ved kodning, du kan lave flere ting som giver samme løsning, eller tæt på samme løsning ihf)
Avatar billede udvikler Nybegynder
05. februar 2006 - 13:41 #49
hvad vil i så mene at jeg kan gøre for at beskytte bruger systemet mest muligt?

Indtil videre er der kun md5 hash :)
Avatar billede johan.o Nybegynder
05. februar 2006 - 15:29 #50
Med hensyn til at checke for keywords så er vi fuldstændig enige om at det er i relativt begrænsede situationer man kan eller har brug for at bruge denne fremgangsmåde, men de steder hvor den er brugbar er den tilgengæld meget effektiv.

Med hensyn til include's af filer, så er serveren vel allerede 'overtaget' hvis en bruger har mulighed for at uploade en fil som ikke kan tåle at blive inkluderet. Jeg mener hvis brugeren har uploaded filemanager.php så kalder han den vel bare direkte.

--> aco, jeg ved godt at du ikke bruger denne metode, men emnet er spændende :)

Session-highjack.

Jeg har faktisk skrevet en lille artikel som snuser til emnet...og i dagens anledning gjort den gratis.

http://www.eksperten.dk/artikler/857

Den 'løsning' der tages op i artiklen er absolut ikke fejlfri. Som det nævnes kan en 'angriber' surfe med et stjålet session id, så længe den originale ejer af dette id ikke bevæger sig på sitet.

Der er mange måder session highjacking kan ske. Udover direkte 'sniffing' af traffik så er dette også en mulighed.

Forestil dig et bruger forum hvor man har mulighed for at logge sig på med brugernavn og kode men man har også mulighed for at logge sig på anonymt.

Jeg logger mig først på anonymt og kigger så på de(n) cookies jeg bliver tildelt. Der kan f.eks. være en cookie der hedder 'SESSIONID'. Så nu har jeg en rimelig formodning om at session id's gemmes i denne cookie.

Så skriver jeg et indlæg (anonymt) hvor jeg ligger et link til en af mine egne sider. På denne side har jeg et php script som checker om den bruger der besøger siden har en cookie der hedder SESSIONID, hvis dette er tilfældet, sender den en mail til mig med indholdet af denne cookie.

Så nu sætter jeg mig og venter på at modtage en mail fra min side.

Når mailen kommer kan jeg relativt nemt logge på anonymt og så ændrer indholdet i min SESSIONID cookie til det jeg fik i mailen og voila, jeg har highjacket en brugers session.

Det kræves naturligvis at der ikke er foretaget nogen andre former for check i brugerforummet end at hvis SESSIONID er et korrekt id, så er du logget ind, men princippet er overaskende enkelt.

Hvad gør man så for at forhindre denne fremgangsmåde ?

Ja, min artikel giver et bud på en løsning, men jeg hører da gerne om andres erfaringer.

Mvh. Johan
Avatar billede olebole Juniormester
05. februar 2006 - 15:33 #51
johan >> at læse en cookie fra et andet domæne kræver så, der benyttes en buggy browser  :)
Avatar billede jakobdo Ekspert
05. februar 2006 - 15:38 #52
Kan session-hijacking ikke undgåes (eller gøres svære) ved at gemme IP?
Altså når en bruger logger ind, så gemmer vi IP og session ID i en tabel.
Så tjekker vi hele tiden om ip og session stemmer overens, hvis ikke, så logges brugeren af.
Avatar billede udvikler Nybegynder
05. februar 2006 - 15:52 #53
jeg har lige læst hele din artikel grundigt igennem, og jeg vil ligesom jakobdo mene at det ville være nemmere og mere sikkert at gemme ip'en og session id'et i en tabel og derefter tjekkes det hver gang en bruger logger på.

har dog lige nogle spørgsmål:

- er session id'et det samme for én bruger hver gang han/hun logger på ?
- hvordan gemmer man et session id ?
Avatar billede johan.o Nybegynder
05. februar 2006 - 17:36 #54
Ang. ip som identifikation. I langt de fleste tilfælde vil det være en udemærket måde, men ikke alle har fast ip adresse og derudover kan et netværk af computere som sidder bag en proxy, vise samme ip for alle computerne i netværket. Så i disse tilfælde vil en se ud som mange eller mange vil se ud som en. Det skal siges at dette er taget råt for usødet fra en artikel jeg har læst, jeg er ikke selv netværks haj, men det var medvirkende til at jeg ville prøve at finde en anden metode.

olebole --> Ja, det har du da så ret i, jeg sidder og blander det sammen med session id i url'en, ups :)

Jeg har læste for nyligt noget om at man kunne danne nye session id's ved hvert besøg, men kan ikke lige huske om det kun var i PHP 5 eller.....det må jeg lige kigge på :)

aco --> Ja, hvis ikke man bevidst forsøger at ændre det, så er det et unikt id der følger den enkelte session.

Session id finder du således : $sesid=session_id();

Mvh. Johan
Avatar billede olebole Juniormester
05. februar 2006 - 17:40 #55
Ja, så kan den hentes med noget 'referer-noget' ... endnu en god grund til at sætte session-cookies  ;o)
Avatar billede olebole Juniormester
05. februar 2006 - 17:42 #56
- og i dette hjem sidder 5-6 PC'er på samme lan = samme IP. Endvidere vil enhver ondsindet besøgende vel gå gennem en proxy  =)
Avatar billede jakobdo Ekspert
05. februar 2006 - 18:27 #57
Selvom 2 computere har samme ip, så vil det jo ikke ændre noget!
For hvis man har en bruger som logger ind, han får et sessions id og det gemmer vi så i tabellen sammen med hans ip.
Næste gange den bruger laver noget igen, så tjekker vi at sessions id og ip stemmer overens.

En person som laver session-hijack, vil få svært ved at komme fra samme ip.
Avatar billede olebole Juniormester
05. februar 2006 - 18:43 #58
- overhovedet ikke. De PC'er, der står i dette hjem, tilhører forskellige personer - der i øvrigt ikke alle er i familie. Der kunne i teorien godt forekomme forsøg på session-hijacking. Det kunne der også i et stort firma, hvor 2-300 PC'er befinder sig bag samme IP  :)
Avatar billede olebole Juniormester
05. februar 2006 - 18:45 #59
- og i det øjeblik, du kommer ind på mit site, kender jeg din IP (hvis den er statisk). Derefter er det pærelet at 'udsmykke' sig med samme IP via en proxy.

Der er ikke meget, der er lettere end at fake en IP  ;o)
Avatar billede polle007 Nybegynder
05. februar 2006 - 19:04 #60
Sidder man på samme lokale netværk, skal der helt andre midler til, da man her har mulighed for at sniffe sit offers trafik.

Jeg vil ikke påstå, at det er nemt at fake en vilkårlig ip adresse
Avatar billede udvikler Nybegynder
05. februar 2006 - 19:05 #61
puha, nu er jeg da forvirret. :)

Hvordan vil i så mene jeg skal undgå Sessin hijacking bedst muligt?
- begrund jeres svar!
Avatar billede olebole Juniormester
05. februar 2006 - 19:48 #62
polle007 >> "Jeg vil ikke påstå, at det er nemt at fake en vilkårlig ip adresse"

- det behøver du heller ikke, da jeg jo allerede har gjort det. Det bliver gjort millioner af gange i døgnet, verden over  ;o)
Avatar billede polle007 Nybegynder
05. februar 2006 - 19:49 #63
ole, undskyld, hvad? hvis jeg har ip adresse 80.1.2.3
påstår du så, at du med nemhed kan tilgå en webserver, og udgive dig for at være mig?
Avatar billede olebole Juniormester
05. februar 2006 - 19:53 #64
Ja  :)
Avatar billede polle007 Nybegynder
05. februar 2006 - 19:54 #65
Så giv mig opskriven, og jeg snakker ikke om at sætte en http header, som alle kan forfalske
Avatar billede udvikler Nybegynder
05. februar 2006 - 19:55 #66
hov hov, tror det er ulovligt det der :-)
Avatar billede olebole Juniormester
05. februar 2006 - 19:59 #67
polle007 >> Du beder mig om at give dig opskriften på at bruge en andens IP i et offentligt forum?

Det bliver den dag, Dolly Parton har sovet på maven en hel nat igennem!  :D
Avatar billede polle007 Nybegynder
05. februar 2006 - 20:01 #68
vi ved jo begge to, at det gør man ikke bare. Alene det at få en TCP samtale igang, er lidt af en udfordring, for ikke at snakke om, at du skal reroute trafikken, så webserveren sender til din ip og ikke min
Avatar billede olebole Juniormester
05. februar 2006 - 20:17 #69
Vi ved forhåbentlig også at der er tusindvis af 'hackere', der gør det dagligt - og det er vel dem, vi bør bekymre os om i denne situation ... ikke fru Jensens nevø henne på hjørnet  ;o)
Avatar billede polle007 Nybegynder
05. februar 2006 - 20:19 #70
ole, det er overhovedet ikke så nemt som du gør det til. Tidligere i tråden påstod du også det være en smal sag
Avatar billede polle007 Nybegynder
05. februar 2006 - 20:21 #71
hvis der ikke kommer flere kommentarer fra mig, så er det fordi jeg ikke gider diskutere det yderligere :o
Avatar billede olebole Juniormester
05. februar 2006 - 20:22 #72
Ja - og det gør jeg stadig. For folk, der beskæftiger sig med hacking, er det ikke spor svært - og jeg går som sagt stadig udfra, det er dem, der er problemet i denne sammenhæng  :)
Avatar billede olebole Juniormester
05. februar 2006 - 20:23 #73
*LoL* jamen, det er da helt okay  :D
Avatar billede johan.o Nybegynder
05. februar 2006 - 21:21 #74
aco --> 'Hvordan vil i så mene jeg skal undgå Sessin hijacking bedst muligt?'

He he, ja som du nok er helt med på efterhånden så er der ikke en entydig gylden løsning. Det jeg syntes du skal gøre er først at vurdere hvilket sikkerheds nivaue du har brug for. Hvis du kommer frem til at du vil have 99% sikkerhed, skal du ikke bruge HTTP protokollen overhovedet, som jeg skriver i artiklen, er alt i denne protokel i klar text og kan læses af alle. I dette tilfælde bør du nok kigge på noget SSL, som der også er nogen der nævner i kommentarene til artiklen.

Hvis du derimod vurderer at så høj sikkerhed ikke er nødvendigt (den er også dyr) så bør du kigge på hvert enkelt tiltag du tænker på at implementere og vurdere fordele og ulemper. Som f.eks. om løsningen udelukker nogen brugere. Derfra kan man faktisk sige at det du forsøger at skabe er 'security through obscurity', altså at man prøver at gøre det umuligt for en hacker at forstå hvad der sker på dit site, og derved forhindre ham i at lave ulykker.

Mvh. Johan
Avatar billede udvikler Nybegynder
05. februar 2006 - 22:21 #75
Jeg vil mene at sikkerheds niveau'et på min side skal være på 70-80%
Siden vil være et community som omhandler et specifikt programmerings sprog. Jeg vil ikke komme ind på sidens indhold yderliger, da det er lidt af en hemmelig endnu. :-)

Hvad koster SSL egentlig, hvis det overhovedet koster noget?

Forresten så ligner min side eksperten på nogle punkter, derfor kan sikkerheds tjek som eksperten foretager også være brugbare. Er der nogle som evt. kan fortælle noget om det, eller må/vil man ikke det?
Avatar billede olebole Juniormester
06. februar 2006 - 00:18 #76
Hmmm ... var lige forbi Fætter Google, men den er holdt op med at opgive, hvor mange sider, der er indekseret. Sidste tal, jeg kan huske er vist noget med 5.000.000.000. Odds for, at nogen udser sig netop dit site er måske ikke så stort. Der er mange ting at veje op mod hinanden ... og er der en, der vil ind og være destruktiv, kommer han ind, hvis han er god nok.
Jeg er ganske på linje med johan.o ... og så læs tråden igennem igen og pluk det, du synes virker fornuftigt - og der opnået rimelig konsensus omkring. Bufferzone har også lige skrevet en artikel om emnet:
    http://www.eksperten.dk/artikler/908
Avatar billede olebole Juniormester
06. februar 2006 - 00:29 #77
- og så skal man naturligvis altid huske, at en bruger altid kan manipulere en form på en side med JavaScript. Jeg har f.eks. i min Hyperlinks-linje i IE en Favorite, der i stedet for at kalde 'http://www.domain.dk/side.html', kalder:
    java script:d=document;t=d.getElementsByTagName('textarea')[0];t.value='<ole>\n\n\n\n/mvh\n</bole>';t.focus();void(0)

- den klikker jeg lige på ved mit første indlæg i en tråd.

Du kan prøve at stå på denne side - paste koden ind i browserens adresselinje og trykke 'Return' og se, hvad der sker - hvis du ikke kan gætte det udfra koden  ;o)

Det er blot et eksempel, men også værdier af hidden fields kan ændres ... alt kan ændres og felter kan slettes og/eller indsættes.
Avatar billede johan.o Nybegynder
07. februar 2006 - 15:56 #78
Kom i tanke om en anden ting i forbindelse med sql injektion.

Ofte er fremgangs måden at en 'hacker' prøver med en sql injektion der gør at alle rækker i tabellen bliver hentet.

F.eks. i et login system :

En bruger indtaster username og pwd --> som sendes til dette script -->

$res=mysql_query("SELECT * FROM users WHERE user='".$_POST['username']."' AND pwd='".$_POST['pwd']."'");

Så vil en mulig sql injektion se således ud : username = ' OR 1=1 --'

Således bliver alle rækker i tabellen returneret, så hvis vi efterfølgende blot skriver :

$row=mysql_fetch_assoc($res);

vil $row blot indeholde den første bruger's data fra tabellen.

Derfor vil det være en god ting at checke hvor mange rækker vores $res indeholder, den bør jo kun indeholde 1 række.

if(mysql_num_rows($res)==1) {
..det er fint, kun 1 række.. }
else {
..hov der er noget galt, enten 0 rækker eller flere end 1.. }

Mvh. Johan
Avatar billede udvikler Nybegynder
10. februar 2006 - 13:55 #79
Er det ikke lidt nemmere at indsætte en LIMIT 1 på ? :-)
Avatar billede olebole Juniormester
10. februar 2006 - 14:00 #80
-aco- >> Der _skal_ være en LIMIT på 1. Ellers lader man jo MySQL rode resten af tabellen igennem, selvom den allerede har fundet det ene match, der skal bruges  ;o)

Det samme gælder iøvrigt updates, hvor man ved, det kun er én bruger, der skal opdateres.

Denne fejl - sammen med brug af '*' - er noget af det, der gør mange PHP-applikationer frygtelig langsomme. Desværre er det meget udbredte fejl blandt PHP'ere  :o|
Avatar billede jakobdo Ekspert
10. februar 2006 - 14:59 #81
Det eksempel johan.o kommer med, vil vel sætte en LIMIT 1 ud af funktion?
Avatar billede olebole Juniormester
10. februar 2006 - 15:21 #82
Ja, men det var nok også mere en principiel betragtning, jeg kom med  ;o)
Avatar billede jakobdo Ekspert
10. februar 2006 - 15:25 #83
Det ved jeg godt! :o)
Det var mere ment til Aco.
Avatar billede olebole Juniormester
10. februar 2006 - 15:31 #84
- hvilket jeg vel egentlig burde have vidst  ;D
Avatar billede johan.o Nybegynder
10. februar 2006 - 16:23 #85
Øhm, ikke helt sikker på at jeg er enig...eller også er jeg :)

Hvis vi tilføjer 'LIMIT 1' aner vi ikke om der er foretaget en korrekt query eller en bruger har fundet et hul. Så ved at udelade dette og istedet checke antallet af returnerede rækker kan vi fastslå om alt er ok, eller ej.

Mvh. Johan
Avatar billede olebole Juniormester
10. februar 2006 - 16:29 #86
Hvis vi forudsætter, at vi beskytter os mod SQL-injection ved at validere på, om bruger-inputtet har et format, som ventet - og iøvrigt escape det på passende måde - burde det ikke være nødvendigt at checke på dette sted.
Vi er vel allerede blevet enige om, at en POST- eller GET-variabel _aldrig_ kan optræde direkte i en SQL-query - i en seriøs applikation  ;o)
Avatar billede morhan Novice
10. februar 2006 - 16:33 #87
Hvis user-kolonnen er unikt, så performer den ikke ringere, fordi limit udelades
Avatar billede olebole Juniormester
10. februar 2006 - 16:37 #88
- men hvorfor tage bukserne ned og tørre sig igen, når man nu lige har gjort det?  Prøv at læse (10/02-2006 16:29:42) igen  ;o)
Avatar billede olebole Juniormester
10. februar 2006 - 16:39 #89
johan.o's eksempel forbryder sig mod de mest grundlæggende forbehold - som har været diskuteret forlængst i denne tråd. Gjorde det ikke det, ville det gøre sig selv overflødigt  ;o)
Avatar billede morhan Novice
10. februar 2006 - 16:41 #90
jeg kommenterede blot din påstand 14:00:20, at der altid _skal_ være limit på, for at den ikke skal lede resten af tabellen igennem..
Avatar billede olebole Juniormester
10. februar 2006 - 16:51 #91
Ja, det er fuldstændig ligesom, at der altid _skal_ gåseøjne om HTML-attributter. Ikke fordi, der _skal_ - men fordi, du så ikke glemmer dem, når de vitterligt _skal_ være der.
Det er et spørgsmål om at indse nyttigheden af en god kodestil, der ikke levner muligheder for fejl, når disse let kan undgås  :)

Sålænge 'LIMIT 1' ikke skader, er det ikke smart at udelade den - for så sætter jeg gerne 100 mod 1 på, den bliver glemt, når den af performance-mæssige årsager burde være der  ;o)
Avatar billede johan.o Nybegynder
10. februar 2006 - 18:39 #92
Vi er naturligvis enige om at hvis de input's der skal bruges til queryen er mulige at checke/escape til 100% sikre variabler er det unødvendigt, men der kan forekomme input der er meget svært at gøre dette ved og i disse tilfælde vil mit 'forbryderiske' eksempel :), kunne yde en bistand til sikkerheden.

Jeg syntes nu ikke man direkte kan overfører gåseøjne reglen på denne, de steder hvor du kan udelade gåseøjne, betyder det ikke noget at de er der, derfor kan man ligeså godt bruge dem. Vi er enige om at selvfølgelig bør man bruge LIMIT hvor man kan, men det betyder jo noget for den ressource der returneres fra din query om du bruger LIMIT eller ej, så det kræver vel lidt mere 'indblik' end blot _altid_.

Mvh. Johan
Avatar billede olebole Juniormester
10. februar 2006 - 18:44 #93
Undskyld, men jeg gik udfra, det var tydeligt, mit indlæg kun går på tilfælde, hvor man på forhånd ved, der skal findes ét match. Alt andet ville naturligvis være komplet tåbeligt!
Ved man, der kun skal findes ét match, er det en rigtig god regel, _altid_ at bruge 'LIMIT 1' ... og selvfølgelig checke inputtet grundigt  :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester

Seneste spørgsmål Seneste aktivitet
19 min siden Libre Office Impress Af Frank i Andre styresystemer
I dag 11:47 VB script Af Jenshentze i Word
I dag 11:21 Popup ved opstart Af mort1 i Windows
04/0918:50 Slet lokal konto Af ErikHg i Windows
04/0916:05 Ændre tal i en celle Af xvid i Excel