web安全
约 1978 个字 15 行代码 预计阅读时间 7 分钟
Web指所有基于 HTTP 或者其他超文本传输协议开发的应用,包含网页、App、API接口等
通过 HTTP等文本协议,在客户端和服务端之间进行数据交换。客户端需要将服务端传出的数据展示渲染出来,服务端需要将客户端传入的数据进行对应的处理
XSS
Cross-Site Scripting,跨站脚本攻击。浏览器中插入一段恶意的JavaScript脚本,从而窃取你的隐私信息或者仿冒你进行操作
攻击类型:反射型XSS、基于DOM的以及持久(存储)型XSS
对比
浏览器 → 后端 → 浏览器
</h3><script>alert('xss');</script><h3>
通过开头的</h3>和结尾的<h3>,将原本的<h3>标签进行闭合,中间通过<script>标签插入JS代码并执行,就完成了整个反射型XSS的流程
适合前后端一体化应用中,必须用户点击带有特定参数的链接才能引起
URL → 浏览器
和反射型类似,只不过不需要经过服务端,而是通过JS修改DOM
浏览器 → 后端 → 数据库 → 后端 → 浏览器
将恶意的JS脚本写入正常的服务端数据库中,只要用户使用业务功能,就会被注入JS脚本
存储用户的输入并对它们进行展示的地方,都可能出现持久型XSS。e.g. 搜索结果、评论
通过XSS,攻击者能做什么?
- 窃取Cookie:通过
document.cookie获得Cookie信息 - 未授权操作: 利用JS特性,直接代替用户在HTML进行各类操作
- 键盘记录和钓鱼:伪造登陆框
如何进行防护?(XSS防护的核心原则就是验证)
- 验证输入 或 验证输出
- 展示用户内容的时候去进行验证,而不是当用户输入的时候就去验证
- 验证过程,优先采用编码的方式来完成
- 检测和过滤:白名单规则
- CSP(内容安全策略): 在服务端返回的HTTP header 里面添加一个CSP选项
SQL注入
通过构造一些恶意的输入参数,在应用拼接SQL语句的时候,去篡改正常的SQL语意,从而执行黑客所控制的SQL查询功能
1. 修改where语句(通过" or ""=")
SELECT * FROM Users WHERE Username ="admin" AND Password ="123456"
SELECT * FROM Users WHERE Username ="" AND Password ="" or ""=""
(""=""的结果是 true,当有一个 or 是true,最终结果就一定是true)
2. 执行任意语句:利用分号将原本的SQL语句进行分割
INSERT INTO Users (Username, Password) VALUES("test","000000"); SELECT * FROM Users;
通过SQL注入,能做什么?
- 绕过验证
- 任意篡改数据
- 窃取数据(拖库)
SELECT * FROM Users WHERE UserId = 1 UNION SELECT * FROM Users
- 消耗资源: 利用while打造死循环操作
如何防止SQL注入?
- PreparedStatement:将SQL语句的解析和实际执行过程分开,解析:数据库驱动
String sql = "SELECT * FROM Users WHERE UserId = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, userId);
ResultSet results = statement.executeQuery();
- 使用存储过程
- 和上述类似,存储过程防注入是将解析SQL的过程,由数据库驱动转移到了数据库本身
- 验证输入:防护效果最弱
CSRF/SSRF
跨站请求伪造攻击(CSRF):黑客通过JS脚本窃取你保存在网页中的身份信息(Cookie中),通过仿冒你,让你的浏览器发起伪造的请求,最终执行黑客定义的操作
(黑客控制浏览器发起伪造攻击)
- 通过自动提交表单的形式来发起攻击,通过抓包分析出相关接口所需要的参数,从而构造对应的 form 表单 (CSRF 在传播和攻击成本上都低于 XSS)
防护办法1:CSRF Token
- CSRF Token每次用户正常访问页面时,服务端随机生成返回给浏览器。每一次接口调用,携带均不同。黑客无法提前猜测,即无法构造正确的表单
防护办法2:二次验证
- 已登录但仍需输入独立的支付密码(仅用户知道,黑客无法获取)
服务端请求伪造(SSRF):黑客控制服务端发起一个其定义的内网请求,从而获取到内网数据
服务器有代理请求的功能:用户输入URL(如某个图片资源),然后server会向这个URL发起请求,通过访问其他的服务端资源来完成正常的页面展示
- 利用这个代理发起请求的功能,黑客可以提交一个内网的地址,实现对内网任意服务的访问
- (即内网穿透:让外网的设备找到处于内网的设备)
- 黑客可以利用SSRF向内网发起任意的HTTP请求,后果:
- 内网探测
- 文件读取:选择不同的协议类型,读取server的文件内容e.g.
file://
内网探测举例
请求的地址: https://image.baidu.com/search/detail?objurl=http://s1.sinaimg.cn/picture.jpg
http://s1.sinaimg.cn/picture.jpg会返回图片,所以网页会正常展示
黑客构造一个恶意的请求地址:https://image.baidu.com/search/detail?objurl=127.0.0.1:3306
- 不断重复尝试不同的IP和端口号,一点一点探测出整个内网的结构
常见防护手段:
- 白名单限制:目标URL进行限制
- 协议和资源类型限制
- 请求端限制 :尽量使用POST,避免GET
权限提升:黑客不断获取新的身份,来扩大/提升自己的权限,不断扩大攻击影响,最终实现控制整个系统
- 水平提升:权限等级没变,但获得了新的数据和权限
- 垂直提升:获得更高级别的权限
黑客通过SSRF进入内网 → 利用.svn/.git文件的信息泄露,请求内网各种地址 → 服务器A → SQL注入 → 服务器B → SSH扫描 → 服务器C(内网服务器的ROOT权限)
权限持久化:黑客利用“后门”,即获取更高权限后,为进行保留,在应用中留下一个隐藏的进程,下次再进入通过此进程来连通
- 后门通过木马(Trojan)的形式出现
- 持久化的实现:定时任务、开机启动 或 伴随于系统的常驻进程来实现
如何防护权限提升和持久化?
- 最小权限原则:每个用户和进程只分配用到的权限
- IDS(Runtime Application Self-Protection, 入侵检测系统):通过分析正常用户和黑客在网络层或者主机层中的行为异同,来识别黑客的攻击
反序列化漏洞
序列化: 将对象(Object)转化成字符串或者字节流
反序列化:字符串/字节流 → Object
实现方式:
- Java中Serializable接口,可以把对象转化为二进制的字节流,把字节流再还原为对象
- 反序列化工具:Fastjson和Jackson
- XML或JSON协议可以把对象转化为带格式的文本,把文本再还原为对象
定义
数据 → 对象 需要根据数据内容调用特定方法
- 黑客:在数据中嵌入自定义的代码(如某个系统命令)
- 此时反序列过程会执行此代码,使黑客能够控制整个应用及服务器
防护:
- 认证和签名:对存储的数据进行签名,以此对调用来源进行身份校验
- 限制序列化和反序列化的类,只允许某些类可以被反序列化(白名单)
- RASP检测(Runtime Application Self-Protection, 实时程序自我保护):在关键函数的调用中,增加一道规则的检测
- 通过 hook 的方式,直接将整个应用都监控了起来(会有性能损耗)
Note
反序列化漏洞——存在于Fastjson、Jackson等知名的JSON解析库中
- 属于 插件漏洞(第三方的插件、依赖库、工具和框架)
0day(零日漏洞): 在插件发布修复漏洞的安全补丁之前,黑客就已经知道漏洞细节的漏洞
- 仅仅只有黑客知道 (甚至都可以在黑客间作为资产来交易)
利用自动化的插件管理工具,对公开的插件漏洞进行监控,及时更新补丁