最近了解到二次注入,因而參考強網杯的"three hit",本地搭建了二次注入的環境來複現理解二次注入的造成php
搭建一個web環境,功能有註冊、登陸、登陸後顯示同年齡的人html
如下給出源碼,因爲只是爲了達到復現二次注入產生的效果來理解二次注入,故在功能和界面上代碼寫得比較粗糙,望見諒mysql
conn.php源碼:web
1 <?php 2 $con = mysqli_connect('localhost','root','root','test'); 3 if(!$con){ 4 die('Cound not connect:'.mysqli_connect_error()); 5 } 6 ?>
register.php源碼:sql
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>註冊</title> 5 <meta charset="utf-8"> 6 </head> 7 <body> 8 <h2 align="center">註冊</h2> 9 <form action="" method="POST"> 10 用戶名: <input type="text" name="name"><br> 11 年齡: <input type="text" name="age"><br> 12 密碼: <input type="text" name="pwd"><br> 13 <input type="submit" name="submit" value="提交"> 14 </form> 15 <?php 16 require('conn.php'); 17 if(isset($_POST['submit'])){ 18 $user = addslashes(@$_POST['name']); //addslashes過濾掉單引號等防注入 19 $age = addslashes(@$_POST['age']); 20 $pwd = addslashes(@$_POST['pwd']); 21 $sql = "INSERT INTO user(name,pwd,age) VALUES('".$user."','".$pwd."','".$age."')"; 22 if($res = mysqli_query($con,$sql)){ 23 echo "註冊成功<br>用戶名:$user<br>年齡:$age<br><a href='login.php'>去登陸</a>"; 24 }else{ 25 echo "註冊失敗"; 26 } 27 } 28 ?> 29 </body> 30 </html>
login.php源碼:數據庫
1 <?php 2 session_start(); 3 ?> 4 5 <!DOCTYPE html> 6 <html> 7 <head> 8 <title>登陸</title> 9 <meta charset="utf-8"> 10 </head> 11 <body> 12 <h2 align="center">登陸</h2> 13 <form action="" method="POST"> 14 用戶名: <input type="text" name="name"><br> 15 密碼: <input type="text" name="pwd"><br> 16 <input type="submit" name="submit" value="登陸"> 17 </form> 18 <h2>已註冊用戶:</h2><hr> 19 <?php 20 require("conn.php"); 21 $sql = "SELECT * FROM user"; 22 // 列出已註冊用戶 23 if($res = mysqli_query($con,$sql)){ 24 while($row = mysqli_fetch_assoc($res)){ 25 echo "用戶名:".$row['name']."<br>年齡:".$row['age']."<br>"; 26 } 27 } 28 ?> 29 <hr> 30 <?php 31 if(isset($_POST['submit'])){ 32 $name = @$_POST['name']; 33 $pwd = @$_POST['pwd']; 34 $sql = "SELECT * FROM user WHERE name='".$name."' and pwd='".$pwd."'"; 35 // 登陸 36 if($res = mysqli_query($con,$sql)){ 37 if(mysqli_num_rows($res)>0){ 38 $_SESSION['user'] = $name; 39 header("Refresh:0;url=index.php"); 40 }else{ 41 echo '登陸失敗'; 42 } 43 } 44 } 45 ?> 46 </body> 47 </html>
index.php源碼:服務器
1 <?php 2 session_start(); 3 if(!isset($_SESSION['user'])){ 4 header("Refresh:0;url=login.php"); 5 } 6 ?> 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <title>首頁</title> 11 <meta charset="utf-8"> 12 </head> 13 <body> 14 <?php 15 require('conn.php'); 16 //顯示當前用戶信息 17 $sql = "SELECT * FROM user WHERE name='".@$_SESSION['user']."'"; 18 if($res = mysqli_query($con,$sql)){ 19 while($row = mysqli_fetch_assoc($res)){ 20 $current_name = $row['name']; 21 $current_age = $row['age']; 22 echo '當前用戶:'.$current_name.'<br>年齡:'.$current_age; 23 } 24 } 25 echo "<br><br>"; 26 //顯示同齡用戶 27 $sql = "SELECT * FROM user WHERE age='".$current_age."' LIMIT 1";// $current_age從數據庫取出未通過濾直接拼接SQL語句,從而產生二次注入 28 if($res = mysqli_query($con,$sql)){ 29 while($row = mysqli_fetch_assoc($res)){ 30 echo '與'.$current_name.'<br>同年齡爲'.$current_age.'的有<br>'.$row['name']."<br>"; 31 } 32 } 33 34 echo "<br><br><a href='register.php'>去註冊</a>" 35 ?> 36 </body> 37 </html>
先註冊一個用戶test1,年齡爲1session
登陸後,能夠看到正常的效果fetch
接下來,註冊一個用戶user1,年齡爲1' and 1=2 #ui
這裏能夠看到,單引號前是被加了\的,產生不了注入
接着在login.php能夠看到,從數據庫取出的年齡是有單引號而且最後有個#註釋符的,是被污染的危險數據
登陸以後,能夠看到,本來該顯示同年齡的人的地方並無顯示,說明報錯了,and 1=2被拼接進了SQL語句
接下來就是常規的SQL注入了
接着註冊年齡爲【1' order by 1 #】...【1' order by 4#】、【1' union select 1,2,3#】、【1' union select user(),2,3#】...
【1' order by 1#】
【1' order by 4#】
【1' union select 1,2,3#】
【1' union select user(),2,3#】
二次注入能夠理解爲先將惡意數據插入到數據庫,以後服務器從數據庫取出惡意數據,未通過濾就直接拼接SQL語句進行查詢而致使的漏洞
由於精心構造的惡意數據在中間折轉了一次,故名爲二次注入