前段时间工作时,安全同学特意提醒要注意安全问题,如:
个人中心
里面的越权漏洞 (越权查看个人地址,越权领奖,越权订单,越权发票等数据)坦白说,安全这块关注比较少,于是跟安全同学交流学习,推荐一本叫白帽子讲 web 安全书籍,本文的内容是基于该书籍的介绍进行修改调整。
本书全名:白帽子讲 Web 安全
作者:吴翰清
出版社:电子工业出版社
版次:2015 年 1 月
随需而得
。简单分为 4 个阶段:
威胁分析就是把所有的威胁都找出来,一般是采用头脑风暴法。
但大部分会采用威胁建模,把尽可能多的风险列出,好处是避免遗漏,常用的方法叫STRIDE模型,如下:
主要包括伪装、篡改、抵赖、信息泄露、拒绝服务、提升权限。
风险由以下因素组成:
Risk = Probability * Damage Potential
影响风险高低的因素,除了造成损失的大小外,权衡事件发生的可能性,才能正确地判断出风险。
微软提出的DREAD模型可以更科学的判断威胁的风险程度:
优秀的安全方案应该具备以下特点:
id=1、2、3
递增的方式,建议使用加密算法、随机数算法、哈希算法来提供不可预测性。指A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"
。
定义如下:
协议相同
域名相同
端口相同
举例来说,http://www.jb.com/dir/page.html
这个网址,协议是http://
,域名是www.jb.com
,端口是80
,它的同源情况如下。
http://www.jb.com/dir2/other.html:同源
http://www.jb.com/dir/inner/another.html:同源
http://jb.com/dir/other.html:不同源(域名不同)
http://v2.www.jb.com/dir/other.html:不同源(域名不同)
http://www.jb.com:81/dir/other.html:不同源(端口不同)
设想这样一种情况:
用户登录 A 网站以后,又去浏览网站 B。如果网站 B 可以读取 A 网站的 Cookie
,会发生什么?
很显然,如果Cookie
包含隐私(比如金额、个人信息等),这些信息就会泄漏。
由此可见,同源政策的目的是为了保证用户信息的安全,防止恶意的网站窃取数据。
沙箱模型技术是浏览器和其他应用程序中保护安全的一种组件关系设计模式,设计目的一般是为了让不可信任的代码运行在一定的环境中,限制不可信任的代码访问隔离区之外的资源。
工作原理一般是,浏览器周期性地从服务器端获取一份最新的恶意网址黑名单,如果用户上网时访问的网址存在于此黑名单中,浏览器就会弹出一个警告页面。
XSS
攻击通常指黑客通过HTML注入
篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。
某天,公司需要一个搜索页面,根据 URL
参数决定关键词的内容。jb 很快把页面写好并且上线,代码如下:
<input type="text" value="<%= getParameter("keyword") %>">
<button>搜索</button>
<div>
您搜索的关键词是:<%= getParameter("keyword") %>
</div>
然而,在上线后不久,就接到了安全组发来的一个神秘链接:
带着一种不祥的预感点开了这个链接,页面中弹出了写着” XSS” 的对话框。
当浏览器请求 http://xxx/search?keyword="><script>alert('XSS');</script>
时,服务端会解析出请求参数 keyword
,得到 "><script>alert('XSS');</script>
,拼接到 HTML
中返回给浏览器。形成了如下的 HTML
:
<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索</button>
<div>
您搜索的关键词是:"><script>alert('XSS');</script>
</div>
浏览器无法分辨出 <script>alert('XSS');</script>
是恶意代码,因而将其执行。
这里不仅仅 div
的内容被注入了,而且 input
的 value
属性也被注入, alert
会弹出两次。
恶意代码未经过滤,与网站正常的代码混在一起;
浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
存储型XSS
会把用户输入的数据存储在服务器端,具有很强的稳定性。
攻击步骤:
把用户输入的数据反射给浏览器,黑客往往需要诱使用户点击一个恶意链接,才能攻击成功。
攻击步骤:
反射型跟存储型的区别
通过修改页面的DOM
节点形成的XSS
,称之为DOM Based XSS
。
攻击步骤:
URL
,其中包含恶意代码。URL
。JavaScript
取出 URL
中的恶意代码并执行。跟前两种的区别:
DOM
型 XSS
攻击中,取出和执行恶意代码由浏览器端完成,DOM 属于前端 JavaScript 自身的安全漏洞,而其他两种XSS
都属于服务端的安全漏洞。XSS
攻击有两大要素:
常见的Web
漏洞如XSS、SQL Injection
等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。
输入检查的逻辑,必须放在服务器端代码中实现。如果只是在客户端使用JavaScript
进行输入检查,是很容易被攻击者绕过的。
目前Web
开发的普遍做法,是同时在客户端 JavaScript 中和服务器端代码中实现相同的输入检查。客户端JavaScript
的输入检查,可以阻挡大部分误操作的正常用户,从而节约服务器资源。
在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御XSS
攻击。
CSRF(Cross-site request forgery)跨站请求伪造:
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
a.com
,并保留了登录凭证(Cookie
)。b.com
。b.com
向 a.com
发送了一个请求:a.com/act=xx
。浏览器会默认携带a.com
的Cookie
。a.com
接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。a.com
以受害者的名义执行了act=xx
。a.com
执行了自己定义的操作。get
类型,直接请求一个url
即可。post
类型,访问链接后自动提交表单,模拟完成一个post
操作。URL
、超链接、CORS
、Form
提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。Referer Check
,用于检查请求是否来自合法的源,但目前大部分都可以自定义请求头,所以也只能是辅助形式。Token
,这是页面目前公认的做法,下面详细说明。上面提及到CSRF
的特性,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用 Cookie 中的信息。
而CSRF
攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么可以要求所有的用户请求都携带一个CSRF
攻击者无法获取到的Token
。服务器通过校验请求是否携带正确的Token
,来把正常的请求和攻击的请求区分开,也可以防范CSRF
的攻击。
CSRF Token
输出到页面中。Token
。Token
是否正确。Token 的值必须是随机生成的。
点击劫持是一种视觉上的欺骗手段。
攻击者使用一个透明的、不可见的iframe
,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe
页面。
一眼看这个按钮没啥问题,但实际会跳到jb.html
,还可以模拟一些博客的点赞、关注功能,但因为需要诱使用户与页面进行交互,实施的攻击成本更高,一般来说都比较少见。
用户以为点击的是下层页面内容,但真正操作的是上面的透明的一层。而因为它是透明的,真正的意图是由攻击者在控制。
注入安全应该是安全领域中最常见的攻击方式,一般测试同学也是比较关注这类,前面提交到的xss
本质也是对HTML
的注入攻击。
注入攻击的本质,是把用户输入的数据当做代码执行。
关键的条件:
有这么一段逻辑:
var Shipcity;
ShipCity = Request.form ("ShipCity");
var sql = "select * from OrdersTable where
ShipCity = '" + ShipCity + "'";
变量ShipCity
的值由用户提交,在正常情况下,假如用户输入Beijing
,那么SQL
语句会执行:
SELECT * FROM OrdersTable WHERE ShipCity = 'Beijing'
但假如用户输入一段有语义的SQL
语句,比如:
Beijing'; drop table OrdersTable--
那么,SQL
语句在实际执行时就会如下:
SELECT * FROM OrdersTable WHERE ShipCity =
'Beijing';drop table OrdersTable--'
这里看到,原本正常执行的查询语句,现在变成了查询完后,再执行一个 drop 表的操作,而这个操作,是用户构造了恶意数据的结果。
1. 猜测数据库名,备份数据库
2. 猜解字段名称
3. 遍历系统的目录结构,分析结构并发现WEB虚拟目录,植入木马
4. 查询当前用户的数据库权限
5. 设置新的数据库帐户提权得到数据库管理员账户权限
6. 利用存储过程获取操作系统管理员账户
7. 客户端脚本攻击:通过正常的输入提交方式将恶意脚本提交到数据库中,当其他用户浏览此内容时就会受到恶意脚本的攻击。
8. 客户端脚本攻击:通过SQL注入方式将恶意脚本提交到数据库中,直接使用SQL语法UP
String sql = "select id, no from user where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.executeQuery();
如上所示,就是典型的采用 sql
语句预编译和绑定变量 。为什么这样就可以防止sql
注入呢?
因为采用了PreparedStatement
,就会将sql
语句:"select id, no from user where id=?"
预先编译好,也就是SQL
引擎会预先进行语法分析,产生语法树,生成执行计划.
后面输入的参数,无论输入的是什么,都不会影响该sql
语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql
命令,比如 select ,from ,where ,and, or ,order by
等等。
所以即使后面输入了这些sql
命令,也不会被当成sql
命令来执行了,因为这些 sql 命令的执行, 必须先的通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql
命令来执行的,只会被当做字符串字面值参数。所以sql
语句预编译可以防御sql
注入。
有一些场景必须的采用字符串拼接的方式,此时需要严格检查参数的数据类型,还有可以使用一些安全函数,来防止 sql 注入。
安全函数的使用,比如:
MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
name = ESAPI.encoder().encodeForSQL(codec, name);
String sql = "select id,no from user where name=" + name;
ESAPI.encoder().encodeForSQL(codec, name)
该函数会将 name
中包含的一些特殊字符进行编码,这样 sql
引擎就不会将name
中的字符串当成sql
命令来进行语法分析了。
比如 String sql = "select id,no from user where id=" + id;
在接收到用户输入的参数时,我们就严格检查 id
,只能是int
型。复杂情况可以使用正则表达式来判断。这样也是可以防止sql
注入的。
XML
是一种常用的标记语言,通过标签对数据进行结构化表示,进行攻击需要满足两大条件:
解决方案跟上面类似,对用户输入数据中包含的保留字符进行转义即可。
代码注入与命令注入往往都是由一些不安全的函数或者方法引起的。
对抗代码注入、命令注入时,需要禁用eval()、system()
等可以执行命令的函数。如果一定要使用这些函数,则需要对用户的输入数据进行处理。
代码注入往往是由于不安全的编程习惯所造成的,危险函数应该尽量避免在开发中使用,可以在开发规范中明确指出哪些函数是禁止使用的。
了解安全评估流程,xss、csrf、sql
注入攻击的原理及常用的预防措施,点击劫持常用的手段信息。