이 악용 된 사소한 조작의 몇 가지 (인 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>
은 $ Vorname 같은 시도! = ''&& $ Passwort가! = ''&& $ Nachname가! = '' –
그래서 당신이 악용 양식을 구축하고자이 있다는 것입니다 맞지만 실패하지 않는가? – RamRaider
$ count = mysqli_num_rows ($ query2); ... 그게 정확한지 모르겠다. – halojoy