1. 程式人生 > >SQL手工注入基礎篇

SQL手工注入基礎篇

0.前言

本篇博文是對SQL手工注入進行基礎知識的講解,更多進階知識請參考進階篇(咕咕),文中有誤之處,還請各位師傅指出來。學習本篇之前,請先確保以及掌握了以下知識:

  • 基本的SQL語句
  • HTTP的GET、POST請求,URL編碼

文中所有例題選自sqlilab,可以先配置好一起邊看邊操作。因為虛擬機器炸了,所以我自己搭建了一個簡陋的平臺,sqlilab可自行進行搭建練習,在後面的部落格也會寫一些關於sqlilab的wp。

 

1.準備工作

在開始SQL注入之前,我們首要需要了解SQL注入的原理,對於一個新安裝好的MySql資料庫,你至少會包含三個已經建立好的資料庫分別是user、infomation_schema、performance_schema如下圖所示

 

而SQL注入要乾的,這些系統資料庫中儲存了MySql各個資料庫的屬性以及使用者資訊,我們要做的就是繞過過濾再來利用這些系統表進行查詢。

瞭解了這個之後我們還要了解一點就是PHP的GET方法和POST方法傳參的區別,如果使用GET方法,則會自動進行一次url解碼,例如傳入%23實際得到‘#’,而POST則會將資料原封不動的傳輸。下面我們開始進入正式的SQL注入階段。

2.判斷注入型別

一般的對於SQL的查詢語句,有字元型和數值型查詢,而這兩者的區別就是是否有單引號,這決定了我們接下來應該如何構造SQL注入語句。

  判斷方法有如下幾種,

  1. +-數值,如果是數值型的,你可以嘗試使用1+1,1+2,這樣的語句,例如  看網頁回顯是否正確。
  2. and 1=1,and 1=2,直接在後面新增“1 and 1=1”和“1 and 1=2”(前面有個空格)來進行查詢,若1=1回顯正確而1=2回顯錯誤則為數值型。
  3. 加‘#,在後面新增'#進行查詢,若回顯正確則表明為字元型。

除了上述幾種方法還可以用其他方法進行判斷,但原理都是構造SQL語句進行判斷。

 

3.查列數

  通過上述方法知道了注入型別之後,我們就可以進行下一步的操作了,在這裡我搭建了一個簡易的存在字元型查詢漏洞的頁面,大家可以在本地搭建一下一邊學習一邊練習。

SQL程式碼如下:

 1 /*
 2 Navicat MySQL Data Transfer
 3 
 4 Source Server         : Mysql
 5 Source Server Version : 50553
 6 Source Host           : localhost:3306
 7 Source Database       : test
 8 
 9 Target Server Type    : MYSQL
10 Target Server Version : 50553
11 File Encoding         : 65001
12 
13 Date: 2019-09-18 23:17:53
14 */
15 
16 SET FOREIGN_KEY_CHECKS=0;
17 
18 -- ----------------------------
19 -- Table structure for secret_table
20 -- ----------------------------
21 DROP TABLE IF EXISTS `secret_table`;
22 CREATE TABLE `secret_table` (
23   `fl4g` varchar(32) DEFAULT NULL
24 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
25 
26 -- ----------------------------
27 -- Records of secret_table
28 -- ----------------------------
29 INSERT INTO `secret_table` VALUES ('flag_is_here');
30 
31 -- ----------------------------
32 -- Table structure for student
33 -- ----------------------------
34 DROP TABLE IF EXISTS `student`;
35 CREATE TABLE `student` (
36   `id` int(11) NOT NULL AUTO_INCREMENT,
37   `name` varchar(255) DEFAULT NULL,
38   `class` varchar(255) DEFAULT NULL,
39   `age` int(11) DEFAULT NULL,
40   `note` varchar(16) DEFAULT '',
41   PRIMARY KEY (`id`)
42 ) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
43 
44 -- ----------------------------
45 -- Records of student
46 -- ----------------------------
47 INSERT INTO `student` VALUES ('1', 'zhangsan', 'nss', '18', '');
48 INSERT INTO `student` VALUES ('2', 'lisi', 'nss', '19', '');
49 INSERT INTO `student` VALUES ('3', 'wangwu', 'nss2', '20', '');
50 INSERT INTO `student` VALUES ('4', 'zhaoliu', 'nss2', '21', '');
51 INSERT INTO `student` VALUES ('5', 'sunqi', 'nss2', '22', '');
52 INSERT INTO `student` VALUES ('6', 'qianba', 'nss', '23', '');
53 INSERT INTO `student` VALUES ('7', 'liujiu', 'nss', '24', '');
View Code

PHP程式碼如下:

 1 <?php
 2     if (!empty($_POST['st'])) {
 3         $conn = mysqli_connect("localhost","root","root","test");
 4         $name = $_POST['name'];
 5         $sql = "select * from student where name='".$name."';";
 6         
 7         $result = mysqli_query($conn,$sql);
 8 
 9         echo "<table border='1'>
10         <tr>
11         <th>Id</th>
12         <th>Name</th>
13         <th>Class</th>
14         <th>Age</th>
15         <th>Note</th>
16         </tr>";
17         
18         while($row = mysqli_fetch_array($result)) {
19             echo "<tr>";
20             echo "<td>" . $row['id'] . "</td>";
21             echo "<td>" . $row['name'] . "</td>";
22             echo "<td>" . $row['class'] . "</td>";
23             echo "<td>" . $row['age'] . "</td>";
24             echo "<td>" . $row['note'] . "</td>";
25             echo "</tr>";
26         }
27         echo "</table>";
28 
29         mysqli_close($conn);
30     }
31 ?>
32 
33 <!doctype html>
34 <!-- flag in SQL -->
35 <form action="" method="POST">
36     <input type="text" placeholder="Input A Name" name="name" value="">
37     <button type="submit" name="st" value='1'>提交</button>
38 </form>
39 <div style="position: absolute;bottom:0;width:100%;display:flex;flex-direction:column;">
40     <hr >
41     <a style="align-self:center;" href="./source.txt">Source</a>
42 </div>
View Code

 

 通過上面的判斷我們知道是字元型注入,現在我們需要查出這個資料表的列數來為後面的聯合查詢做鋪墊。

當查詢語句最後為where xx 的時候我們使用order by num;

當查詢語句最後為limit xx的時候我們使用into @,@;

對於第一種order by num; num代表數值,語義就是以第幾列進行排序,當列不存在是就會報錯,我們就可以用二分的方法找出正確的列數。如下

 

 

 

 

 

 對於lisi' order by 6#,lisi是資料庫中的正常資料,單引號是為了閉合前面的select語句,#是mysql的單行註釋語句,提示報錯,換成5則正確,說明該表有5列。

對於limit xx的情況,我會在另一篇額外講解。

 

4.確定欄位位置

  當我們獲得表的列數之後,就可以通過聯合查詢獲得資料庫的資訊,但在此之前,我們還需要確定每個欄位顯示在網頁上的位置,方便檢視後面的資料。

  對於例題,我們知道列數為5之後,構造引數lisi' and 1=2 union select 1,2,3,4,5#即可知道每個欄位的位置

 

 

  完整的SQL語句就是select * from student where name = ‘lisi’ and 1=2 union select 1,2,3,4,5#';

   and 1=2是為了避免一些只顯示一行的頁面過濾掉後面的聯合查詢的資料,所以讓前面的查詢條件永遠為false,這裡你不加這個,但為了方便我們都加上這個。

  union就是合併操作,完整語義就是使用union合併兩個select的結果集,前者為空,後者結果為1,2,3,4,5,所以就會把這些結果合併然後顯示到對應的欄位。

 

5.獲取資料庫資訊

  當列數和欄位位置都知道後,我們就可以通過進一步的查詢來獲取資料庫資訊了,下面提供一些常用的資料庫函式。

  database():檢視當前資料庫名稱
  version():檢視資料庫版本資訊
  user():返回當前資料庫連線的使用者
  char():將ASCII碼轉化成字元,用於分隔每個欄位的內容

   使用方法就是將函式放在列的位置,例如提交lisi' and 1=2 union select 1,user(),database(),4,5#,結果如下:

  

 

  同樣在最開始的時候我們提到了MySql的幾個系統表,我們也可以從這些系統表中獲取所有表名,列數,欄位名等資料。

  例如查詢所有表名,提交lisi' and 1=2 union select 1,2,3,4,TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='test,結果如下

  

 

  第五個位置也就是查詢INFORMATION_SCHEMA.TABLES表中資料庫為test的所有表名,MySql的表屬性會儲存在這個表中,因為後面還有一個單引號,所以這裡右邊就不要單引號了。

  這樣我們就查詢到了所有的表名,現在我們發現有個表叫做secret_table,猜測flag隱藏在其中,那麼我們再來獲取這個表所有的欄位名。

  提交lisi' and 1=2 union select 1,2,3,4,COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='secret_table。結果如下

  

 

  語義同上,這裡就不在做解釋了,現在我們可以看到這個表有一個叫fl4g的欄位,那flag就藏在這裡沒錯了。

  接下來要做的就簡單了,我們只需要提交lisi' and 1=2 union select 1,2,3,4,fl4g from secret_table#

  

 

   到此我們就找到了最終的flag。

 

6.總結

  SQL手工注入的基礎知識道馳就結束了,推薦看完了這篇再去學習SQLmap的知識,可以很快上手也可以瞭解其本質的東西,不推薦直接學習SQLmap成為指令碼小子。

  再梳理一遍上述知識,首先找到注入點,注入點一般是網頁的某個提供查詢的地方,然後確定是字元型還是數值型,當確定了注入型別之後,就是進行確定一些資料表的資訊,方便後面的盲注,最後在從這些注入點得到我們想要的資訊。

  對於CTF題目來說,一般不是讓你盲注,會將程式碼給你,這時候注入點肯定是會有諸多的過濾,這時候我們就不能直接執行上述語句了,我們就需要構造一些語句去繞過執行,但最終要達到的效果和上述內容是一致的。

  對於更多的SQL注入知識,以及一些繞過技巧我將會在後面的進階篇詳解闡述。

&n