白帽子讲Web安全读书笔记

网友投稿 508 2022-05-30

起初,研究计算机系统和网络的人,被称为"Hacker",“Hacker"在中国按照音译,被称为“黑客”

第一篇 ,世界安全观

Web安全筒史

起初,研究计算机系统和网络的人,被称为"Hacker",“Hacker"在中国按照音译,被称为“黑客”

对于现代计算机系统来说,在用户态的最高权限是root (administrator),也是黑客们最渴望能够获取的系统最高权限。不想拿到“root"”的黑客,不是好黑客。漏洞利用代码能够帮助黑客们达成这一目标。

黑客们使用的漏洞利用代码,被称为"exploit"。在黑客的世界里,有的黑客,精通计算机技术,能自己挖掘漏洞,并编写exploit;

只对攻击本身感兴趣,对计算机原理和各种编程技术的了解比较粗浅,因此只懂得编译别人的代码, 自己并没有动手能力,这种黑客被称为“SriptKids",即“·脚本小子”。

今天已经形成产业的计算机犯罪、网络犯罪中,造成主要破坏的,也是这些“脚本小子”。

中国黑客简史

笔者把中国黑客的发展分为了:启蒙时代、黄金时代、黑暗时代。

黑客技术的发展历程

从黑客技术发展的角度看,在早期,黑客攻击的目标以系统软件居多。

一方面,是由于这个时期的Web技术发展还远远不成熟;

另一方面,则是因为通过攻击系统软件,黑客们往往能够直接获取root权限。

这段时期,涌现出了非常多的经典漏洞以及"exploit"。比如著名的黑客组织TESO,就曾经编写过一个攻击SSH的exploit,并公然在exploit的banner中宣称曾经利用这个exploit入侵过cia.gov (美国中央情报局)。

2003年的冲击波蠕虫是一个里程碑式的事件,这个针对Windows操作系统RPC服务(运行在445端口)的蠕虫,在很短的时间内席卷了全球,造成了数百万台机器被感染,损失难以估量。在此次事件后,网络运营商们很坚决地在骨干网络上屏蔽了135、445等端口的连接请求。此次事件之后,整个互联网对于安全的重视达到了一个空前的高度。

Web安全的兴起

SQL注入的出现是Web安全史上的一个里程碑,它最早出现大概是在1999年,

黑客们发现通过SQL注入攻击,可以获取很多重要的、敏感的数据,甚至能够通过数据库获取系统访问权限,这种效果并不比直接攻击系统软件差。SQL注入漏洞至今仍然是Web安全领域中的一个重要组成部分。

xss (跨站脚本攻击)的出现则是Web安全史上的另一个里程碑。实际上, xss的出现时间和SQL注入差不多,但是真正引起人们重视则是在大概2003年以后。在经历了MySpace的xSs蠕虫事件后,安全界对xss的重视程度提高了很多, OWASP 2007 TOP 10威胁甚至把xss 排在榜首。

黑帽子,白帽子

白帽子,则是指那些精通安全技术,但是工作在反黑客领域的专家们;

黑帽子,则是指利用黑客技术造成破坏,甚至进行网络犯罪的群体。

返璞归真,揭秘安全的本质

通过一个安全检查(过滤、净化)的过程,可以梳理未知的人或物,使其变得可信任。

被划分出来的具有不同信任级别的区域,我们称为信任域,

划分两个不同信任域之间的边界,我们称为信任边界。

数据从高等级的信任域流向低等级的信任域,是不需要经过安全检查的;

数据从低等级的 信任域流向高等级的信任域,则需要经过信任边界的安全检查。

笔者认为,安全问题的本质是信任的问题。

一切的安全方案设计的基础,都是建立在信任关系上的。我们必须相信一些东西,必须有一些最基本的假设,安全方案才能得以建立;如果我们否定一切,安全方案就会如无源之水,无根之木,无法设计,也无法完成。

举例来说,假设我们有份很重要的文件要好好保管起来,能想到的一个方案是把文件“锁".到抽屉里。这里就包含了几个基本的假设,首先,制作这把锁的工匠是可以信任的,他没有私自藏一把钥匙:其次,制作抽屉的工匠没有私自给抽屉装一个后门;最后,钥匙还必须要保管在一个不会出问题的地方,或者交给值得信任的人保管。反之,如果我们一切都不信任,那么也就不可能认为文件放在抽屉里是安全的。当制锁的工匠无法打开锁时,文件才是安全的,这是我们的假设前提之一。但是如果那个工匠私自藏有一把钥匙,那么这份文件也就不再安全了。这个威胁存在的可能性,依赖于对工匠的信任程度。如果我们信任工匠,那么在这个假设前提下,我们就能确定文件的安全性。这种对条件的信任程度,是确定对象是否安全的基础。

在现实生活中,我们很少设想最极端的前提条件,因为极端的条件往往意味者小概率以及高成本,因此在成本有限的情况下,我们往往会根据成本来设计安全方案,并将一些可能性较大的条件作为决策的主要依据。

因此,把握住信任条件的度,使其恰到好处,正是设计安全方案的难点所在,也是安全这门学问的艺术魅力所在。

破除迷信,没有银弹

安全是一个持续的过程。

安全三要素

安全三要素是安全的基本组成元素,分别是机密性(Confidentiality)、完整性(Integrity),可用性(Availability).

机密性要求保护数据内容不能泄露,加密是实现机密性要求的常见手段。

完整性则要求保护数据内容是完整、没有被篡改的。常见的保证一致性的技术手段是数字,签名。

可用性要求保护资源是“随需而得"。

假设一个停车场里有100个车位,在正常情况下,可以停100辆车。但是在某一天,有个坏人搬了100块大石头,把每个车位都占用了,停车场无法再提供正常服务。在安全领域中这种攻击叫做拒绝服务攻击,简称Dos (Denial of Service)。拒绝服务攻击破坏的是安全的可用性。

如何实施安全评估

资产等级划分

资产等级划分是所有工作的基础,这项工作能够帮助我们明确目标是什么,要保护什么。

在互联网的基础设施已经比较完善的今天,互联网的核心其实是由用户数据驱动的-用户产生业务,业务产生数据。

互联网公司除了拥有一些固定资产,如服务器等死物外,最核心的价值就是其拥有的用户数据,

所以互联网安全的核心问题,是数据安全的问题。

对互联网公司拥有的资产进行等级划分,就是对数据做等级划分。

当完成资产等级划分后,对要保护的目标已经有了一个大概的了解,接下来就是要·划分信任域和信任边界了。

通常我们用一种最简单的划分方式,就是从网络逻辑上来划分。比如最重要的数据放在数据库里,那么把数据库的服务器圈起来; Web应用可以从数据库中读/写数据并对外提供服务,那再把Web服务器圈起来;最外面是不可信任的Internet.

威胁分析

在安全领域里,我们把可能造成危害的来源称为威胁(Threat),而把可能会出现的损失称为风险(Risk),

风险一定是和损失取系在一起的

接下来要提到的“威胁建模”和“风险分析”两个阶段,这两个阶段的联系是很紧密的。什么是威胁分析?

威胁分析就是把所有的威胁都找出来。怎么找?一般是采用头脑风暴法。当然,也有一些比较科学的方法,比如使用一个模型,帮助我们去想,在哪些方面有可能会存在威胁,这个过程能够避免遗漏,这就是威胁建模。

介绍一种威胁建模的方法,它最早是由微软提出的,叫做STRIDE模型。STRIDE是6个单词的首字母缩写,我们在分析威胁时,可以从以下6个方面去考虑。

在进行威胁分析时,要尽可能地不遗漏威胁,头脑风暴的过程可以确定攻击面(AttackSurface)在维护系统安全时,最让安全工程师沮丧的事情就是花费很多的时间与精力实施安全方案,但是攻击者却利用了事先完全没有想到的漏洞(漏洞的定义:系统中可能被威胁利用以造成危害的地方。)完成入侵。这往往就是由于在确定攻击面时,想的不够全面而导致的。

风险分析

风险由以下因素组成:

Risk = Probability* Damage Potential

影响风险高低的因素,除了造成损失的大小外,还需要考虑到发生的可能性。

介绍一个DREAD模型,它也是由微软提出的。DREAD也是几个单词的首字母缩写,它指导我们应该从哪些方面去判断一个威胁的风险程度。

设计安全方案

最终,一个优秀的安全方案应该具备以下特点:

能够有效解决问题;

用户体验好;

高性能;

低耦合;

易于扩展与升级。

白帽子兵法

Secure By Default原则

黑名单、白名单

黑名单、白名单比如,在制定防火墙的网络访问控制策略时,

如果网站只提供Web服务,那么正确的做法是只允许网站服务器的80和443端口对外提供服务,屏蔽除此之外的其他端口。这是一种“白·名单”的做法;

如果使用“黑名单”,则可能会出现问题。假设黑名单的策略是:不允许SSH端口对Internet开放,那么就要审计SSH的默认端口: 22端口是否开放了Internet。

但在实际工作过程中,经常会发现有的工程师为了偷懒或图方便,私自改变了SSH的监听端口,比加把SSH的端口从22改到了2222,从而绕过了安全策略。

在网站的生产环境服务器上,应该限制随意安装软件,而需要制定统一的软件版本规范。 这个规范的制定,也可以选择白名单的思想来实现。按照白名单的思想,应该根据业务需求,列出一个允许使用的软件以及软件版本的清单,在此清单外的软件则禁止使用。如果允许工程师在服务器上随意安装软件的话,则可能会因为安全部门不知道、不熟悉这些软件而导致一些漏洞,从而扩大攻击面。

最小权限原则最小权限原则要求系统只授予主体必要的权限,而不要过度授权,这样能有效地减少系统、网络、应用、数据库出错的机会。

比如在Linux系统中,一种良好的操作习惯是使用普通账户登录,在执行需要root权限的操作时,再通过sudo命令完成。这样能最大化地降低一些误操作导致的风险;同时普通账户被盗用后,与root帐户被盗用所导致的后果是完全不同的。

纵深防御原则

纵深防御包含两层含义:,

要在各个不同层面、不同方面实施安全方案,避免出现疏漏,不同安全方案之间需要相互配合,构成一个整体;

要在正确的地方做正确的事情,即:在解决根本问题的地方实施针对性的安全方案。

某矿泉水品牌曾经在广告中展示了一滴水的生产过程:经过十多层的安全过滤,去除有害物质,最终得到一滴饮用水。这种多层过滤的体系,就是一种纵深防御,是有立体层次感的安全方案。

纵深防御并不是同一个安全方案要做两遍或多遍,而是要从不同的层面、不同的角度对系· 统做出整体的解决方案。

在常见的入侵案例中,大多数是利用web应用的漏洞,攻击者先获得一个低权限的webshell然后通过低权限的webshell上传更多的文件,并尝试执行更高权限的系统命令,尝试在服务器上提升权限为root;接下来攻击者再进一步尝试渗透内网,比如数据库服务器所在的网段。

常有必要将风险分散到系统的各个层面。就入侵的防御来说,我们需要考虑的可能有Web应用安全、OS系统安全、数据库安全、网络环境安全等。在这些不同层面设计的安全方案,将共同组成整个防御体系,这也就是纵深防御的思想。

纵深防御的第二层含义,是要在正确的地方做正确的事情。如何理解呢?它要求我们深入理解威胁的本质,从而做出正确的应对措施。

对于一个复杂的系统,纵深防御是构建安全体系的必要选择。

数据与代码分离原则

实际上,缓冲区溢出,也可以认为是程序违背了这一原则的后果-程序在栈或者堆中,将用户数据当做代码执行,混淆了代码与数据的边界,从而导致安全问题的发生。

在Web安全中,由·“注入”·引起的问题比比皆是,如XSS. SQL Injection, CRLF Injection.. X-Path Injection等。此类问题均可以根据“数据与代码分离原则”设计出真正安全的解决方案,因为这个原则抓住了漏洞形成的本质原因。以XSS为例,它产生的原因是HTML Injection或JavaScript Injection,

不可预测性原则

微软的Windows系统用户多年来深受缓冲区溢出之苦,因此微软在Windows的新版本中增加了许多对抗缓冲区溢出等内存攻击的功能。微软无法要求运行在系统中的软件没有漏洞,因此它采取的做法是让漏洞的攻击方法失效。比如,使用DEP来保证堆栈不可执行,使用ASLR让进程的栈基址随机变化,从而使攻击程序无法准确地猜测到内存地址,大大提高了攻击的门,槛。经过实践检验,证明微软的这个思路确实是有效的–即使无法修复code,但是如果能够使得攻击的方法无效,那么也可以算是成功的防御。微软使用的ASLR技术,在较新版本的Linux内核中也支持。在ASLR的控制下,一个程序每次启动时,其进程的栈基址都不相同,具有一定的随机性,对于攻击者来说,这就是“不可预测性"。

不可预测性原则,可以巧妙地用在一些敏感数据上。比如在CSRF的防御技术中,通常会使用一个token来进行有效防御。这个token能成功防御CSRF,就是因为攻击者在实施CSRF攻击的过程中,是无法提前预知这个token值的,因此要求token足够复杂时,不能被攻击者·猜测到。

不可预测性的实现往往需要用到加密算法、随机数算法、哈希算法,好好使用这条原则,在设计安全方案时往往会事半功倍。

第二篇 客户端脚本安全

第2章浏览器安全

同源策略

同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也最基本的安全功能

如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略的基础之上的,```浏览器只是针对同源策略的一种实现`。对于客户端Web安全的学习与研究来说,深入理解同源策略是非常重要的,也是后续学习的基础。

很多时候浏览器实现的同源策略是隐性、透明的,很多因为同源策略导致的问题并没有明显的出错提示,如果不熟悉同源策略,则可能一直都会想不明白问题的原因。

浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。

这一策略极其重要,试想如果没有同源策略,可能a.com的一段JavaScript脚本,在b.com未曾加载此脚本时,也可以随意涂改b.com的页面(在浏览器的显示中)。为了不让浏览器的页面行为发生混乱,浏览器提出了"Origin" (源)这一概念,来自不同Origin的对象无法互相干扰。对于JavaScript来说,以下情况被认为是同源与不同源的。!

由上表可以看出,影响“源”的因素有: host (域名或IP地址,如果是IP地址则看做一个根域名)、子域名、端口、协议。

需要注意的是,对于当前页面来说,页面内存放JavaScript文件的域并不重要,重要的是.加载JavasScript页面所在的域是什么。换言之, a.com通过以下代码:

加载了b.com上的b.js,但是b.js是运行在a.com页面中的,因此对于当前打开的页面(a.com页面)来说, b.js的Origin就应该是a.com而非b.com。在浏览器中,

但XMLHttpRequest受到同源策略的约束,不能跨域访问资源,在AJAX应用的开发中尤其需要注意这一点。

如果XMLHttpRequest能够跨域访问资源,则可能会导致一些敏感数据泄露,比如CSRF的token,从而导致发生安全问题。但是互联网是开放的,随着跨域请求的需求越来越迫切

w3C委员会制定了XMLHttpRequest跨域访问标准。它需要通过目标域返回的HTTP头来授权是否允许跨域访问,因为HTTP头对于JavaScript来说一般是无法控制的,所以认为这个方案可以实施。注意:这个跨域访问方案的安全基础就是信任"JavaScript无法控制该HTTP头”

对于浏览器来说,除了DOM, Cookie,XMLHttpRequest会受到同源策略的限制外,一些第三方插件也有各自的同源策略。最常见的一些插件如Flash, Java Applet.Silverlight. Google Gears等都有自己的控制策略。

在www.b.com/test2.html中通过@import加载了http://www.a.com/test.html为Css文件,渲染进入当前页面DOM,同时通过document.body.currentStyle.fontFamily访问此内容。问题发生在IE的CSS Parse的过程中, IE将fontFamily后面的内容当做了value,从而可以读取www.a.com/test.html的页面内容。