web安全原理简单,要的也就是积累,本篇阐述原理思路也用来记录每次遇到的小trick(嗯,就是未完待续,每次遇到就补充)~
二进制安全问题总是因为出现未定义的读写,而web安全问题同样是因为出现了未定义行为,这种未定义可能是基础设施漏洞,是编码逻辑漏洞,也可能是自己并未完全掌握环境特性,所以一般的安全策略都是使用最新的基础设施,深入了解所使用的每一个功能尽最大努力实现设计功能同样多的最终功能,这和最小权限原则相类似。
同样设计时也不要假设信任任何外部,于是也就有了参数过滤,参数过滤方法白名单显然是最小的过滤列表与规则能实现,能够实现上面提到的实现满足设计功能的最少功能的web程序,这里面少量需要关注的也就是过滤无逻辑漏洞,无知识性漏洞(如不完全了解正则表达式及其相关函数的特性)
我的安全观
这是朋友被面试问到的问题,当时自己也想了下,但是前几天翻道哥的白帽子发现更透彻,于是记录:
- 防御某种攻击而非某次攻击
- 安全问题的本质是信任问题,必须信任最基本的假设,但这种信任越少越好,因为它们一旦被攻破整个体系就再无安全性可言。
- 安全是个持续的过程,系统本身一定存在未发现的漏洞而且随着产品迭代升级又会引入新的漏洞
- 互联网安全的核心问题是数据安全
- 安全原则:默认安全,白名单,最下权限,纵深防御,数据代码分离,不可预测。
浏览器安全
同源策略
安全基石,作用在document上,浏览器脚本只能操作加载它的网页,即同源(域名,协议,端口,主机都相同),其中js不能读写非同源的内容。
XSS 过滤器
XSSAuditor
内容安全策略(CSP)
由web开发者声明浏览器遵守,它可以声明资源获取策略,即只能从哪些地址/方法获取指定类型的资源,通过白名单能够有效的减轻JS攻击的危害,当然配置不当(如使用unsafe-inline
时)或配合其他漏洞(如使用上传漏洞绕self
)仍然可能被利用。
HTML5 沙箱
可用于限定不解析js。
服务端攻击
它的攻击目标是服务器,因此危害相对更大!
服务端请求伪造(ssrf)
原理
当服务器IO操作的对象由用户指定,若过滤不严将造成此漏洞。即客户端将能控制服务端进行io请求,如网络连接,文件读取等。
作用
危害为 {服务端能做的事}-{客户端能做的事} 这个差集,如:
- 任意文件读取
- 利用对远端的服务请求,以服务器身份向外发送请求
可绕过地址访问限制,使用内网服务,实现主机服务扫描等
伪造的身份向其他非内网服务器发送请求 - 实现一些waf绕过
防御
严格的参数过滤。
外部实体注入(xxe)
原理
与xml注入放在一起,作为一种结构化文档,在服务端被解析时,若注入特殊数据,这些数据将被执行~
作用
- 任意文件读写
防御
参数过滤
任意文件上传
原理
用户能够上传未定义类型的文件。
危害
当能够向服务端写入任意文件时,写入的文件已经绕过了安全防线,处于某种特殊受信任状态,有如下三类:
- 被上传的文件作为配置文件被启用
- 被上传的文件作为恶意代码被执行(最常见的上传webshell,绕CSP的js)
- 被上传的文件借用用户对服务端的信任而钓鱼
防御
防御可以追踪文件上传的整个流:
- 客户端验证(不安全的)
- 服务端对文件类型的验证(后缀和MIME等,需要防解析漏洞)
- 服务端对文件内容进行清洗(如对图片进行重绘)
- 服务端对文件名进行清洗(如使用户无法控制文件名任何字段)
数据库注入(sqli)
原理
其原理就是用户输入的数据被当作SQL语句(代码)执行了,既然语句被执行,那么一定会产生相应的结果,理想的是直接返回想要查询的数据,最差也能通过语句执行的时间获取布尔数据。从原理处大致能猜到只要存在SQL注入漏洞,即SQL语句被执行一定能够通过此获取数据,但是若作为一个攻击者,我们的目的是要高效的获取数据,于是有了下面的方法:
- 联合注入:使用union语句合并多条语句的结果,后一条语句可控导致查询任意内容。
- 报错注入:构造运行时出错的嵌套的多条语句,第一条语句成功执行后运行时错误,返回第一条执行的结果
- 布尔盲注:无回显但是查询到结果与否将会返回不同的页面等。
- 时间盲注:无任何回显但是能通过一些需要较长时间才能执行完并返回的命令判断注入的语句是否成功执行,并通过组合其他语句与判断条件实现类似不二盲注的猜解。
- 带外注入:无输出时可使用布尔型注入,但是这效率较低(特别是基于时间的),带外注入利用dnslog等方式能一次向指定服务器发送一串完整的数据。
- 宽字符注入:算绕过技术了,绕过转义符
- 二次注入:第一次注入时被转义,当其被查询再插入时再次转义
- 堆叠注入:当注入点可堆叠查询时,将可能使用语句分隔符注入多条语句,该语句甚至可以为写语句。
作用
- 最直观的它能获取数据库数据
- 根据SQL数据库特性,更能实现一些其他功能:
- 文件读写
- 命令执行(可用危险存储过程,写入shell,udf插件)
- 服务扫描
防御
- 让用户的输入不被传入SQL语句中(如使用if语句根据用户输入赋值为相应的开发人员预设的值,但是这在大多数情况下是不现实的)
- 让用户的输入不会被解析为代码(如预编译语句绑定参数(注意预编译语句存在后端语言端实现与数据库端实现,不正确的使用依然存在风险),安全的存储过程)
- 对用户的输入进行过滤(如各种转义)
- 加强利用难度(如数据库最小权限,不返回错误等)
配置错误
原理
配置不当
危害
根据配置错误处,危害各种各样,如:
- 启用调试模式导致敏感数据泄露
- 启用危险的解析
- 目录列出,目录遍历
反序列化
原理
对象需要被传递或持久化保存时需要序列化,序列化的是对象的数据(即代码部分不独属于对象而是类),再使用时根据序列化里的数据找到当前空间里对应的类,创建新的实例并对其属性根据序列化数据进行赋值(差异根据实现而定),当用户能控制反序列化的输入时将能够对象的属性,一般来说当前影响的只是数据危害还不大,但是不同的语言会有一些特性,它们会在反序列化过程中被执行(例如PHP的__wakeup
魔术方法),若控制的数据影响到这些魔术方法时将可能导致任意代码执行。
危害
- 浪费服务器资源造成拒绝服务
- 在如Cookie,User等处反序列化造成认证绕过
- 在利用链满足的条件下造成拒绝服务
防御
一般的方法是参数清洗,黑白名单等策略:
- 使用lookahead技术(hook)重写关键方法,只允许指定的类被反序列化,例如java的
SerialKiller
实现很大程度的阻止了主流的利用连。 - 对输入进行过滤
- 禁止JVM执行外部命令Runtime.exec
- 进行权限控制,例如chroot或降权,将危害限定在一定范围(辅助措施,最后的防线)
- 使用运行时代码自保护(RASP)等技术缓解危害
原型链污染
原理
javascript是基于原型的语言,当对象不存在指定属性时将会根据原型链逐层向上查找,且对象的__proto__
属性为其上层原型,若能对对象的任意属性操作则能通过该属性更改其之上的”类”属性,而这种改动将会影响到所有该”类”属性之下的对象,即通过更改某对象的属性将能够影响到其他对象的属性。
危害
修改上层原型的数据,将可能影响所有其下层元素,当下层未定义该属性时,将会受到该攻击,这通常会导致授权绕过,在环境符合时也可能导致命令执行。
防御
控制对属性的赋值操作。
客户端攻击
它的攻击目标是客户端,也就是它攻击网站的使用者而非网站本身,危害相对较小但是不容忽视!
跨站脚本攻击(xss)
原理
客户端(浏览器)会执行网页返回的脚本(主要为JavaScript),若用户能够控制网页的返回内容,让其含恶意代码即可使客户端执行恶意代码,分为三类:
- 反射型XSS
- 存储型XSS
- DOM型XSS(不同于前面两种它会修改DOM结构以使js执行)
- 通用型XSS(由浏览器本身而非WEB站点产生)
它的利用一个是要让服务端返回目标代码,另一个是要让目标代码被执行(如作为事件响应或直接作为< script >)
危害
它的危害即让客户端执行任意代码,当然由于权限及js本身作用有限,它一般直接危害不到操作系统本身,具体的可以参考Beef提供的功能。
防御
通常的防御就是抓住利用的第二条,让注入的恶意代码不被客户端当作代码来执行,追踪参数路径:
- 在输入时清洗关键字
- 在输出时清洗关键字
- 特别提出,为防止cookie窃取应对其添加
httponly
属性
一般为了保证语义不变,不应该直接删除关键字,而是利用返回的内容应该作为数据被渲染到页面上这点来处理,例如:
- 当参数最终被作为html一部分应该转义为html实体,如
htmlspecialchars()
- 当参数最终被作为url一部分应该用url编码
- 当参数最终被作为js里的数据,应该对关键字做16进制编码并使用
""
包含。
客户端请求伪造(csrf)
原理
http作为无状态的协议需要使用其他方式保存状态与凭证,如使用cookie,它分为关闭浏览器就会失效的会话cookie和一定时期内一直有效的本地cookie,不管怎么说,当用户登陆网站后浏览器将处于被认证状态,使用它浏览网页将会直接使用其权限进行操作,若在用户不知情的情况下浏览器访问某个url即以存储的身份执行了某种敏感操作即为漏洞。
危害
使用户在不知情的情况下以其登陆过的身份执行敏感操作,如修改密码,向好友发信息等
防御
思路为让敏感操作只有用户知情的情况下才能操作:
- referer判断:某个操作只有通过某个特定页面跳转到,若不是来自特定页面此操作及非法
- 验证码:判断是用户真人操作(含验证密码)
- 随机token:和referer判断类似,某个操作只有通过某个特定页面才能操作,这个页面含有一个不可预测的token,那么非用户自身将无法得到这个token,硬编码的无正确token的请求将会失效
绕过
http分块传输
123
HTTP请求走私
123
拒绝服务
慢速攻击
原理
123
防护
123
缓存投毒Dos
原理
中间缓存服务器会根据一定的规则命中缓存,如取请求方法与请求路径即请求参数,不会关注所有请求头,因此会出现不同的请求头命中同一缓存的情况,但若是这里面部分请求被服务器解析返回错误页,且这些错误页被缓存,将导致同类请求被返回错误,即造成拒绝服务,有如下三类,他们思路都是中间服务器不真正执行请求操作,只把它认为合法的请求转发给后端,只要构造一个能通过中间服务器但使后端服务器报错的请求,且该请求里的缓存命中部分为常规数据即可:
- HTTP Header Oversize (HHO):利用中间服务器与后端服务器可接受的请求大小差异,若前者大于后者,则处于它们大小之间的请求将被视为正常请求转发给后端,后端认为超大则返回错误页。
- HTTP Meta Character (HMC):利用中间服务器不处理但后端服务器会处理的非法字符,后端认为非法则报错。
- HTTP Method Override (HMO):中间服务器使用原始http协议获取请求方法并转发给后端,后端可能根据业务与部署需要从请求头的其他字段读取真正的请求方法,当获取到错误的请求方法就会报错。
防护
- 禁用或有选择的禁用缓存错误页面。
- 使用WAF在中间层拦击异常数据。
其他
http
Host
有的时候需要改Host
此时必须在协议后写绝对地址才能成功:
1 | GET /links/ HTTP/1.1 |
参考
《白帽子讲web安全》