Meer over veiligheid PHP en MySQL

Status
Niet open voor verdere reacties.

georgeboot

Gebruiker
Lid geworden
3 jan 2007
Berichten
70
Beste forumleden,

Ik maak geregeld website's, en ik heb eigenlijk nog nooit nagedacht over de veiligheid van PHP-sricpts en MySQL-database's. Natuurlijk ga ik er vanuit dat deze 'veilig genoeg' zullen zijn, maar ik zou graag weten hoe hackers toch binnen komen, en zo daar de les uit leren: wat kun je er tegen doen.

Zijn er hier misschien mensen die nog wat informatie hebben daarover? Ik kan begrijpen dat je niet zomaar een hack-manier gaat posten (ivm. eventueel misbruik), maar ik zou het toch leuk vinden om daar eens naar te kijken.

Iemand?

Alvast heel erg bedankt!
 
Dankje! Er staan inderdaad een hoop dingen in. Zijn er nog meer van zulke dingen?
Wat ik leuk zou vinden, is en hack-manier, en dan daar de oplossing voor gebruiken. Iemand die daar meer over heeft?
 
Heei,

Toen ik dit topic las.. dacht ik yes! Dat is nou precies iets waar ik wat over weet.. Ik zal je in het kort wat uitleggen over bepaalde dingen die je moet gebruiken om je script overzichtelijk/veilig endergelijke te maken. Dit zal ik doen aan de hand van een paar voorbeelden. Ik zal beginnen met overzichtelijk te programmeren, waarom? Omdat als je niet overzichtelijk programmeerd de beveiliging er wel eens bij in kan schieten. en het voordeel daarvan is dat iedereen makkelijk je code kan lezen en ook makkelijk kan debuggen als je met een fout zit waar je zelf niet uit komt

Oké lets go, (Ik zal steeds mezelf van vroeger laten zien)

Wat veel beginners doen is de code zo gauw mogelijk plaatsen en dan als het werkt vinden ze het best.. Maar als je niet iets wilt wijzigen of toevoegen is het met een onoverzichtelijke code al snel heel erg moeilijk om het stukje te vinden wat je nodig hebt.. (Vooral bij grote scripts)

Een voorbeeld van zo'n script (Klein formuliertje)

PHP:
if($_SERVER['REQUEST_METHOD'] == 'POST'){
if(!empty($_POST['naam'])){
if(!empty($_POST['verhaal'])){
echo "Gelukt!";
}else{
echo "U heeft geen verhaaltje opgegeven";
}
}else{
echo "U heeft geen naam in gevoerd";
}
}
HTML:
<form method="POST" action="">
<table>
<tr>
<td>Naam </td><td><input type="text" name="naam"></td>
</tr>
<tr>
<td>Verhaaltje </td><td><input type="text" name="verhaal"></td>
</tr>
</table>
</form>

Dit is natuurlijk zo onoverzichtelijk als het maar kan.. Als hier een fout in zit kan je het misschien nog wel vinden, (5 minuten?) Maar als je nu 1000 regels van zulk soort code hebt?

Beter is het om het zo te doen (Je hebt wel meer regels nodig maar het is echt beter voor jezelf)

HTML:
	<form method="POST" action="">
		<table>
			<tr>
				<td>Naam </td><td><input type="text" name="naam"></td>
			</tr>
			<tr>
				<td>Verhaaltje </td><td><input type="text" name="verhaal"></td>
			</tr>
		</table>
	</form>

En dan het PHP gedeelte zoiets..

PHP:
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
	if(!empty($_POST['naam']))
	{
		if(!empty($_POST['verhaal']))
		{
			echo 'Gelukt!';
		}
		else 
		{
			echo 'U heeft geen verhaaltje ingevoerd!';
		}
	}
	else 
	{
		echo 'U heeft geen naam ingevoerd!';
	}
}

Zoals je ziet is dit veel makkelijker te debuggen dan het andere scriptje hierboven..

Oké nu over de beveiliging.. Een website hacken kan op verschillende manieren.
Maar SQL injection wordt het meeste toegepast. Ik kan hier best een hele tutorial van maken maar die zijn er al zat daarom verwijs ik je naar de volgende (nederlandse) tutorial

http://www.phphulp.nl/php/tutorials/3/444/1007/

Als je die gelezen hebt.. Zal ik een paar dingen op een rijtje zetten. Om je query te beveiligen gebruik je de volgende attributen om het egt veilig te maken

- mysql_real_escape_string();
- is_nummeric
- intval

een voorbeeld query dan maar even..

PHP:
$query insert = mysql_query("INSERT INTO tabelnaam (naam, verhaaltje) VALUES ('".mysql_real_escape_string($_POST['naam'])."', '".mysql_real_escape_string($_POST['verhaal'])."' WHERE uitleg='".intval($_POST['uitleg'])."')");

Snap je het? Zonee vragen mag altijd:)
 
intval() en is_numeric() heb je nooit nodig eigenlijk. Voor het checken van een nummer gebruik je ctype_digit(). Daarnaast zou ik gewoon altijd mysql_real_escape_string() gebruiken, en elders valideren of iets überhaupt een getal is (indien van toepassing) met ctype_digit().

En trouwens, empty() is ook niet echt handig. Laat dingen door die je niet door wilt laten, zoals whitespaces en tabs. Gebruik in plaats daarvan dit:

PHP:
if(trim($_POST['x']) == ''){

  // leeg

}

Dan weet je zeker dat het leeg/gevuld is.
 
Laatst bewerkt:
Oké, bedankt voor deze uitleg!

Ik heb het eens even geprobeerd op een zelfgemaakt schript, en inderdaad... Het trieste geval is dat ik mijn eigen database nu leeg heb. Backup terugzetten dan maar:p, EN beveiliging aanpassen natuurlijk.

Zijn er verder nog andere manieren om een website binnen te komen? Je kunt dus een invoerveld invullen met een 'aanvullende' SQL-query, maar als je dit beveiligd kun je daar dus niet meer me binnen komen.
Weten jullie dan nog andere manieren?

Ik heb nu mijn script aangepast, dus de genoemde injecties zullen mij niet meer overkomen (hoop ik...)


Alvast bedankt voor nieuwe uitleg;)
 
laat eens een stukje code van je zien dan?

Via cmhod kunnen ze ook binnen komen:) Dus de rechten van een map vervormen.. Of met sessions gaan klooien.
 
Mijn (nog niet aangepaste) code voor het beveiligen van pagina's is:
PHP:
<?php

  /*
  Log-in en beveiligings module BoBe 

  
  */
  
  session_start();
  require_once("connection.php"); // include het bestand met database gegevens: $host $user $pass en $data
  
  if (isset($_SESSION["ingelogd"])) {
  // Gebruiker is al ingelogd, dus gegevens uit de sessie worden in variabelen gezet
  
    $gebruikersnaam = $_SESSION["gebruikersnaam"];
    $account_id     = $_SESSION["account_id"];
  }
  
  elseif ((isset($_POST["gn"])) AND (isset($_POST["ww"]))) {
  // Gebruiker heeft zojuist ingelogd, dus gebruikersnaam en wachtwoord moeten gecontroleerd worden
  
    $username = $_POST["gn"];
    $username = strip_tags($username);
    $password = $_POST["ww"];
    $password = sha1($password);
    
    $sql = "SELECT toegang, username, password, id, auth FROM accounts WHERE username = '$username' ";
    
    // Ophalen gebruikersnaam, wachtwoord en accountID
    $verbinding = mysql_connect($host,$user,$pass) or die (mysql_error());
    mysql_select_db($data) or die (mysql_error());
    
    $resultaat = mysql_query($sql) or die (mysql_error());
    mysql_close($verbinding);
    
    if (mysql_num_rows($resultaat) == 1) {
      $record = mysql_fetch_assoc($resultaat);
      
      mysql_free_result($resultaat);
      
      if (($record["username"] != $username) OR ($record["password"] != $password)) {
        // Inloggegevens komen niet overeen: geen toegang
        inloggen();
        
      } elseif ($record["toegang"] == 1) {
        // Login oke
        $gebruikersnaam = $username;
        $account_id     = $record["id"];
		$authorisatie	= $record["auth"];

        $_SESSION["gebruikersnaam"] = $gebruikersnaam;
        $_SESSION["account_id"]     = $account_id;
        $_SESSION["ingelogd"]       = 1;
		$_SESSION["authorisatie"]	= $authorisatie;
      }
      
    } else {
      // Gebruikersnaam bestaat
      inloggen();
      
      mysql_free_result($resultaat);
    }
    
  } else {
    // Gebruiker heeft nog niet ingelogd: geen toegang
    inloggen(); 
  }
    
  function inloggen() {
  
    include("login.php");
    exit;
    
  }

?>


De code van mijn login-pagina is:
HTML:
<form name="inloggen" action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post">
	<table width="200" border="0">
	  	<tr>
	   		<td>Gebruikersnaam:</td>
	    	<td><input type="text" name="gn" onChange="javascript:this.value=this.value.toLowerCase();" /></td>
      	</tr>
	  	<tr>
	    	<td>Wachtwoord</td>
	   		<td><input type="password" name="ww" /></td>
      	</tr>
	  	<tr>
	    	<td>&nbsp;</td>
	    	<td><input type="submit" value="Inloggen" /></td>
      	</tr>
  	</table>
</form>

Ik include dus op iedere pagina de security.php.

Voor welke manieren van hacking is dit script vatbaar?
 
Laatst bewerkt:
Heei,

Begrijp je wat ik nu bedoel met overzichtelijk programmeren? Het spijt me maar ik moet egt 3, 4 keer kijken voordat ik wat begin te snappen aan je script..

Maar idd je script is lek. sql injection is zeer goed mogelijk...:)

PHP:
$sql = "SELECT toegang, username, password, id, auth FROM accounts WHERE username = '$username' ";

We nemen hem onder de loop:)

als ik nou eens als username dit neem..

Pietje'

Dan wordt er in de query dit ingevoerd

PHP:
SELECT blablablab FROM accounts WHERE username = '     pietje'      '

Ik heb even spaties erbij gedaan zodat je het beter kan zien.. Maar je ziet dat dit een syntax error gaat opleveren.. en daarmee kan je weer dingen mee uitvoeren en zo toegang tot de database verschaffen. Voor meer info die tut die ik je gaf..

EDIT:

Rofl nu vergat ik de oplossing, hoe je het beter kan doen is dus zo

PHP:
$sql = "SELECT toegang, username, password, id, auth FROM accounts WHERE username = '".mysql_real_escape_string($username).'" ";

TIP. Geef je query's een duidelijke naam dit is handig voor een persoon die je code moet lezen:)

Verder vind ik je inlog script een beetje vaag.. Er zijn vele betere en makkelijkere te vinden..
 
Laatst bewerkt:
Niels,

Bedankt voor je reactie. Ik begrijp dat je het wat onoverzichtelijk vind, vind ik zelf namelijk ook...:p
Maar verder heb ik het script zelf gemaakt. Het werkt 'goed', dus vond ik het wel voldoende. Blijkbaar niet dus;)

Als ik als gebruikersnaam:
HTML:
pietje'
invul, en bij wachtwoord:
HTML:
pietje
dan gaat er niets fout... Geen error of wat. Toch is het script zo als het boven geschreven is... Ik zal wel wat fout doen:p


Hoe kun je verder beveiligen tegen CMHOD ? En hoe kun je dmv. sessions toegang krijgen? De grotere vraag daarna is dan natuurlijk: wat doe je ertegen.


Nogmaals bedankt voor de aandacht en de vele reacties!
 
Heb je een online voorbeeld?

Tegen chmod gewoon nooit mappen 777 geven.. (Full control) en tegen sessions sla nooit wachtwoorden in sessions op alleen id.. En gebruik om te controleren nooit sessie id maar controleer het eerst via de database:)
 
Waarschijnlijk staat de magic_quotes() functie aan, die automatisch dat soort dingen oppakt... maar het is niet verstandig daarop te vertrouwen want het is deprecated en zal dus niet lang meer ondersteunt worden.
 
Welke code? Ik heb op die site nog NIETS aangepast in het script. Het is dus de security.php die ik in een eerdere post laat zien...

Lukt het jullie om binnen te komen, en op welke manieren dan wel? Ikzelf komt met als gebruikersnaam:
Code:
jan'
niet binnen. Zelfs geen error...
Het kan dat die functie aan staat ja, maar dat zou ik verder niet weten. Ik zou zeggen probeer het scriptje even uit, en rapporteer alle mogelijke lekken even, dan kunnen andere mensen daar ook nog een hoop van leren!

George
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan