SQL手工注入基礎篇

0.前言

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

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

文中全部例題選自sqlilab,能夠先配置好一塊兒邊看邊操做。由於虛擬機炸了,因此我本身搭建了一個簡陋的平臺,sqlilab可自行進行搭建練習,在後面的博客也會寫一些關於sqlilab的wp。html

 

1.準備工做

在開始SQL注入以前,咱們首要須要瞭解SQL注入的原理,對於一個新安裝好的MySql數據庫,你至少會包含三個已經創建好的數據庫分別是user、infomation_schema、performance_schema以下圖所示mysql

 

而SQL注入要乾的,這些系統數據庫中存儲了MySql各個數據庫的屬性以及用戶信息,咱們要作的就是繞過過濾再來利用這些系統表進行查詢。sql

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

2.判斷注入類型

通常的對於SQL的查詢語句,有字符型和數值型查詢,而這二者的區別就是是否有單引號,這決定了咱們接下來應該如何構造SQL注入語句。ide

  判斷方法有以下幾種,函數

  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.查列數

  經過上述方法知道了注入類型以後,咱們就能夠進行下一步的操做了,在這裏我搭建了一個簡易的存在字符型查詢漏洞的頁面,你們能夠在本地搭建一下一邊學習一邊練習。fetch

SQL代碼以下:flex

 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注入知識,以及一些繞過技巧我將會在後面的進階篇詳解闡述。

相關文章
相關標籤/搜索