作为一名安全爱好者,在安全路上不断探索的过程中,每次拜读安全大牛的作品时,都有不同的收获,证明你看待安全的角度和高度上了新台阶,第一次接触过《白帽子讲web安全》,小白的我既懵懂又敬佩,时隔多年,再次拜读,虽说一些技术已过时,但思想是不老的,特此分享阅读笔记。
作者格言
吴翰清领导的团队每天帮助阿里云抵御16亿次的黑客攻击。吴翰清现在年薪五百多万,甚至阿里的创始人马云都说阿里离不了吴翰清。
互联网本来是安全的,自从有了研究安全的人,就变得不安全了;
安全是一门朴素的学问,也是一种平衡的艺术;
一个优秀的安全方案,应该是:在正确的地方,做正确的事。
安全工程师的核心竞争力不在于他能拥有多少个0day,掌握多少种安全技术,而是在于他对安全理解的深度,以及由此引申的看待安全问题的角度和高度。
“破坏永远比建设容易” “最大的漏洞就是人!”
如果新技术不在一开始就考虑安全设计的话,防御技术必然会落后于攻击技术;
安全问题的本质是信任的问题。(将文件锁在抽屉中);安全三要素:机密性、完整性、可用性。
不可预测性,能有效地对抗篡改、伪造的攻击;(加密算法、随机数、哈希算法)
白帽子与黑帽子
白帽子一般为企业或安全公司服务,工作的出发点就是解决所有的安全问题,因此所看到的必然要求更加全面、宏观;
黑帽子主要目的是入侵系统,找到他们有价值的数据,因此黑帽子只需要以点突破,找到对他们最有用的一点,以此渗透,因此思考问题的出发点必然是有选择性的、微观的。
客户端脚本安全
HttpOnly不等于绝对安全
使用HtppOnly有助于缓解XSS攻击,但还有窃取用户信息、模拟用户身份等严重后果,曾经Apache支持的一个header是TRACE,TRACE一般用于调试,它会将请求头作为HTTP的Response Body返回,利用这个特性可以把HtppOnly Cookie读出来。目前各产商已经修补这些漏洞,但未来也许会出现新的漏洞,现业界给关键业务添加HttpOnly Cookie已成为标准做法。
P3P( Platform for Privacy Preferences,隐私设定平台规范)
P3P头的介入改变a.com的隐私策略,从而使<iframe>、<script>等标签在IE中不再拦截第三方cookie的发送。P3P头只需要由网站设置一次即可,之后每次请求都会遵循此策略,不需要重复设置。
P3P头现在网站的应用中被广泛应用,因此CSRF的防御不能依赖浏览器对的第三方Cookie的拦截策略,如果测试CSRF时发现<iframe>等标签在IE中居然能发送cookie,可能是P3P在作怪。
Token
CSRF的Token仅仅用于对抗CSRF攻击,当网站还同时存在XSS漏洞时,这个方案会无效,因为XSS可以模拟客户端浏览器执行任意操作,在XSS攻击下,攻击者完全可以请求页面后,读取出页面内容的Token值,然后再构造一个合法的请求,这个过程称之为XSRF,和CSRF以示区分。
注意Token的保密性和随机性。
点击劫持
点击劫持与CSRF有异曲同工之妙,都是在用户不知情的情况下诱使用户完成操作,但在CSRF攻击的过程中,如果出现用户交互的页面,功能可能无法顺利完成。与之相反,点击劫持利用的就是与用户交互的界面。
利用图片的style,或者能够控制CSS,如果应用没有设置style的position为absolute的话,图片就可以覆盖到页面的任意位置,形成点击劫持。
X-Frame-Options是为了解决点击劫持而生的,当值为DENY时,浏览器会拒绝当前页面加载任何frame页面;当值为SAMEORIGIN,frame页面的地址只能为同域名下的页面;若值为ALLOW-FROM,则可以定义允许frame加载的页面地址。
Firefox的Content Security Policy以及Firefox的NoScript扩展可以有效防御点击劫持;
HTML5安全
Canvas是H5最大创新之一,<canvas>标签让js可以在页面直接操作图片对象,也可直接操作像素,构造图片区域。
通过Canvas自动破译验证码,最大的好处是可以在浏览器环境中实现,降低攻击门槛。H5使过去难以做到的事情变为可能。
postMessage允许每一个window(包括当前窗口、弹出窗口、IFRAMES等)对象往其他窗口发送消息,从而实现跨窗口的消息传递。这个功能不受同源策略的限制。所以使用时需要注意:
1.必要时验证窗口的Domain,甚至URL,实际是在代码中实现一次同源策略的验证过程。
2.在接收窗口不应该信任接收到的消息,需要对消息进行安全检查。
服务端应用安全
注入攻击的本质,是把用户和输入的数据当做代码执行。两个关键条件:1是用户能够控制输入;2是原本程序要执行的代码,拼接了用户输入的数据。
注入攻击
INTO DUMPFILE适用于二进制文件,他会将目标文件写入同一行内;而OUTFILE则更适用于文本文件。
写入文件的技巧,经常被用于导入一个webshell,因此在设计数据库安全方案时,可以禁止普通数据库用户具备操作文件的权限。
一般来说,在数据库中执行系统命令,要求具有较高的权限。在建立数据库账户时应遵循“最小权限原则”,尽量避免给Web应用使用数据库管理员的权限。
UDF(用户自定义函数)
在攻击过程中,将lib_mysqludf_sys.so上传到数据库可访问的路径。在创建UDF后,就可以使用sys_eval()和sys_exec()等函数执行系统命令;
攻击存储过程
存储过程为数据库提供了强大的功能,跟UDF很像,但存储过程必须使用CALL或EXECUTE执行(臭名昭著的“xp_cmdshell”)。在MS SQL Server和Oracle数据库中,都有大量的存储过程,很多存储过程存在SQL注入问题。
宽字节注入(基于字符集注入)
当php的addslashes()函数或者当magic_quotes_gpc开启时,会在特殊字符前加转义字符"\"
当mysql使用GBK编码时,如: 0xbf27 or 1=1’
0x27被转义为0x5c27,0x5c跟0xbf拼凑成一个字符,因此转义符号0x5c(\)被吃掉。
要解决这个问题,需要统一数据库、操作系统、web应用所使用的的字符集,避免各层对字符理解存在差异。统一设置为UTF-8是个很好方法。
正确防御SQL注入
1.防御sql注入的最佳方式,就是使用预编译语句,绑定变量。
2.使用安全的存储过程对抗sql注入;需要将sql语句定义在数据库中,存储过程也可能存在注入,要避免使用动态SQL语句;如无法避免,则应该使用严格的输入过滤或者编码函数来处理用户的输入数据;
3.检查数据类型,如限制输入数据只能为integer;
4.使用安全函数,如OWASP ESAPI;
5.为每个应用分配不同的账户,web应用使用的数据库账户,不应该创建自定义函数、操作本地文件的权限;
CRLF注入
CR是“\r”, 十六进制为0x0d
LF是“\n”,十六进制为0x0a;
\r\n这两个字符用于表示换行。
CRLF注入并非仅能用于log注入,凡是使用CRLF作为分隔符的地方都有可能存在注入,如“注入HTTP头”
对抗CRLF非常简单,只要处理好“\r”"\n"这两个字符即可,尤其是那些使用“换行符”作为分隔符的应用。
设计安全的文件上传功能
1.文件上传的目录设置为不可执行;(文件上传后放到独立的存储上,做静态文件处理)
2.判断文件类型,结合mime type、后缀检查,推荐使用白名单;对于图片处理,使用压缩函数或relize函数,在处理图片的同时破坏可能包含的HTML代码。
3.使用随机数改写文件名和文件路径。
4.单独设置文件服务器的域名;(浏览器同源策略)
Apache文件解析问题:在1.x,2.x中,对文件名从后往前解析,知道遇见认识的文件类型为止定义在(mime.types),将a.php.rar解析成a.php;
IIS文件解析问题:当文件名为abc.asp;xx.jpg时,IIS6将文件解析为abc.asp;
加密算法与随机数
ECB模式的缺陷
对于ECB模式来说,改变分组密文的顺序,将改变解密后的明文顺序;替换某个分组密文,解密后该对应分组的明文也会被替换,而其他分组不受影响;党需要加密的明文大于一个分组长度时,应变使用ECB模式;
PKCS#5填充
Padding Oracle Attack,对CBC模式,在不知道密钥的情况下,对padding bytes进行尝试,还原出明文,或者构造出任意明文的密文;
类似于差分故障注入,原理为:假iv ^ 假明文 =真iv ^ 真明文=中间值
密钥管理
密码系统的安全性应该依赖于密钥的复杂性,而不是算法的复杂性;
密钥管理最常见的错误,就是将密钥硬编码在代码中;一是可能导致代码被广泛传播,二是软件开发团队的成员都能查看代码;
对web应用,常见的做法是将密钥(包括密码)保存在配置文件或者数据库中,每个web应用需要使用密钥时,通过带认证信息的API请求密钥管理系统,动态获取密钥,保护密钥私密性。
在应用发布到生产环境中,需要重新生成新的密钥或密码,以免与测试环境中使用的密钥相同。
密钥集中管理,降低系统对于密钥的耦合性,也有利于定期更换密钥;密钥管理的主要目的,防止密钥从非正常的渠道泄露。
时间真的随机吗
切记:不要把时间函数当成随机数使用;
种子一旦确定,在通过同一伪随机数算法计算出来的随机数,其值是固定的,多次计算所得之也是固定的;
一定要使用足够强大的随机数生成算法,在java中,可以使用java.security.SecureRandom
web框架安全
xss防御
通过自定义的方法,使xss防御的功能得到完善;甚至在代码检测工具中,可以自动判断使用哪种安全的编码方法;依据“是否有细分场景使用不同的编码方式”来判断XSS的安全方案是否完整;不可盲从指导文档。
CSRF防御
使用security token得私密性(不可预测原则)解决CSRF攻击问题;
“读数据”不是CSRF的攻击目标,对“读数据”“写数据”予以区分,比如要求所有的写操作都是用HTTP POST;
在spring mvc以及一些其他流行的web框架,并没有直接针对CSRF的保护,需要自己实现;
HTTP headers管理
框架会提供一个统一的设置cookie函数,HttpOnly的功能可以在此函数实现;就不用担心有遗漏;
对框架来说,管理好跳转的目的地址是必要的
(1)如果提供统一的跳转函数,可以实现一个白名单,制定跳转地址只能在白名单内;
(2)控制HTTP的Location字段,限制只能哪些地址,本质还是白名单;
文件包含漏洞
本地文件包含漏洞(LFI)
php的include()、require()、include_once()、require_once()包含一个新的文件时,该文件作为PHP代码执行,PHP内核不在意被包含的文件是什么类型;
fopen()、fread()能够读取敏感文件带来的后果也比较严重;
php的open_basedir作用是限制在某个特定目录下PHP能打开的文件,避免目录遍历漏洞;
要解决文件包含漏洞,应该避免包含动态的变量,使用枚举:
远程文件包含(RFI)
如果PHP的配置选项allow_url_include为ON的话,include/require是可以加载远程文件的。
远程代码执行
PHP中有不少可以直接执行代码的函数,如:eval()、assert()、system()、exec()、shell_exec()、passthru()、pcntl_exec()等。
一般来说,最好在PHP中禁用这些函数;
unserialize()导致代码执行
unserialize()它能将序列化的数据重新映射为PHP变量。如果定义了_destruct()函数,或者是_wakeup()函数,这两个函数将执行。
定制安全的PHP环境
register_globals:为ON时,php不知道变量从何而来,容易出现变量覆盖,强烈建议设置为OFF;
为了对抗远程文件包含,请关闭allow_url_include和allow_url_fopen;
display_errors,错误回显,一般用于开发模式,推荐关闭;
magic_quotes_gpc
推荐关闭,还能提高性能,不值得依赖;
session.cookie_httponly=1:开启;
session.cookie_secure:若是全站https则开启;
cgi.fix_pathinfo:若php以cgi安装,则需关闭,避免文件解析问题;(访问/test.jpg/noexit.php将jpg解析成php)
safe_mode:会影响很多函数,如实共享环境,建议开启,与disable_functions配合使用;如是单独的应用环境,考虑关闭,更多依赖disable_functions控制环境安全;
disable_functions:在php中禁用函数,禁用函数可能为开发带来不便,禁用太少增加写出不安全代码的几率;
对于PHP6来说,magic_guotes_gpc、safe_mode已经取消;
Web Server配置安全
检查module安装情况,根据"最小权限原则"运行web进程,尽可能减少不必要的module,检查使用的module对应版本是否存在已知漏洞;
一些参数可以优化性能,缓解DDOS攻击;
最后,补充一句,如果我们的产品能够潜移默化地培养用户的安全习惯,将用户往更安全的行为上引导,这样的安全是最理想的产品安全;
网友评论