Web安全漏洞挖掘入门:从HTTP协议到SQL注入、XSS与越权

Web安全是网络安全学习中非常重要的一个方向。很多初学者在学习漏洞时,容易陷入“记Payload、记工具、记命令”的误区,却忽略了漏洞产生的真正原因。
实际上,SQL注入、XSS、CSRF、SSRF、文件上传以及越权等漏洞虽然表现形式不同,但背后都有一个共同逻辑:不可信的数据进入了不应该进入的位置,或者用户拥有了不应该拥有的权限。
本文从HTTP请求开始,逐步分析常见Web安全问题,并结合Python、JavaScript等代码示例,帮助初学者建立比较系统的Web安全思维。
一、Web安全到底在研究什么?
Web安全简单来说,就是研究Web应用在开发、部署和运行过程中可能出现的安全问题,并通过安全测试和安全设计降低风险。
一个简单的网站,看起来只是:
浏览器
↓
输入网址
↓
打开网页
但真正的请求链路可能是:
浏览器
↓
DNS
↓
CDN
↓
WAF
↓
Web服务器
↓
应用程序
↓
数据库
↓
内部服务
任何一层出现配置错误或者代码问题,都可能影响整体安全。
因此,学习Web安全不能只盯着某一个漏洞。
更重要的是理解:
用户输入从哪里来?
↓
经过什么处理?
↓
最终去了哪里?
↓
谁有权限访问?
↓
系统有没有正确的安全边界?
二、为什么HTTP是Web安全的基础?
学习Web安全之前,最好先把HTTP弄明白。
例如一个普通GET请求:
GET /user?id=1001 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
Cookie: session=abcdef123456
这里至少需要理解:
- 请求方法
- URL
- 请求头
- Cookie
- 参数
POST请求则可能是:
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=test&password=123456
安全测试时,经常需要观察:
请求方法
URL
参数
Cookie
Header
状态码
响应长度
响应内容
响应时间
例如:
GET /search?keyword=hello HTTP/1.1
这里的:
keyword=hello
就是一个值得分析的输入点。
三、漏洞分析最重要的思想:数据流
理解漏洞最简单的方法,就是分析数据流。
可以把很多漏洞抽象成:
用户输入
↓
应用处理
↓
危险操作
例如:
SQL注入
用户输入
↓
SQL字符串拼接
↓
数据库
XSS
用户输入
↓
HTML输出
↓
浏览器解析
命令执行
用户输入
↓
Shell命令
↓
操作系统
路径遍历
用户输入
↓
文件路径
↓
文件系统
所以漏洞挖掘真正要寻找的是:
用户可控的数据,是否进入了危险的处理流程?
四、SQL注入是什么?
SQL注入是最经典的Web漏洞之一。
假设存在下面的代码:
username = request.form["username"]
sql = (
"SELECT * FROM users "
"WHERE username = '" + username + "'"
)
cursor.execute(sql)
问题在于:
用户输入
↓
字符串拼接
↓
SQL语句
↓
数据库执行
也就是说,用户输入直接影响了SQL语句的结构。
这就是SQL注入产生的根本原因。
五、SQL注入应该如何修复?
最常见的方法之一就是参数化查询。
例如:
username = request.form["username"]
cursor.execute(
"SELECT * FROM users WHERE username = ?",
(username,)
)
此时:
SQL结构
+
用户数据
被明确区分。
相比之下,下面这种方式不推荐:
sql = "SELECT * FROM users WHERE id=" + user_id
更安全的写法:
cursor.execute(
"SELECT * FROM users WHERE id = ?",
(user_id,)
)
因此在开发Web应用时:
尽量使用参数化查询,不要通过字符串拼接构造SQL。
六、哪些参数值得重点关注?
在经过授权的安全测试环境中,可以重点观察:
id
uid
user_id
username
keyword
search
page
sort
order
category
例如:
GET /product?id=1001 HTTP/1.1
此时可以进一步分析:
id
↓
后台如何处理?
↓
是否进入数据库?
↓
是否进行类型校验?
↓
是否使用参数化查询?
需要注意:
出现数据库报错
≠
一定存在SQL注入
没有数据库报错
≠
一定不存在SQL注入
现代应用经常会统一处理异常。
因此真正的漏洞判断应该综合:
源码
日志
响应内容
状态码
业务行为
七、XSS是什么?
XSS的全称是:
Cross-Site Scripting
中文一般叫做:
跨站脚本攻击。
它的核心问题是:
应用程序把不可信输入当成了HTML或者脚本内容。
例如:
const value = new URLSearchParams(
location.search
).get("keyword");
document.getElementById(
"result"
).innerHTML = value;
问题就在:
innerHTML
浏览器会按照HTML内容解析它。
如果只是单纯展示文本,更推荐:
const value = new URLSearchParams(
location.search
).get("keyword");
document.getElementById(
"result"
).textContent = value;
区别非常简单:
innerHTML
↓
按照HTML解析
textContent
↓
按照普通文本处理
八、XSS常见类型
1. 反射型XSS
数据流通常是:
用户输入
↓
服务器
↓
响应
↓
浏览器
常见场景:
搜索
错误提示
参数回显
跳转页面
2. 存储型XSS
数据会先保存:
用户输入
↓
数据库
↓
页面读取
↓
浏览器
常见位置:
评论
留言
昵称
个人签名
文章标题
这种问题的影响范围往往更值得关注。
3. DOM型XSS
漏洞发生在浏览器端:
const content = location.hash.substring(1);
document.querySelector(
"#output"
).innerHTML = content;
这类问题不一定需要服务器参与,因此前端代码安全也非常重要。
九、CSRF是什么?
CSRF:
Cross-Site Request Forgery
中文称为:
跨站请求伪造。
简单理解就是:
利用用户当前已经登录的身份,让浏览器执行一个用户没有主动发起的请求。
例如系统存在:
POST /change-email HTTP/1.1
email=test@example.com
如果服务端只依赖Cookie判断身份:
浏览器
↓
自动携带Cookie
↓
服务器
就需要考虑非预期请求的问题。
十、CSRF如何防御?
经典方案之一是:
CSRF Token。
例如:
import secrets
csrf_token = secrets.token_hex(32)
print(csrf_token)
页面:
<input
type="hidden"
name="csrf_token"
value="RANDOM_TOKEN">
服务器进行验证:
token = request.form["csrf_token"]
if token != session["csrf_token"]:
return "Invalid request", 403
除此之外,还可以结合:
SameSite Cookie
Origin检查
Referer检查
敏感操作二次认证
形成多层防护。
十一、文件上传为什么危险?
很多网站都有:
头像上传
图片上传
简历上传
附件上传
视频上传
错误示例:
filename = upload.filename
upload.save(
"/var/www/uploads/" + filename
)
这里至少存在几个问题:
文件名可信吗?
文件内容可信吗?
文件类型可信吗?
文件大小有限制吗?
上传目录是否允许执行?
因此不能只检查文件扩展名。
可以先建立白名单:
ALLOWED_EXTENSIONS = {
".jpg",
".jpeg",
".png",
".gif"
}
然后进行后缀检查:
from pathlib import Path
filename = Path(upload.filename)
if filename.suffix.lower() not in ALLOWED_EXTENSIONS:
raise ValueError(
"unsupported file type"
)
实际生产环境还应该增加:
MIME检测
文件头检测
文件内容检测
重新编码
随机文件名
大小限制
病毒扫描
存储隔离
十二、为什么上传目录不能直接执行脚本?
假设网站目录:
/var/www/html/
上传目录:
/var/www/html/uploads/
如果上传目录同时存在:
写入权限
+
脚本执行权限
那么一旦文件校验出现问题,影响可能进一步扩大。
更合理的结构:
/var/www/app/
├── src/
├── config/
└── static/
/data/uploads/
让上传内容进入独立数据目录。
安全原则就是:
用户可以上传文件,不代表服务器应该执行这个文件。
十三、命令执行漏洞为什么危险?
来看一个简单例子:
import os
host = request.args.get("host")
os.system(
"ping -c 1 " + host
)
程序本来的设计:
输入IP
↓
执行Ping
↓
返回结果
但是实际情况:
用户输入
↓
Shell命令
↓
操作系统
于是用户输入就进入了操作系统命令解释环境。
十四、如何降低命令执行风险?
可以使用参数数组:
import subprocess
host = request.args.get("host")
result = subprocess.run(
["ping", "-c", "1", host],
capture_output=True,
text=True,
timeout=5
)
print(result.stdout)
同时可以增加IP格式验证:
import ipaddress
try:
ipaddress.ip_address(host)
except ValueError:
raise ValueError("Invalid IP address")
进一步还可以增加:
命令白名单
超时
资源限制
低权限账户
日志审计
十五、越权漏洞为什么很容易被忽略?
很多安全测试只关注:
SQL注入
XSS
文件上传
命令执行
却容易忽略越权。
例如:
GET /api/order?id=1001 HTTP/1.1
当前用户:
user_id = 1001
能够查询自己的订单。
但是:
GET /api/order?id=1002 HTTP/1.1
如果也能返回数据,那么可能存在:
用户A
↓
访问
↓
用户B订单
这就是典型的对象级授权问题。
十六、越权漏洞如何修复?
错误代码:
order = get_order(order_id)
return order
更安全的逻辑:
order = get_order(order_id)
if order.user_id != current_user.id:
return "Forbidden", 403
return order
核心原则:
用户认证成功,不代表用户拥有所有资源访问权限。
十七、认证与授权有什么区别?
这是Web安全非常基础的概念。
Authentication:认证
回答:
你是谁?
例如:
用户名
密码
验证码
MFA
Token
Authorization:授权
回答:
你可以做什么?
例如:
普通用户
管理员
财务
审计员
开发人员
所以:
认证成功
≠
拥有全部权限
十八、SSRF是什么?
SSRF:
Server-Side Request Forgery
中文称:
服务端请求伪造。
常见业务场景:
用户输入URL
↓
服务器访问URL
↓
返回结果
例如:
import requests
url = request.args.get("url")
response = requests.get(
url,
timeout=5
)
return response.text
问题在于:
用户是否可以任意控制URL?
如果可以,就需要考虑服务器可能被诱导访问本不应该访问的内部资源。
因此生产环境应该进行:
URL解析
协议限制
IP校验
DNS校验
重定向控制
访问范围限制
十九、路径遍历是什么?
假设存在:
GET /download?file=manual.pdf
后台代码:
filename = request.args["file"]
path = "/data/files/" + filename
return send_file(path)
问题是:
filename
是否完全可信。
如果用户可以任意控制服务器读取路径,就可能出现文件访问范围突破。
一种安全思路是白名单:
FILES = {
"manual": "/data/files/manual.pdf",
"guide": "/data/files/guide.pdf"
}
key = request.args.get("name")
path = FILES.get(key)
if not path:
return "Not Found", 404
return send_file(path)
这样客户端只能访问程序明确允许的资源。
二十、API安全为什么越来越重要?
现在很多Web应用已经从传统网页变成:
前端
↓
API
↓
微服务
↓
数据库
例如:
POST /api/v1/user/update
Content-Type: application/json
{
"username": "test",
"email": "test@example.com"
}
测试API的时候,不仅要看参数,还要看:
认证
授权
对象ID
敏感字段
速率限制
返回数据
二十一、API中的敏感字段问题
例如客户端发送:
{
"username": "test",
"email": "test@example.com",
"role": "admin"
}
如果后端直接:
update_user(request.json)
就可能导致客户端控制本不应该修改的敏感字段。
更加合理的是字段白名单:
allowed_fields = {
"username",
"email"
}
data = {
key: value
for key, value in request.json.items()
if key in allowed_fields
}
这样可以减少:
批量赋值
敏感字段修改
权限字段覆盖
等风险。
二十二、Burp Suite在Web安全学习中的作用
Burp Suite是Web安全学习中非常常见的工具。
它最核心的功能不是“一键扫描”,而是:
拦截
修改
重放
分析
例如:
GET /user?id=1001 HTTP/1.1
Host: example.com
Cookie: session=xxxx
可以从请求中分析:
方法
URL
Cookie
Header
参数
再结合响应:
状态码
长度
内容
时间
判断应用行为是否发生变化。
因此:
Burp Suite更适合作为HTTP分析工具,而不是单纯的扫描器。
二十三、为什么不能完全依赖扫描器?
自动化扫描很适合:
资产发现
批量检测
快速验证
初步筛选
但很多业务逻辑问题很难自动判断。
例如:
优惠券
订单
退款
积分
支付
审批
权限
这些功能需要安全人员理解:
业务流程
身份关系
权限边界
数据关系
所以更加合理的方式是:
人工理解业务
↓
工具辅助分析
↓
自动化检测
↓
人工确认
↓
形成报告
二十四、如何建立自己的Web安全测试清单?
资产层
[ ] 域名
[ ] 子域名
[ ] IP
[ ] 开放端口
[ ] Web服务
[ ] API
功能层
[ ] 登录
[ ] 注册
[ ] 搜索
[ ] 用户资料
[ ] 文件上传
[ ] 文件下载
[ ] 密码修改
[ ] 管理后台
漏洞层
[ ] SQL注入
[ ] XSS
[ ] CSRF
[ ] SSRF
[ ] 文件上传
[ ] 路径遍历
[ ] 命令执行
[ ] 越权
认证授权层
[ ] Session
[ ] JWT
[ ] MFA
[ ] 权限控制
[ ] 水平越权
[ ] 垂直越权
二十五、Python如何帮助安全自动化?
安全工作中经常需要处理:
大量URL
大量接口
大量参数
大量日志
Python非常适合做自动化。
例如:
from urllib.parse import urlparse, parse_qs
url = (
"https://example.com/search"
"?id=1001&keyword=test&redirect=/home"
)
parsed = urlparse(url)
params = parse_qs(
parsed.query
)
for key, value in params.items():
print(
f"{key} -> {value}"
)
输出:
id -> ['1001']
keyword -> ['test']
redirect -> ['/home']
后续可以继续加入:
参数分类
风险标记
测试记录
报告生成
二十六、安全人员真正应该培养什么能力?
很多人认为网络安全就是:
会Nmap
会Burp
会Kali
会扫描
实际上远远不够。
真正重要的是:
理解协议
理解代码
理解数据库
理解系统
理解权限
理解业务
理解数据流
例如看到:
sql = "SELECT * FROM user WHERE id=" + user_id
能够第一时间想到:
用户输入
↓
字符串拼接
↓
SQL
再看到:
element.innerHTML = value
应该想到:
用户输入
↓
HTML
↓
浏览器解析
这就是漏洞思维。
二十七、推荐的Web安全学习路线
如果准备系统学习Web安全,可以按照:
网络基础
↓
TCP/IP
↓
HTTP/HTTPS
↓
Linux
↓
Python
↓
JavaScript
↓
SQL
↓
Web开发基础
↓
常见漏洞
↓
API安全
↓
源码审计
↓
安全自动化
其中最重要的几个基础:
HTTP
Linux
Python
JavaScript
SQL
最好真正理解,而不是只背命令。
二十八、建议使用靶场学习
学习漏洞时,建议优先选择:
DVWA
OWASP Juice Shop
WebGoat
bWAPP
例如使用Docker运行Juice Shop:
docker pull bkimminich/juice-shop
然后:
docker run -d \
--name juice-shop \
-p 3000:3000 \
bkimminich/juice-shop
查看:
docker ps
访问:
http://127.0.0.1:3000
这样可以在自己的隔离环境中学习:
漏洞原理
HTTP请求
代码缺陷
修复方法
二十九、从“漏洞”到“风险”
发现一个漏洞之后,不应该马上结束。
还需要继续分析:
谁可以触发?
需要什么权限?
影响什么数据?
会不会影响业务?
是否可以继续扩大影响?
例如:
漏洞:
越权
影响:
其他用户数据可以被读取
风险:
隐私泄露
业务风险
合规风险
一个成熟的安全报告不仅应该写:
存在漏洞
还应该写清楚:
漏洞原因
漏洞位置
影响范围
修复建议
三十、总结
Web安全看起来有很多漏洞:
SQL注入
XSS
CSRF
SSRF
文件上传
路径遍历
命令执行
越权
但很多漏洞最终都可以归纳成几个核心问题:
不可信输入
↓
不安全处理
↓
危险操作
↓
安全边界失效
因此学习Web安全时,与其记住几十种Payload,不如真正理解:
输入从哪里来?
数据去了哪里?
系统如何处理?
谁有权限?
哪里存在安全边界?
三十一、写给正在学习网络安全的人
刚开始学习Web安全时,很容易出现:
今天学SQL注入
明天学XSS
后天学Kali
再学Burp
最后发现:
每个都会一点,但是不会把知识串起来。
更合理的路线应该是:
网络
↓
系统
↓
编程
↓
Web
↓
漏洞
↓
靶场
↓
源码
↓
自动化
当你真正理解HTTP、Linux、Python、SQL和JavaScript以后,再去学习漏洞,会轻松很多。
因为很多“高级漏洞”最终还是建立在基础知识之上。
三十二、结语
Web安全真正值得学习的,并不是某一个固定Payload,而是一套稳定的分析方法:
找到输入点
↓
追踪数据流
↓
定位危险操作
↓
检查认证
↓
检查授权
↓
分析安全边界
↓
判断实际影响
↓
提出修复方案
SQL注入考验:
输入 + 数据库
XSS考验:
输入 + 输出 + 浏览器
越权考验:
身份 + 资源 + 权限
SSRF考验:
用户输入 + 服务器网络能力
命令执行考验:
用户输入 + 操作系统
所以,真正的Web安全能力,不是“会多少工具”,而是:
看到一个请求之后,能够快速判断数据去了哪里、谁可以访问、哪里存在安全边界。

这才是网络安全学习中最值得长期积累的能力
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐





所有评论(0)