# 编码安全规范
此安全规范参考多处网上公开资源整合,如有侵权,请告知
# 概述
通过对主流的WEB高危漏洞表现形式和危害介绍,增强WEB应用开发人员的安全意识,以WEB应用开发安全原则和解决方案规范开发过程中的安全控制,推动开发人员编写强壮安全的代码。
# 名词解释
# 跨站脚本攻击Cross Site Script(XSS)
攻击者利用应用程序的动态展示数据功能,在html页面里嵌入恶意代码。当用户浏览该页之时,这些嵌入在html中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的。
# 反射型跨站脚本攻击
攻击者会通过社会工程学手段,发送一个URL连接给用户打开,在用户打开页面的同时,浏览器会执行页面中嵌入的恶意脚本。
# 存储型跨站脚本攻击
攻击者利用web应用程序提供的录入或修改数据功能,将数据存储到服务器或用户cookie中,当其他用户浏览展示该数据的页面时,浏览器会执行页面中嵌入的恶意脚本,以至于所有浏览者都会受到攻击。
# DOM跨站攻击
由于html页面中,定义了一段JS,根据用户的输入,显示一段html代码,攻击者可以在输入时,插入一段恶意脚本,最终展示时,会执行恶意脚本。
# SQL注入攻击(SQL injection)
由于html页面中,定义了一段JS,根据用户的输入,显示一段html代码,攻击者可以在输入时,插入一段恶意脚本,最终展示时,会执行恶意脚本。
# 任意文件上传攻击(File upload)
由于html页面中,定义了一段JS,根据用户的输入,显示一段html代码,攻击者可以在输入时,插入一段恶意脚本,最终展示时,会执行恶意脚本。
# 任意文件下载攻击(File download)
当用户通过web 下载文件时,所下载文件及路径为变量形式传给程序,程序未对下载文件及路径做检测,导致用户可随意输入下载地址,造成任意文件下载漏洞的出现。
# 开发规范
# 输入验证
# SQL注入
# 表现形式
当应用程序将用户输入的内容,拼接到SQL语句中,一起提交给数据库执行,就会产生SQL注入威胁。
# 危害性
- 可读取数据库中的库和表
- 可执行系统命令
- 可修改任意文件
- 可安装木马后门
# 开发原则
- 最小输入原则:限定输入长度及类型:浏览器限字符串最大为2083字节(微软Internet Explorer)实际可使用的URL长度为2048字节。Firefox:65536字节,Chrome:8182字节,Safari:80000字节,Opera:190000字节
- 客户端与服务器端必须都做验证:建立白名单,拒绝所有其他数据。服务端做数据处理的SQL语句不允许拼接参数,使用参数化方式创建SQL语句
- 数据库部分:储存过程中不允许出现exec
# 解决方案
【辅助】过滤或转义:对参数进行关键词过滤(所有可能操作数据库
信息的关键字);对关键字进行转义
【首选】使用参数化方式创建SQL语句进行数据处理
【推荐】使用第三方安全框架ESAPI处理参数
# 跨站脚本攻击
# 表现形式
Web应用程序从用户处获取输入,不经验证,直接在Web页面上输出。漏洞类型:存储型XSS / 持久型、反射型XSS / 非持久型、DOM based XSS。
# 危害性
- 盗取用户cookie,伪造用户身份登录
- 控制用户浏览器
- 结合浏览器及其插件漏洞,下载病毒木马到浏览者的计算机上执行
- 衍生URL跳转漏洞
- 使官方网站出现钓鱼页面
- 蠕虫攻击
- 盗取客户端键盘记录
# 开发原则
- 对输入进行安全性白名单/黑名单验证,可采用正则表达式。如统一大小写之后再验证,并且如果采用危险字符(特殊字符+关键字)过滤的方式进行验证,勿将危险字符替换为空,容易产生绕过
- 验证所有的headers, cookies, query strings, form fields, hidden fields
- 对即将输出到前端的用户可控数据进行编码转义
- 不要在JS文件中编写重要代码
- 在测试阶段, 进行必要的安全测试和检验
# 解决方案
【辅助】输入验证:验证输入,确保所有可能构成JavaScript、CSS等语句的特殊字符及关键字都被验证(过滤或转义)。针对必须包含富文本的特殊需求,谨慎设置白名单
【强制】输出转义:
HTML标签转义,下表为需要编码的字符:
元字符 编码后字符 & & amp; < & lt; > & gt; “ & qout; ‘ & #x27; / & #x2F; JavaScript内容转义。Java示例代码:
<script>alert('#escapeJavaScript($user.name)')</script> <script>x='#escapeJavaScript($user.name)</script> <div onmouseover="x='#escapeJavaScript($user.name)'"></div>CSS style内容转义:把除了字母、数字外的所有字符都编码成十六进制,形式为“\uHH”
URL内容安全编码:可使用URLEncode,将字符转换成“%HH”的格式
XML中对数据部分做HTML转义。示例代码:
String q = "random word $500 bank$"; String url = "http://example.com/query?q=" +URLEncoder.encode(q,"UTF-8");JSON内容做HTMLEscape,再对变量做一次JavascriptEscape。示例:
<?xml version="1.0" enconding="UTF-8" ?> <man> <name>#eacapeXML($name)</name> </man>
【强制辅助】给Cookies加上HttpOnly选项。在Http响应中,使用Set-Cookie时,添加额外的标签,该标签会保护cookie,防止JavaScript读取:
使用HttpOnly函数,javax.servlet.http.Cookie:
Cookie cookie = getMyCookie("myCookieName"); cookie.setHttpOnly(true);当使用Java EE 6和以上版本,HttpOnly flag可以在web.xml中设置:
<session-config> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config>Tomcat六以上的版本,可以在context.xml中添加useHttpOnly属性:
<?xml version="1.0" enconding="UTF-8" ?> <context path="/myWebApplicationPath" useHttpOnly="true">
【推荐】预防XSS的安全框架
- JAVA:ESAPI框架,对富文本处理有良好的支持
- .NET : ANTIXSS支持
- PHP: XSS支持
【强制】禁止引用第三方脚本,禁止iframe引用第三方页面
# 文件上传
# 表现形式
Web应用程序在处理用户上传的文件操作时,如果用户上传文件的路径、文件名、扩展名成为用户可控数据,就会导致直接上传脚本木马到web服务器上,直接控制web 服务器:
- 中间件解析漏洞:llS6.0:Microsoft IIS 可以执行ASP 或者任何其他可执行扩展执行任何扩展名文件,如"a.asp;.jpg"就以ASP或ASPX 文件方式在服务器上执行, 需要文件上传程序通过检查文件名的最后一段作为扩展名来保护系统。利用这个漏洞,攻击者可以绕过保护把危险的可执行文件上传到服务器上。上传a.asp; .jpg, 服务器发现后缀为jpg,允许上传,但通过web访问时由;自动截断,执行a.asp木马程序(iis6.0解析漏洞)
- 00截断上传漏洞:上传文件名为x.php%00.jpg 时,php 验证程序后缀名为JPG 允许上传,当php取文件名时,读取到%00 会认为是截断符号,以x.php 进行存储,最终导致php 文件上传
# 危害性
恶意用户可以上传任意文件,甚至上传后门、木马,病毒,恶意脚本或者WebShell到web服务器上,直接控制web服务器
# 开发原则
- 由程序自定义上传文件的文件名称
- 只接受指定类型的文件(如zip、图片等),并验证上传文件类型
- 检查上传文件的大小
- 重要目录设置文件访问权限。(Java SecurityManager)
- 所有涉及路径的操作验证路径安全性
# 解决方案
- 【推荐】上传文件要保存的文件名和目录名由系统根据策略生成,不允许用户自定义
- 【首选】允许用户自定义文件名的情况,需要做两个类型的验证:上传文件目录限制及文件类型白名单验证:
- 上传文件的目录必须是http请求无法直接访问到的
- 上传文件的目录必须限定于指定目录,为达到此需求同样需验证文件名,可借鉴操作系统对文件名称的要求:不能包含下列字符:""、"/"、":"、""、"?"、" " "、"<"、">"、"|"
- 设置文件类型白名单,并且正确验证文件类型:对于绝大部分开发人员使用的截取"."来判断文件名的方式,禁止截取最后一个"."字符做判断, 须以"."为分界字符截取字符串集合,循环验证集合内所有值,或者直接截取第一个"."字符(即文件名除了扩展名外不允许出现"."字符)
- 重要文件直接验证文件内容
- 【推荐】图片上传,通过处理(缩略图、水印等),无异常后再保存到服务器
- 【强制辅助】代码层面也须设置文件上传目录的权限,禁止文件执行:Java SecurityManager,可控制文件的读写、删除、执行权限
- 【推荐】上传文件需要做日志记录
# 任意文件下载
# 表现形式
用户通过web下载文件时,所下载文件及路径为变量形式传给程序,例:http://www.aaaaaa.com/download.action?file=centos.iso,若程序未对下载文件及路径做检测, 就会导致用户可随意输入下载地址,造成任意文件下载漏洞的出现
# 危害性
任意文件下载漏洞为高风险漏洞,可以读取服务器配置文件,相关用户名密码等,造成非常大的安全隐患
# 开发原则
- 要下载的文件地址保存至数据库中,让用户提交文件对应ID下载文件
- 下载文件之前做权限判断
- 文件放在web无法直接访问的目录下
- 记录文件下载日志
- 不允许提供目录遍历服务。所有涉及路径的操作验证路径安全性
# 解决方案
- 【辅助】限定文件读写权限(java SecurityManager)
- 【【首选】以下解决方案二选一:
- 验证外部输入的文件下载地址(文件名),验证合法性,可借鉴操作系统对文件名称的要求:不能包含下列字符:""、"/"、":"、"*"、"?"、" " "、"<"、">"、"|"
- 使用与下载地址有映射关系的md5串进行映射下载,下载地址存储于数据库,如下链接:http://www. aaaaaa.com/download.php?file=(32 位md5 串)
# 服务器端请求伪造(SSRF)
# 表现形式
SSRF(Server-Side Request Forgery:服务器端请求伪造.由攻击者构造形成由服务端发起请求的安全漏洞。也可称为:未验证的重定向或转发。 当服务端向内网或 第三方服务请求资源的时候,URL部分或全部可控,此时没有对目标地址做过滤与限制,漏洞引发。 一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。 由于它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统。
# 危害性
- 对服务器所在内网、本地进行端口扫描,获取一些服务的banner信息
- 攻击运行在内网或本地的应用程序(比如溢出)
- 对内网web应用进行指纹识别,通过访问默认文件实现
- 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等)
- 利用file协议读取本地文件等
# 开发原则
- 解析目标URL,获取其Host
- 解析Host,获取Host指向的IP地址
- 检查IP地址是否为内网IP
- 请求URL
- 如果有跳转,拿出跳转URL,执行第一步
# 解决方案
内网请求
- 【首选】设置内网可请求地址白名单,并将地址存于数据库,设置映射关系标识,前端用户必须通过标识来选择要请求的地址。 或者设置黑名单内网 IP,判断请求地址,限制在黑名单之外。以上方案原则上可二选一,实际应用推荐白名单
- 【强制辅助】统一错误信息,避免用户根据错误信息来判断远程服务器端口状态
- 【推荐辅助】限制请求的端口为 HTTP 常用端口,比如 80、443、8080、8090
- 【强制辅助】禁用不需要的协议。仅仅允许 HTTP 和 HTTPS 请求。可以防止类似于file://、gopher://和ftp://等引起的问题
外网请求:以下验证至少存在一种,并且首选白名单
- 【首选】根据需求设置外网请求地址白名单并验证
- 【次选】无法设置白名单的情况,更需谨慎对待当前页面,对XSS、cookie安全此类的安全策略应更严格。可在需要考虑SSRF 攻击但又无法设置白名单的位置添加url防篡改机制。如果有数据返回,需过滤或验证返回数据。可根据业务需求判断返回包是否包含预期以外的风险数据
- 【推荐辅助】禁止302跳转
# 跨站请求伪造(CSRF)
# 表现形式
攻击者在用户浏览网页时,利用页面元素(例如img的src),强迫受害者的浏览器向Web应用程序发送一个改变用户信息的请求。 一句话理解:攻击者借你的cookie(登陆权限),让你亲自完成attacker布置的操作(添加/删除/修改)并且你并不知道这个过程。
# 危害性
攻击者利用被攻击者的身份发起了某些被攻击者原本不知情的网络请求。包括被攻击者的身份发布一条微博,以被攻击者的身份发布一条留言 ,以被攻击者的身份关注某个用户的微博等。著名的微博蠕虫就是利用这种漏洞,造成了较大的影响。
# 解决方案
- 【强制辅助】所有敏感请求,都使用POST方式提交
- 【强制策略】重要操作做二次验证,如短信认证,二次密码认证,验证码、生物验证等。注:所有的验证码必须与实际参与业务的参数在同一请求内提交服务端li ,例:修改密码时,需要确保验证码、新密码、旧密码在同一请求内提交,避免验证码绕过。所有验证码不能传递到客户端,指标:客户端右键“查看源码”看不到验证码
- 【强制】使用token防御:用户交互时,设置一个具有超时机制的随机token,种植在用户的cookie 中。当用户提交表单时,生成隐藏域,值为cookie中随机token, 用户提交表单后匹配两处token值,来判断是否为用户提交。如:使用ESAPI框架生成token
- 【错误示例】不要靠验证referer的方式预防CSRF:验证用户提交数据的referer 信息,当为提交页时,说明为用户提交,当为其他页面时,说明为csrf 攻击。i 但是,referer是很容易被篡改的。所以,不要靠验证referer的方式预防CSRF
- 【参考】二次验证、token验证、referer验证,三种验证的安全度:二次验证>token验证>referer验证,正常请求使用token验证,重要请求使用二次验证
# XML外部实体攻击(XXE)
# 表现形式
XXE漏洞全称XML External Entity Injection 即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没 有禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害。 XXE漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。 DTD实体是用于定义引用普通文 本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
- 内部实体声明
- 引用外部实体
# 危害性
- 任意文件读取
- 命令执行
- 内网端口扫描
- 攻击内网网站
- 发起Dos攻击
# 开发原则
- 使用开发语言提供的禁用外部实体的方法
- 过滤用户提交的XML数据
# 解决方案
- 【推荐】使用开发语言提供的禁用外部实体的方法。如
- Php
- Java
- Python
- 【强制】过滤用户提交的XML数据:过滤关键词:
<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC
# 实体(Bean、JSON)注入
# 表现形式
在前后端进行数据交互时,数据形式以JSON、Bean为主。其中JSON可通过API直接转换成Bean实体;Bean可以通过spring mvc或struts等框架由前台表单参数自动填充属性值, 组成Bean实体。如果没有对这两种类型参数做限制,可能产生Bean的属性数据被篡改或者覆盖的情况,严重时可更改用户密码等私密数据。 同样,用于显示在前端的Bean 属性如果没有做限制,那么默认所有属性都将返回前端,暴露给用户,间接造成敏感数据泄露。 综上,对于实体注入漏洞,根据数据流方向及数据格式可做以下Bean操作分类:
- 后端Bean返回前端:敏感数据泄露
- 前端表单填充后端Bean:实体属性值篡改/覆盖 JSON注入:前端JSON传入后端转换为Bean,实体属性值篡改/覆盖
# 危害性
- 泄露bean中的属性
- 新建/更改用户权限、角色及其他重要信息
- 根据bean的功能不同引发其他类型漏洞:sql注入,XSS等
# 开发原则
- Bean操作:无论bean由前端填充到后端还是由后端返回前端显示,都禁止直接操作整个bean,而是操作我们实际需要的那几个属性
- 对于JSON注入,需要对传入的JSON key值做重复性验证
# 解决方案
- 【首选】Bean操作:
- 后端Bean返回前端显示:①使用vo的方式,每次数据返回前端组合一个新的vo实体;②使用@JsonView注释可过滤返回至前端的重要属性,@JsonView注释可以自己定义视图规则,在controller层可随意配置
- 前端表单填充后端Bean,避免使用框架自动填充整个实体,只使其填充需要的某些属性。否则,需要禁止填充不需要的重要属性:①Spring框架使用@ModelAttribute 注释的 Spring MVC 应用程序中,使用@InitBinder注释方法来配置绑定器,决定禁止绑定属性;②Spring框架使用@RequestBody注释的 Spring MVC 应用程序中,绑定i 过程由 HttpMessageConverter 实例处理,这些实例使用 Jackson 等库将 HTTP 请求正文转换为 Java 对象,使用@JsonIgnore注释以可阻止将某个字段绑定到请求; ③Struts 仅将 HTTP 请求参数绑定到对应公共 setter 访问器的 Actions 或 ActionForms 属性,可以将属性的 setter 设置为私有来禁止填充
- 使用populate方法进行bean操作时,理论上同样具有被注入的风险,实际开发过程中需要谨慎对待各参数。(示例代码:BeanUtils.populate(user, map);)
- 【首选】对于JSON注入,需要对传入的JSON key值做充分验证:
- 优先选择json-lib-2.1工具包,遇到JSON值覆盖(key值重复)的情况会抛出异常,IllegalArgumentException、JSONException,注意异常捕获处理
- 特殊字符验证:":"、" ” "、","
# HTTP响应截断
# 表现形式
与许多软件安全漏洞一样,Header Manipulation是达到目的的手段,而不是目的本身。 简单讲,在以下情况下会出现HTTP头操作漏洞:
- 数据通过不受信任的来源进入Web应用程序,最常见的是HTTP请求
- 数据包含在发送给Web用户的HTTP响应头中,而不进行验证
最常见的HTTP头操作漏洞是HTTP Response Splitting。假如应用程序允许CR(回车符,也由%0d或\ r \ n)和LF(换行符,也由%0a或\ n)字符输入, 那么不仅使攻击者能够控制应用程序打算发送的响应的标题和正文,而且还允许它们完全在其控制下创建其他响应。许多应用程序服务器都会阻止将恶意字符注 入HTTP响应头。例如Apache Tomcat,如果尝试设置带有禁止字符的响应头,tomcat会抛出IllegalArgumentException。 即使应用程序服务器会阻止使用恶 意回车/换行字符设置HTTP响应头,我们也应当在可控的代码中做相应的处理。至少要防止正常用户误操作引起的业务问题,保证安全、用户体验一个不能少。
# 危害性
响应截断导致第二个响应完全受攻击者控制,可能引发其他漏洞:XSS、页面劫持、结合跨站请求伪造进行cookie操作,恶意重定向等
# 开发原则
任何由用户控制的即将加入HTTP响应头信息的输入都需要经过验证
# 解决方案
【首选】所有请求都需过滤回车换行字符及其各种编码形式
# 日志伪造
# 表现形式
在以下情况下会发生日志伪造漏洞:
- 数据从不受信任的来源进入应用程序
- 数据被写入应用程序或系统日志文件
在理想的情况下,攻击者可以通过向应用程序提供包含特殊字符的输入,将错误信息插入日志文件中,可能伪造日志信息,也可能会破坏文件格式甚至使文件无法使用, 损坏的日志文件可用于覆盖攻击者的踪迹危害性。增加追踪困难度。
# 开发原则
- 避免将外部输入直接记录至日志中
- 严格的输入验证
# 解决方案
- 【推荐】记录至日志的信息做到开发人员完全可控
- 【推荐】特殊字符过滤:回车换行符及其各种编码形式、"%"、"="
# 其他注入
# 表现形式
根据代码业务的不同,应用系统可能还会面临以下注入类漏洞的攻击:
- 命令注入:用户输入可能控制系统命令
- 代码注入:系统需要执行一段由用户控制的代码,例:eval、setTimOut等方法
- 配置操纵:用户输入可能控制各种系统设置(例:各种配置文件中内容,db、cache(Redis)、log、activeMQ等)
- 资源注入:用户可能控制用于访问系统资源的标识符和连接网络资源的端口号。例如:根据用户输入的端口号建立一个socket
- LDAP注入:用户输入可能控制LDAP的语法、内容或者命令,类似SQL注入
- OGNL注入:存在于struts2框架,struts将http的请求参数对应为OGNL表达式,恶意用户可能修改系统变量或执行任意代码等
- XPath注入:用户输入可能构建动态的XPath语法进行恶意操作,与SQL注入类似,只不过XPath注入的目标是XML数据库,语言是XPath
以上类型的注入漏洞不多见,只是因为以上类型的开发不常用到,而不是不易被攻击,所以只要应用系统中包含了以上类型的代码开发,就可能产生对应风险。
# 解决方案
- 【推荐】禁止由用户输入来动态构成系统命令、各种script执行代码、系统配置、资源链接等
- 【首选】针对以上注入类型,例如命令注入、代码注入、配置操纵这种类型可以通过设置白名单的方式,或者通过代码与标识映射关系提供给用户选择;不能够设置白名单的,需要进行相应的、严格的输入验证。以下说明:
- 命令注入:";"、"&"、" " "、" ' "、"\xOA"、"\xFF"、"|"
- 代码注入:根据语言不同,确定需要验证的特殊字符,例:javaScript、php
- 配置操纵、资源注入:设立用户可操作白名单。(强制)
- LDAP注入:用户输入可能控制LDAP的语法、内容或者命令,类似SQL注入
- OGNL注入:升级框架版本,最低:OGNL3.0.21、Struts2.3.35,或验证特殊字符:"#"、"\u0023"、" " "、" ' "、"%"、"="、"["、"]"
- XPath注入:"/"、"@"、" " "、" ' "、"%"、"="、"["、"]"、":"、"//"、" "("、" ')"、","
# 安全特性
# 失效的身份认证和会话管理
# 表现形式
- 失效的身份认证
- 使用容易猜测的用户名、用户名对大小写不敏感、用Email做用户名时,未验证注册Email的有效性.只使用密码做认证。不安全的认证错误提示信息、实现不当的验证码机制; 使用过于简单的密码、实现不当的密码恢复机制、密码安全存储(不安全客户端存储等)
- 脆弱Token的实现机制,如使用易被破解的信息生成SessionID。配置不当的单点登录系统SSO
- 失效的会话管理:
- 会话超时利用:没有会话超时机制、公共计算机中的浏览器存储了用户凭证
- 脆弱的/可预测的会话ID:使用带有逻辑性,易被猜测的ID、使用脆弱的加密
- 会话固定攻击(Session Fixation):攻击者把已知的SessionID诱使受害者去使用,使之成为有效的会话ID
- 会话劫持:如SessionID没有添加HTTPOnly标签,导致XSS劫持会话
# 危害性
攻击者可以利用认证或会话管理功能中的泄露或漏洞(比如暴露的账户、密码、或会话ID)来假冒用户, 这些漏洞可能会导致部分或全部账户遭受攻击。一旦成功,攻击者能执行受害用户的任何操作。
# 开发原则
- 失效的身份认证
- 强制性的强密码策略认证,密码长度不少于8位
- 防止短期内密码重用,比如新密码和老密码一样
- 密码有效期,比如设置3个月更换一次密码
- 当登录失败次数超过限定值时,需账户锁定,如自动锁定30分钟或人工申请解锁
- 不要使用与个人隐私相关的数据,如生日,妻子生日,姓名缩写,英文名,手机号码QQ号码等
- 重要应用要求强密码策略,并考虑双因素认证
- 密码必须以不可逆的加密算法,如Hash算法等,加密之后存储在数据库,使用高级的密码哈希算法,如Bcrypt
- 失效的会话管理:
- 使用应用容器提供的标准的SessionID机制
- 使用推荐使用的加密机制,比如SHA1 SHA2等
- 确保用户凭证和SessionID在使用过程中,都处于SSL/TLS的保护下
- 话Cookie在浏览器端 的安全配置,如HTTPOnly、Secure、限定域和作用范围、最大存活时间
- 针对敏感操作,需要使用二次认证的机制来确保安全
- 在任何权限变更之后,需重置新的会话,如多用户登录或账户切换
- 设置登出功能,并在登出操作之后,确保该用户Session被销毁
- 自动会话过期机制
- 空闲超时,比如30分钟未使用,进行过期操作
# 解决方案
- 失效的身份认证
- 【推荐】验证密码强度,可使用ESAPI Authenticator去验证密码的强度。检查新密码不会中出现一个子字符串包包含3个字符与旧密码中相同; 包含以下字符:CHAR_LOWERS, CHAR_UPPERS, CHAR_DIGITS, CHAR_SPECIALS防止短期内密码重用,比如新密码和老密码一样
- 【强制】生成强壮的初始密码:可使用ESAPI Authenticator。随机生成器生成的密码,包含大写字符,小写字符,数字,特殊字符
- 失效的会话管理:
- 【强制】确保会话超时机制得以实现或正确配置
- 【强制】在完成认证之后,改变SessionID确保用户凭证和SessionID在使用过程中,都处于SSL/TLS的保护下
- 【强制】在以下情况下,确保会话失效:一是用户登出;二是会话超时针对敏感操作,需要使用二次认证的机制来确保安全
- 【强制】严格对待Session可信边界:存入seesion的数据一定是可信的,而不是直接从用户处获取的。例:可根据用户传入的数据,去数据库查找与之对应的数据,再存入session,无论是对象还是简单的标识串
# 敏感信息泄露
# 表现形式
敏感信息:
- 客户个人信息:姓名、身份证号码、联系方式、住址、财务账号等
- 商业秘密:经营策略或战略、经营渠道、经营数据、业务规划与计划
- 知识成果:自有研发的业务知识成果、包括教材、课件等
- 薪资信息:员工薪资、职级等相关信息
- 合同信息:涉及合同相关的信息数据
- 业绩数据:涉及业务、业绩相关的报表及信息数据
- 财务数据:涉及业务收入、支出、预算等相关的财务数据
- 系统配置:信息系统运营和维护相关的配置数据,包括系统架构图、配置文件、密码密钥等
- 程序源代码:具有自主产权的程序源代码
表现形式举例:
- 应用程序可能没有对敏感数据进行安全加密
- http表单使用get方式提交
- http表单中涉及私密信息的输入框未设置禁止缓存功能、对重要表单进行默认填充
- 任何可能输出用户敏感信息以及应用系统信息的日志代码、debug代码、测试代码、未妥善处理的异常,同样包括各种直接显示给用户的中间件及版本信息的不安全设置等
- 密码字段使用不可清除的String对象存储
# 危害性
攻击者通常不直接攻击加密系统。被正确加密的数据是难以破解的。任何被忽略的记录代码及不安全代码的都可能会将用户及系统信息泄露给用户,作为恶意用户攻击应用系统的重要依据。
# 开发原则
- 【强制】重要数据使用强加密算法加密,传输使用https(SSL)
- 【强制】http表单提交选择POST方式,servlet处理请求使用doPost()方法;重要数据输入框禁止填充、禁止缓存:autocomplete="off"
- 【强制】日志系统禁止记录用户信息,有关用户信息的debug、测试代码禁止遗留
- 【强制】配置出现异常的统一访问页面,禁止系统异常信息流出
- 【强制】登陆等认证功能失败后,要提供一般性提示信息,禁止提供明确错误信息,防止攻击者“对症下药”,例:登陆认证失败,提示“用户名密码错误”,而不是“用户名不存在”
- 【推荐】密码字段优先选择StringBuffer、数组存储,使用后清除
- 【强制】永远不要相信隐藏域,禁止将敏感信息毫无保留的明文放于隐藏域
- 【强制】涉及敏感信息的页面都需要禁止页面缓存
# 解决方案
- 失效的身份认证
- 【推荐】验证密码强度,可使用ESAPI Authenticator去验证密码的强度。检查新密码不会中出现一个子字符串包包含3个字符与旧密码中相同; 包含以下字符:CHAR_LOWERS, CHAR_UPPERS, CHAR_DIGITS, CHAR_SPECIALS防止短期内密码重用,比如新密码和老密码一样
- 【强制】生成强壮的初始密码:可使用ESAPI Authenticator。随机生成器生成的密码,包含大写字符,小写字符,数字,特殊字符
- 失效的会话管理:
- 【强制】确保会话超时机制得以实现或正确配置
- 【强制】在完成认证之后,改变SessionID确保用户凭证和SessionID在使用过程中,都处于SSL/TLS的保护下
- 【强制】在以下情况下,确保会话失效:一是用户登出;二是会话超时针对敏感操作,需要使用二次认证的机制来确保安全
- 【强制】严格对待Session可信边界:存入seesion的数据一定是可信的,而不是直接从用户处获取的。例:可根据用户传入的数据,去数据库查找与之对应的数据,再存入session,无论是对象还是简单的标识串
# 访问控制(数据越权访问)
# 表现形式
场景:界面上有个连接,点击该连接指向张三的详细信息,url中有张三的id为参数,在地址栏中将张三的id修改为李四的id就看到了李四的数据。严重的情况会导致看到隐私的数据。
# 危害性
只要是通讯中明文的东西,就一定会被恶意地修改。即使你仅仅是传递一个123456(客户端根本不知道什么意思),也可以被改成abcdefg(胡乱修改)而成为逻辑炸弹,同时会成为水平权限攻击的方便条件。
# 开发原则
- 禁止出现以下的数据处理形式:仅仅通过一个容易预测的字段便能决定数据处理的集合(id、is_admin等状态、字典字段)
- url参数必须要通过urlDecode和urlEncode处理或者加密处理
- 增加url参数的不可预测性或者每个url 进行验权
- 如果可能设计url参数防篡改策略
# 解决方案
- 【首选】服务端应获取当前用户输入的id而非当前登录用户id去验证数据处理权限
- 【次选】设计URL参数防篡改策略。目标:防止篡改参数。若发现参数已通过客户端验证,但在提交服务端请求过程中被篡改,那么服务端中止任何响应。 此策略不仅可以预防此漏洞,还可预防其他只能靠篡改参数攻击的漏洞,防参数篡改的基本策略:所有参数及值加密,并且秘钥、加密方式在服务端
- 【辅助】降低URL参数的可预测性
- 针对重要标识,先加密然后存储到客户端标识中(cookie或自定义标识),数据处理时获取此加密标识
- 数据库表id和一般业务的标识位或数据字典code,加密或者使用32位uuid
# 不安全的加密存储
# 表现形式
- 密码、秘钥硬编码
- 使用不安全的密钥生成或存储方式
- 使用弱加密算法,如使用弱的哈希算法来保护密码
- 使用加密算法中的不安全填充模式或工作模式
# 危害性
攻击者通常不直接攻击加密系统,被正确加密的数据是难以破解的。不安全的加密算法或方式更容易被预测或破解从而被攻击者获取重要数据。
# 解决方案
- 【强制】用于加密或者数据模糊化的随机数生成器要选择SecuRandom
- 【强制】所有密码禁止在代码中硬编码,在代码或配置文件中明文存储
- 【参考】各种加密表现形式及安全度
- 最基本加密:对密码做hash+salt处理,确保salt安全存储以及做完善的访问控制,选择SHA2哈希算法系列
- 高级加密:hash算法有一定的安全性,但不能代替加密算法。对密码应该使用更高级的加密算法
- 【强制】选择使用高安全性加密算法的组件,并且密钥存储于数据库进行隔离,若在配置文件中存储密钥需加密或混淆保存,秘钥长度也要满足需求。其中AES秘钥最低128位,RSA最低2048位
- 【推荐】使用高安全度的工作方式或填充模式:使用CBC工作模式而非默认或ECB模式,最直观区别:ECB模式下,同样的明文将生成一样的密文, 而CBC模式每次密文都不同。对于RSA算法,要显示指定QAEP填充模式,可防止一些针对 RSA 的攻击
# 竞争条件
# 表现形式
常用框架spring mvc中的servlet默认为单例模式,在多线程的访问模式下,全局变量的访问会产生竞争关系(struts2中servlet默认为多例模式)。
# 危害性
全局变量的竞争会导致一个用户会看到其他用户的数据,包括订单、合同等私密信息,只要是单例servlet中的全局变量,都会产生此漏洞。
# 解决方案
- 【强制】显示配置servlet为多例模式:为controller添加@Scope("prototype")注释,将默认的单例模式改为多例,使用xml定义bean的情况,同样显示配置scope属性为prototype
- 【备选】单例servlet中不要设置全局变量,使用局部变量或者将变量封装
# API不恰当使用
# 表现形式
应用中使用的一些组件,比如:库文件、框架和其他软件模块等,如果这些组件有漏洞,且以最高权限运行,可以造成严重的数据泄露或完全控制服务器。
# 危害性
服务器组件里的后门,远程执行漏洞,反序列化漏洞等。
# 开发原则
- 【强制】开发框架及组件不能采用存在漏洞的组件:
- 原生反序列化,即ObjectInputStream.readObject 会触发的漏洞
- xml解析器对象重组,如xstream漏洞
- json解析器对象重组,如fastjson、jackson
- hessian黑名单类
# 解决方案
- 【建议】移除不使用的依赖,不需要的功能、组件和文档
- 【建议】利用工具如 versions、DependencyCheck、retire.js
- 【建议】等来持续的记录客户端和服务器以及它们的依赖库的版本信息
- 【建议】对使用的组件持续监控如CVE和NVD等漏洞中心,可以使用自动化工具来完成此功能
- 【建议】仅从官网渠道获取组件并且在有条件的情况下尽可能采用单一包来避免被恶意篡改的风险
- 【建议】很多老的不再支持的库和组件并没有安全升级,这种情况下,可以考虑使用虚拟补丁技术去检查
# 可参考文档
- 《应用安全管理规定》
- 《WEB开发安全基线》
- 《WEB应用安全架构威胁建模》
# 其他
- 无