Hallo,

Ik heb een paar dagen geleden een HTTPRequest gemaakt met jQuery, Ajax en PHP die de data dmv een $_POST meegeeft, dan data ophaalt uit een database en daarmee de content opnieuw inlaadt.

Een vriend van mij heeft gezegt dat deze manier heel makkelijk te hacken is, maar voor dat ik kon vragen waarom ging hij alweer offline.

Kan iemand van jullie mij misschien uitleggen waarom deze methode onveilig is?

Alvast bedankt.
-Richard

Dit is mijn code:

//File: contentswitch.js
$(document).ready(function() {
	$("#menu ul li").click(function() {
		var Title = $(this).attr("title");
		$('#content').fadeOut();
		
		$.post("contentswitch.php", { page: Title }, function(data) {
			$('#content').html(data);
		});
	});
});

//File: contentswitch.php
<?php
	if(isset($_POST['page'])) {
		include 'database.php';
		include 'functions/convertdate.php';
		include 'functions/getcontent.php';
		echo getContent($_POST['page']);
	}
//getContent is een functie die de content uit mijn database haalt,
//vandaar include 'database.php';
?>
Los van dat ik denk dat er beter oplossingen zijn voor wat je wilt bereiken, is het wel belangrijk dat je inkomende data van $_POST, $_FILE, $_GET etc. eerst controlleerd of het wel de data is die jij verwacht.
mysql_real_escape_string escape \x00, \n, \r, \, ', " en\x1a.
Als je bijvoorbeeld dit stuk code hebt:
mysql_query("SELECT * FROM pages WHERE page_title = '".$_POST['page']."'");
Dan zou ik in $_POST['page'] kunnen veranderen in a' OR '1
als ik dat doe wordt de query naar de DB dus
mysql_query("SELECT * FROM pages WHERE page_title = 'a' OR '1'"); en 1 return altijd alles van de SELECT.
Als je dus mysql_real_escape_string gebruikt dan werkt dit niet want dan wordt de query naar de DB
mysql_query("SELECT * FROM pages WHERE page_title = 'a\' OR \'1'");

Ik zou dit trouwens in je functie getContent doen, dus bijvoorbeeld:
<?php
function getContent($_title){
$title = mysql_real_escape_string($_title);
mysql_query("SELECT content FROM pages WHERE title = '.$title.'");
//return pagina
}
?>

Ik heb een functie geschreven om dit een beetje te counteren.


<?php
	include "database.php";
	function filter_query($term) {
		if(!isset($term) || empty($term)) {
			$output = "The parameter must be a valid query term.";
		}
		
		else {
			$filter = array('/\'/', '/\"/', '/\%/', '/\_/', '/\,/', '/\-/');
			
			for($I = 0; $I < count($filter); $I++) {
				if(preg_match($filter[$I], $term)) {
					$output .= "contains ".$filter[$I]."<br />";
				}
			}
			
			if(count($output) > 0) {
				$Out = "404 error";
			}
			
			else {
				$Out = $term;
			}
		}
		return $Out;
	}
?>


Ik heb er ook een mysql_real_escape_string(); aan gehangen in de httprequest.
Ik zou als ik jou was gewoon mysql_real_escape_string(), 1 is dat sneller en 2 makkelijker.
En de 404 komt pas als je de query naar de DB hebt gestuurd, dan check of er data is gekomen zo van de DB,ja laat dan de pagina zien, zo nee laat dan de 404 zien.
Zo krijg je altijd de correcte error te zien, bijvoorbeeld mijn data is valid, maar de pagina bestaat niet dan moet je ook 404 laten zien, maar ook als de data niet valid is, het is beter om dat op 1 plek te doen dan op verschillende plekken in je code
Dat is precies wat ik ook heb. Er wordt gekeken of de query een resultaat teruggeeft.

Als deze 1 is, wordt de pagina weergeven, als deze 0 is of groter dan 1, krijgt de gebruiker een 404 te zien.

Kijk zelf anders.
Mijn mobile website
Beste resultaat is op een mobiel apparaat te zien, iPod telt ook.
Oke, nou zo te zien werkt het allemaal.
Kleine tip: moet je echt de pagina in de DB hebben? want het vaak makkelijker om met template systemen te werken zoals bijvoorbeeld Smarty.
Paginas in DB is vaak geen oplossing voor lange periode.
Mja, ik dacht, ik doe het eens anders. ;)

Reageren