安全建设之Web 开发安全

Author Avatar
xF0rk 4月 14, 2019

Web 应用系统从设计、开发到上线、运营是一个较为复杂的过程,通常包含需求分析、架构设计、系统设计、功能设计、编码实现、测试评估、上线部署、业务运营等关键步骤。本文将简化部分 Web 系统开发相关流程,主要从功能设计、编码测试、发布部署、系统运营四个环节进行简单的安全风险分析,同时针对各环节出现的安全风险提出一些简单的防御措施。

Web 开发过程

如上图所示,将 Web 系统开发过程简化为四个环节:

  • 功能设计,业务研发部门将对 Web 系统相关业务功能进行需求分析、设计,该阶段可能会引入功能逻辑漏洞,包括篡改类、验证码类、越权类漏洞等
  • 编码测试,开发、测试将对 Web 系统业务进行编码和功能测试,该阶段可能引入安全漏洞,包括第三方依赖包、开发框架或开发人员所编写的业务代码等
  • 发布部署,由运维人员将 Web 应用相关基础组件进行部署,该阶段可能由于运维人员的疏忽或一些不安全的配置可能会引入一些类似于弱口令、未授权访问等安全漏洞
  • 业务运营,由相关业务部门使用 Web 系统,该阶段由于 Web 系统对外提供服务,不可避免的需要面对外部的一些恶意流量,这也要求系统需要具有一定的“免疫”性

上述的 Web 开发过程中的四个环节,无论在哪一个环节都可能由于功能、需求变更,需回归、迭代到四个环节中的任意环节。

Web 应用防御

未知攻,焉知防,要想知道如何对 Web 应用系统进行安全防御需要先了解 Web 应用系统相关攻击面及漏洞原理,本节内容将简单介绍部分 Web 漏洞基本原理,并提出较简单的防御手法,实际的业务系统需根据的组件、技术栈,选取具体的安全防御方案

功能逻辑漏洞

通常研发或测试在业务编码实现过程中只关注正向(即强前端导向),在一定程度上忽略了异常数据类型校验,导致在业务功能上出现一些“奇妙”的功能漏洞,部分常见的逻辑漏洞如下图所示

篡改类漏洞

篡改类漏洞,通过篡改请求 Header、Cookie、请求参数来欺骗服务端应用,或通过篡改服务端响应来欺骗前端页面进行响应,通常表现为数量篡改、积分篡改、单价篡改、现金篡改、订单号篡改等,如下图所示

漏洞场景分析

常见的篡改类漏洞场景如下

  • 1 分钱支付任意订单
  • 0 元购买物品
  • 商品数量为 0 时仍可购买商品
  • 购买商品数量为负数
  • 提现金额为负数

篡改类漏洞本质是服务端过分依赖用户提交的数据,未根据业务特性对数据进行合理的检查。针对篡改类漏洞防御需要清晰理解业务功能,对业务数据进行合理校验检查。

验证码类漏洞

验证码,用于打破 Web 应用业务操作的可预测性,如上图所示,根据验证码出现形态不一样,可将验证码分为

  • 图形验证码
  • 行为式验证码
  • 口令验证码
  • 短信验证码
  • 令牌验证码

验证码可用于人机识别、人人识别

  • 人机识别,区分自动化扫描、爬虫、爆破等恶意行为
  • 人人识别,鉴别、确认操作者的身份,例如预设的短信验证码、口令验证码、令牌验证码等

漏洞场景分析

验证码类漏洞,指在使用验证码进行人机识别、人人识别过程中被绕过,导致识别功能失效。若某 Web 应用系统存在如下验证码业务场景,用户 A 可通过短信验证码,来进行某项业务处理

进行威胁分析的时,需忽略前端的页面相关功能,针对服务端接口及业务功能进行安全风险分析

如上图所示,针对不同的业务步骤,可能存在以下安全风险

  • 步骤 1
    • 频繁多次请求发送短信验证码,短信轰炸漏洞?
    • 手机号格式是否正确,是否符合群发手机格式?
  • 步骤 2
    • 响应内容是否包含短信验证码?
    • 短信验证码校验过程是否在前端页面进行校验?
  • 步骤 3
    • 验证码校验爆破是否可行?爆破空间有多大
    • 验证码验证成功或失败后是否立即销毁?
  • 步骤 4
    • 业务逻辑功能是否与验证码用途一致?
    • 响应的业务操作对象是否为用户 A?是否可为用户 B(非用户 A 本人)?
    • 是否可以直接跳过前 3 个步骤,直接进行步骤 4 ?

验证码类漏洞,需根据接口业务功能,进行严格的安全威胁建模分析,并针对不同的威胁提出合适的安全解决方案

越权类漏洞

越权类漏洞,指主体背离了业务系统中的应有(访问控制被绕过、缺失访问控制)访问控制,对客体进行了违规操作,如下图所示

根据越权表现形式不同,可将越权分为(不同越权类型数据流,已在上图用不同颜色进行标识)

  • 未授权访问,匿名用户可操作用户 A 的相关数据或信息
  • 水平越权,用户 A 可操作用户 B 的相关数据或信息
  • 垂直越权,用户 A 可操作管理员 C 的相关数据或信息

漏洞场景分析

若某 Web 应用系统中存在如下业务场景,用户 A 访问订单 A01 数据,服务端收到请求将 A01 数据响应

参照验证码类威胁分析过程,忽略前端页面功能,直接对服务端接口及业务功能进行安全风险分析

如上所示,针对不同的业务步骤,可能存在以下安全风险

  • 步骤 1
    • 用户若未登录能够进行此操作?
    • 用户 A 能够查询 B01(用户 B)、C01(用户 C) 等非个人订单?
    • 用户 A 除查询是否还有审批、支付等高权限操作?
    • 响应内容是否包含敏感信息或高于用户 A 权限的信息数据?

越权类漏洞,需根据接口业务功能,进行严格的权限控制,包括信息所属用户、所能执行操作、信息片段是否出现越权场景

框架编码漏洞

开发、测试人员在 Web 应用系统实施过程中会进行系统编码和功能测试,由于个人疏忽或误操作可能引入安全漏洞,其中包括第三方依赖包、开发框架或开发人员所编写的业务代码等,甚至某些恶意攻击者会攻击公司相关产品、系统供应链上游,来对目标公司实施间接攻击。

常规漏洞

Web 应用系统中常规漏洞如下图所示,包括注入、XSS、文件上传、文件包含、CSRF 等安全漏洞,本章节将针对性选取部分常规漏洞进行漏洞原理分析,同时提供基本的防御方案。目前部分开源框架在某些功能上进行了较好的封装,规避了部分安全漏洞,本章节主要介绍基本漏洞原理,侧重于 0 到 1 过程中可能出现的安全漏洞及对应的防御方案

以下章节将从客户端(即浏览器端)、服务端两个方向介绍几个常规漏洞及防御方案,

同源策略
Web 应用系统客户端大部分为浏览器端,并且随着客户端的业务功能越来越复杂,其所面对的安全风险点也越来越多。为约束客户端资源访问,浏览器会严格遵守同源策略约定。
同源策略用于限制不同源的 document 或脚本,对当前 document 读取或设置某些属性(如下表所示)。若无同源策略限制,则 A 站点的 JS 脚本在 B 站点未加载该脚本时可对 B 站点进行修改。

属性
HTTP 消息头
DOM 树
浏览器存储(Cookie、LocalStorage)

同源通常要求 HOST(IP或域名)、端口、协议一致,可通过下表判断是否与 http://www.xf0rk.space/ 同源

URL 是否同源
http://www.xf0rk.space/home/
https://www.xf0rk.space/
http://www.xf0rk.space:8080/
http://www1.xf0rk.space/
http://xf0rk.space/

默认不允许跨域访问,例如从 www.xf0rk.space 站点向 www1.xf0rk.space/?data=wwwpass,网站请求默认添加 Origin: http://www.xf0rk.space 头,只有站点明确返回头中包含 Access-Control-Allow-Origin: http://www1.xf0rk.space,才允许跨域访问,若设置 Access-Control-Allow-Credentials 为 true,则 Access-Control-Allow-Origin 不能设置成 *。

script、img、iframe、link 等标签可以跨域加载资源,不受同源策略限制,注意加载 javascript 文件域不重要,重点是加载 javascript 页面所在的域,ajax 严格遵守同源策略

Cookie 通常用于标识身份、Session 跟踪,其包含如下属性字段,可通过设置 Cookie 字段属性来限制 Cookie 读取传输方式

属性 备注
expires 过期时间,若未设置,则表示为内存型 Cookie(Session Cookie),否则为本地型 Cookie(Third-Party Cookie)
path 相对路径,默认为目标页面,使用 JS 可实现跨路径读取 Cookie,设置路径不能确保 Cookie 被盗取
domain 域名,默认为本域,本域及其子域可以读取 Cookie
HttpOnly 默认无,表仅通过 HTTP 协议传输,不能被脚本读取
Secure 默认无,表仅通过 HTTPS 协议传输

客户端安全之XSS 漏洞

漏洞原理分析

XSS 漏洞,跨站脚本攻击,指篡改页面中注入了 HTML 代码,插入恶意代码,在用户浏览网页时控制用户浏览器的攻击行为。

反射型 XSS
反射型 XSS 漏洞,即服务端只是将用户输入数据渲染返回到用户端,某服务端代码如下所示

<?php
  $input = $_GET["query"]
  echo "<div>".$input."</div>"
?>

若用户提交 query=<script>alert(1)</script>,则 Web 后端应用会在页面上渲染出如下 HTML,导致出现 XSS 漏洞

<div><script>alert(1)</script></div>

存储型 XSS
存储型 XSS 漏洞存储用户输入数据,每次从“存储”中读取渲染页面时,都会触发 XSS,某服务端代码如下所示

<?php
  $input = mysql_fetch_array($rs) // 从数据库读取
  echo "<div>".$input."</div>"
?>

若 Web 应用从数据库读取的数据为 <script>alert(1)</script>,则 Web 后端应用在页面上渲染出现如下 HTML,导致 XSS 漏洞

<div><script>alert(1)</script></div>

存储型 XSS 与反射型 XSS 不同,反射型 XSS 通常为“一次性”,而存储型 XSS 为“持久型”,其风险级别通常会更高

DOM XSS
DOM XSS 既可能是反射型 XSS 也可能是存储型 XSS,其命名与形成原因有关,某单页页面如下所示

<script>
  function test() {  
    var iStr = document.getElementById("text").value; // 读取 text 中值,进行DOM 渲染
    document.getElementById("t").innerHTML = "<a href='" + iStr + "'>test</a>";
  }
</script>

<div id="t"></div>
<input type="text" id="text" value="" />
<input type="button" id="s" value="write" onclick="test()" />

若用户输入' onclick=alert(1) //,则在前端页面渲染出现如下 HTML,导致 XSS 漏洞

<a href='' onclick=alert(1) //'>test</a>
漏洞基础防御

HttpOnly 加固
XSS 漏洞可用来窃取用户 Cookie 等,如下图所示,所以可以设置 Cookie 属性为 HttpOnly,禁止脚本读取 Cookie

若设置了 HttpOnly,攻击者仍可通过页面截图来窃取目标漏洞系统上的敏感信息,如下图所示

输入输出检查
XSS 漏洞源自用户不安全的输入,所以在防御 XSS 漏洞时,可对用户输入检查或输出渲染页面时进行输出检查,如下图所示

输入检查,即对用户输入内容进行检查,可分为黑、白名单:

  • 白名单,业务内容格式检查,例如生日、身份证号、手机号等;输入检查逻辑必须在服务端进行
  • 黑名单,过滤用户输入的特殊字符,但存在对内容语境理解不够准确

富文本处理,需过滤所有事件,同时采用白名单过滤形式

输出检查,将用户输入渲染到页面时进行转义,XSS 实质是 HTML 代码注入,在服务端对各种值为注入点进行针对性编码

  • HTML 标签,使用 HtmlEncode 编码
  • HTML 属性,使用 HtmlEncode 编码
  • SCRIPT 标签,使用 JavascriptEncode 编码
  • CSS 样式,使用 encodeForCSS 编码
  • 地址输出,确认地址以 HTTP(S)开头,验证地址格式有效性后,再进行 URLEncode 编码

输出检查转义需根据系统架构的前端框架选取与上述 5 个对应的转义方法函数进行转义,需注意各种输出标签位置必须与编码方法对应,否则输出检查转义将会失效

如上所示场景,输出目标为 HTML 中的属性,但是却采用了 JavascriptEncode,导致输出检查转义失败,仍存在 XSS 漏洞,XSS 漏洞如下图所示

正确的场景应选择 encodeForHTML 方法,如下所示

客户端安全之 CSRF

漏洞原理分析

CSRF,跨站点请求伪造,即当用户访问一个特定页面或链接时,在用户不知情的情况下被恶意发起某个请求的攻击行为。

若某业务系统如下链接用于给用户修改密码

http://testcsrf.xf0rk.space/changepasswd.jsp?newpass=123456&confirmpass=123456

若攻击者在某公共页面(例如某条动态或某条新闻)渲染时恶意添加如下 HTML IMG 标签时,则任意用户访问该公共页面时其个人密码会被自动修改成 123456,则表示存在 CSRF 漏洞。

<img src="http://testcsrf.xf0rk.space/changepasswd.jsp?newpass=123456&confirmpass=123456"/>

有的人可能会说密码修改业务请求方法为 POST ,IMG 只能发起 GET 请求,但是如果你后端的 JSP 代码如下所示,则其仍可读取 POST 和 GET 方法提交的参数,导致上述攻击场景仍然存在

String newpass = request.getParameter("newpass"); 
String confirmpass = request.getParameter("confirmpass");

CSRF 基础
通常可以把浏览器客户端的 Cookie 分为 Session Cookie(内存 Cookie)、Third-party Cookie(本地 Cookie),在浏览一个站点过程中,若网站设置了 Session Cookie,那么在同一个浏览器进程,若访问同源的站点,浏览器将会在后台自动发送 Session Cookie,即共用了 Session Cookie;而 Third-patry Cookie 在某些浏览器中会被阻止发送,如下图所示

由于同源站点共享了 Session Cookie,若后端服务器用 Session Cookie 来进行身份标识,则后端应用也会正常响应 IMG 发起的 GET 请求,导致伪造请求操作成功。

漏洞基础防御

在 CSRF 漏洞利用成功的一个关键点是参数可以被预测,如下所示

<img src="http://testcsrf.xf0rk.space/changepasswd.jsp?newpass=123456&confirmpass=123456"/>

为防护 CSRF 漏洞,需要移除、打破这种可预测性,如下

  • 关键操作验证码,newpass=&confirmpass=&code=[随机]
  • 增加交互业务功能,newpass=&confirmpass=&oldpass=[输入旧密码]
  • CSRF TOKEN,通常为框架自带 newpass=&confirmpass=&csrftoken=[自动]
  • Referer 校验

服务端安全之 SQL 注入

漏洞原理分析

SQL 注入,Web 应用系统在后端查询数据库时,直接将用户输入拼接到 SQL 查询语句,导致出现非预期的未授权的 SQL 数据库查询、操作行为。

若某业务系统后端数据库查询操作如下所示

String userid = requestData.get("userid");
String sql = "select * from users where userid = '" + userid + "'";

针对不同的输入,其拼接后的 SQL 查询语句如下所示,针对第一种提交输入,若 Web 应用服务端未将错误 try catch 则 Web 应用进行 SQL 查询时可在浏览器端可收到错误信息,即可判断是否存在 SQL 注入;若 Web 应用服务端捕获了 SQL 查询错误,则可通过提交后 4 种请求,通过响应时间、响应内容来判断是否存在 SQL 注入。

userid 拼接后 SQL 语句
' select * from users where userid = '''
'; drop table users-- select * from users where userid = ''; drop table users--'
0001' AND '1=1 select * from users where userid = '0001' AND '1=1'
0001' AND '1=2 select * from users where userid = '0002' AND '1=2'
0' AND SLEEP(6) AND ' select * from users where userid = '0' AND SLEEP(6) AND ''
漏洞基础防御

预编译语句

String sql = "select * from users where userid = ?";
PreparedStatement preparedStat = connection.prepareStatement(sql)
preparedStat.setString(1, userid)
ResultSet results = preparedStat.executeQuery()

存储过程

CallableStatement callableStat = connection.prepareCall("{call sp_getUsrInfo}")
callableStat.setString(1, userid)
ResultSet results =callableStat.executeQuery()

数据类型检查

正则检查 userid 字符格式,例如全为数字、无特殊符号
限制 userid 字符串长度
业务数据类型,例如手机号、邮箱等

数据库加固

最小权限原则,数据库、表读、写权限、自定义函数权限、读写本地文件权限等

服务端安全之文件上传漏洞

漏洞原理分析

文件上传漏洞,指用户绕过安全防护,上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。

若某业务服务器有如下的文件上传功能,用户可通过该接口上传图片

文件上传接口未对上传文件类型进行检查,导致可直接上传 PHP 文件

可利用上传的 PHP 文件直接执行命令、进行文件管理等

漏洞基础防御

以下内容将介绍几个防御及绕过方法,最后将介绍一个无风险的处理方案

进阶一

上传文件模块增加校验

  • 图片 Content-Type 类型校验,可直接修改 POST 请求中 Content-Type 值来实现绕过

进阶二

上传文件模块增加校验

  • 图片 Content-Type 类型校验,可直接修改 POST 请求中 Content-Type 值来实现绕过
  • 文件后缀检查,可通过 %00 截断绕过,仅在低版本 PHP 中生效
  • 简单图片格式校验,可在正常图片中替换部分内容为一句话木马,或在正常图片后拼接一个 PHP 文件

进阶三

上传模块增加校验

  • 图片 Content-Type 类型校验,可直接修改 POST 请求中 Content-Type 值来实现绕过
  • 文件后缀检查,可通过 %00 截断绕过,仅在低版本 PHP 中生效
  • 将上传图片文件重新读取绘制新的图片,写入到另外一个图片文件中,不可绕过

服务端安全之 SSRF

漏洞原理分析

SSRF(Server-side Request Forge, 服务端请求伪造),由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务。

若业务包含如下图所示功能,当用户在 ssrf_curl.php?url= 后添加一个图片的 URL 时,Web 应用会发起目标 URL 的请求,并将返回的图片响应至客户端

上述业务功能使用 PHP 实现代码如下所示

<?php
  $url = $_GET['url'];
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1)');
  // allow 302
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  $res = curl_exec($ch);
  // set content-type
  header('Content-Type: image/png');
  curl_close($ch) ;
  //return response
  echo $res;
?>

PHP 代码中直接通过 curl 来发起目标 URL 请求,并且没有对目标 URL 进行合理的检查,导致可发起除 HTTP 协议之外的其他请求,CURL 支持的协议如下所示

SSRF 之任意文件读取
如下可通过 file:// 读取目标主机任意文件

SSRF 之操作 Redis
如下可通过 dict:// 访问内网 Redis 信息

通过 SSRF 操作 Redis 写入定时任务,将目标主机 GetShell

写入定时反弹任务

目标机器触发定时任务,将 bash 反弹至攻击机器上,导致 getshell

漏洞基础防护
http:192.168.56.101/ssrf_curl.php?url=http://l0gs.xf0rk.space/images/logo.jpg

SSRF 漏洞思路为通过 CURL 请求一个图片,由于 CURL 支持协议过多、URL 目标不可控,所以为防御 SSRF 漏洞,需要确保目标 URL 可控,可从协议、目标两个方向进行控制

协议控制
根据业务需求,限制 CURL 所能协议,可通过白名单形式来过滤

dict
file
ftp
ftps
gopher
http
https
imap
imaps
ldap
ldaps
pop3
pop3s
rtmp
rtsp
smb
smbs
smtp
smtps
telnet
tftp

目标控制
目标控制可采用白名单和黑名单策略,白名单只需指定能够访问的 URL,控制简单有效,若使用黑名单,控制 URL 目标容易被绕过,绕过主要指通过 URL特性、302 跳转、IP 转换等绕过目标黑名单,部分绕过如下

  • URL 特性,http://[email protected]/ => http://www1.xf0rk.space
  • 进制转换 http://3232235777/ => http://192.168.1.1
  • URL特性 www.xf0rk.space%2E%62%61%69%64%75%2E%63%6F%6D%0D%0A => www.xf0rk.space.a.cn
  • 短网址 http://dwz.cn/11SMa >>> http://127.0.0.1/
  • 域名解析 http://127.0.0.1.attack.io/ => http://127.0.0.1/
  • 302跳转 http://127.0.0.1.attack.io/ => http://127.0.0.1/
  • IPV6 => IPV4

服务端安全之命令注入

漏洞原理分析

在 SSRF 的例子中,通过 PHP 中的 CURL 模块来实现实际的业务功能,若直接通过调用 CURL 命令来实现的话,需注意可能存在命令注入漏洞,如下所示

<?php
  $url = $_GET['url'];
  exec("curl ".$url)
  ....
?>

命令注入请求如下,当 Web 处理完用户请求后,目标系统则成功创建 test 用户

http:192.168.56.101/ssrf_curl.php?url=http://l0gs.xf0rk.space/images/logo.jpg;useradd test
漏洞基础防护

命令注入本质是由于未安全过滤用户输入,导致 Web 应用未授权执行了用户恶意构造的命令,所以 Web 应用处理用户输入应注意

  • 采用白名单或正则表达式对用户输入进行过滤
  • 不让用户直接控制 eval、system、exec、shell_exec 等敏感函数
  • 进入执行命令函数和方法前,对变量进行过滤,对敏感字符进行转义

框架漏洞

在 Web 应用系统开发过程中,会使用一些开源的前端、后端框架,来实现快速、规范开发。在选用实际的框架时,需对框架进行安全评估,以防止出现安全漏洞,把一些不需要安全风险引入到业务系统中。

开源框架漏洞

针对开源框架,需要业务实际使用需求,及时检查框架是否是漏洞版本,若框架版本存在漏洞,及时将框架升级到最新无漏洞版;同时在使用框架时,需要定义一些安全编码规范,避免由于框架配置导致目标框架存在漏洞。

SPRING 后端框架漏洞

2018年4月5日,Pivotal Spring 官方发布安全公告,Spring 中存在三个安全漏洞。CVE-2018-1270 漏洞是指 Spring 框架中通过 spring-messaging 模块来实现 STOMP(Simple Text-Orientated Messaging Protocol),STOMP 是一种封装 WebSocket 的简单消息协议。攻击者可以通过建立 WebSocket 连接并发送一条消息造成远程代码执行。

如下图所示,启动 Spring STOMP 服务

Spring 使用了 STOMP 功能模块,导致服务器可远程执行命令,如下所示

ANGULAR 前端框架漏洞

ANGULAR 前端框架已经做了较好的安全防护,但若使用过程中,误用了某些功能,则可能导致自身业务系统存在安全漏洞。官方文档中提出了一些安全建议

  • 及时把 Angular 包更新到最新版本
  • 不要修改你的 Angular 版本
  • 谨慎使用不安全的方法,以下几个方法分别与 XSS 防护中的几个输出检查方法相对应
    • bypassSecurityTrustHtml
    • bypassSecurityTrustScript
    • bypassSecurityTrustStyle
    • bypassSecurityTrustUrl
    • bypassSecurityTrustResourceUrl
  • 不在服务端拼接模版语言

误用不安全的 bypass 方法
如下,this.dangerousUrl 在渲染过程会被 Angular 自动安全转义,this.trustedUrl 开发人员在代码实现过程中过于信任其安全性,直接在页面 HTML 中渲染调用 bypassSecurity 方法

渲染的页面源码如下所示

this.dangerousUrl 在页面中被自动安全转义未触发 XSS 漏洞

this.trustedUrl 开发人员调用了 bypassSecurity 方法,导致渲染的前端页面存在 XSS 漏洞

JAVA 反序列化执行

JAVA 序列化及反序列化

如下图所示,JAVA 代码中定义了 Person 类,其通过 Fastjson 框架实现了序列化及反序列化两个操作

  • 序列化,将 person java object 对象转化成字符串
  • 反序列化,将字符串转化成 personObj java object对象

参考 Person 类序列化及反序列化思路,重新创建一个 Poc 类,实现在 Java 代码中初始化时执行弹出计算器的命令,代码如下图所示

初始化 Poc 对象时,触发命令执行,弹出计算器

上述代码在初始化 Poc 类时,可指定弹出计算器命令,如果将 Poc 在内存中的 Java Object 对象序列化成字符串,然后再执行反序列化操作,能够成功执行弹出计算器命令?答案是可以的!!!!

JAVA 反序列化 RCE

JAVA 反序列化 代码 如下所示,其代码逻辑为

  • 编译 Poc 代码,输出到 Poc.class 文件
  • 读取 Poc.class 文件内容,通过 TemplatesImpl 类构造反序列化所需的字符串
  • 调用 Fastjson 反序列化

在 Fastjson 反序列化恶意构造字符串时,执行了在 Poc 初始化函数中所定义的命令(弹出计算器)

反序列化 RCE JAR 包

2017年3月15日,Fastjson 官方主动爆出 Fastjson 在1.2.24及之前版本存在远程代码执行高危安全漏洞,攻击者可以通过此漏洞远程执行恶意代码来入侵服务器。

以下代码测试模拟的是 Fastjson 框架反序列化 RCE 漏洞,除了 Fastjson 还有大量的 Java Jar 第三方包都存在反序列化漏洞,如下图所示

如下为利用 Apache Common Collection 反序列化漏洞反弹 Shell 的利用截图

框架漏洞检测

Java 框架漏洞检测可使用 OWASP 的 dependency-check 工具,使用其检测上述 Fastjson 项目如下图所示

应用依赖包检测报告中指出 fastjson-1.2.24.jar 存在严重安全漏洞

安全漏洞编号为 CVE-2017-18349 ,允许攻击者通过发送恶意的 JSON,当应用通过 Fastjson 反序列化字符串时,可远程执行命令

供应链安全

软件供应链是指在企业应用系统开发、应用系统交付、应用系统形成的一个整体的链结构。

  • 应用系统开发,软硬件环境、开发工具、第三方库、软件开发实施过程,包括需求分析、设计、实现和测试等,软件产品在应用系统开发环节形成最终用户可用的形态
  • 应用系统交付,用户通过在线商店、免费网络下载、购买软件安装存储介质、资源共享等方式获取软件产品过程
  • 应用系统形成,使用软件产品的整个生命周期,包括软件升级、维护等过程

由于在一个灰色的软件供应链中,上游开发者总是在处心积虑引入恶意代码,企业在系统研发、测试、运营过程需关注供应链各个环节安全风险。在研发编码过程中,需建立一个可信的开发环境包括

  • 不无条件大量信任第三方包、框架与源,外部基础组件,由于外部组件、第三方包等其在开发、分发环节存在被攻破篡改的风险
  • 在二次开发和定制的基础组件过程中,需注意二次开发不止可能引入碎片化、历史漏洞问题,还可能让代码失去一致性安全保证
  • 明确 Ctrl-C 和 Ctrl-V 引入的外部威胁,由 GitHub 等公开代码借鉴而来的情况在开发实践中不可避免,如果存在蓄意发布的暗藏恶意的代码可能被直接引入
  • 避免大量人员流动,快速迭代中人员流动,一方面不利于代码规范的维持,一方面也引入了“人”本身的不确定因素

不安全的 PYTHON 依赖库

如下图所示,通过引入恶意的 string 库,在库 import 过程,会直接输出 Test hook in current path

如下为引入恶意 python 库的某业务 Web 应用系统,只要攻击者请求 ?cmd= 即可直接在 Web 服务器执行任意命令

不安全的 DOCKER 镜像

2017 年 5 月,DockerHub(Docker 官方镜像仓库)用户 docker123321 注册成功,并相继创建了多个恶意 Docker 镜像

恶意 Docker Tomcat 镜像如下图所示,在 Docker 启动后其会触发一个 Shell 反弹至 98.142.140.13 的 8888 端口

供应链攻击案例

在 360 威胁情报文章 “ 软件供应链来源攻击分析报告 ” 中,披露了在软件开发环节、交付环节、使用环节多个攻击场景及案例。

部署配置漏洞

常见的配置漏洞如上图所示,弱口令或空口令等部分部署配置漏洞在上文漏洞介绍已经有进行了针对性介绍及利用,下文将主要介绍几个未授权访问漏洞

Docker 未授权访问

Docker daemon 默认是监听在 unix socket 上的,如 unix:///var/run/docker.sock,官方还提供一个 Rustful Api 接口,允许通过 TCP 远程访问 Docker。可通过执行以下dockerd -H=0.0.0.0:2375 -H unix:///var/run/docker.sock 让 Docker 监听在本地所有地址的 2375 端口上。

如下扫描发现 172.17.0.1 开放端口 2375 端口为 Docker Remote Api 端口

通过 Docker Remote Api 查看目标宿主机有什么镜像、运行容器

创建容器,设置容器启动命令为反弹 Shell 命令

反弹获取 Docker 宿主机 Shell

K8S 未授权访问

K8S(Kubernetes) 是一个跨主机集群的 开源的容器调度平台,它可以自动化应用容器的部署、扩展和操作 , 提供以容器为中心的基础架构。

K8S 在创建应用页面可指定创建 Docker 容器所能使用的命令,如下图所示,可将宿主机根目录挂载至 Docker 容器中,通过在宿主机定时任务目录下写入定时任务,来 GetShell

同样也可直接通过 YAML 文件指定 K8S 容器配置,如下所示

Hadoop 未授权访问

Hadoop Yarn 提供有默认开放在 8088 和 8090 的 REST API(默认前者)允许用户直接通过 API 进行相关的应用创建、任务提交执行等操作,如果配置不当,REST API 将会开放在公网导致未授权访问。

如下图通过构建 workcount 测试用例,在测试用例中将 Hadoop Yarn Shell 反弹

如下图所示为成功反弹 GetShell

漏洞安全防护

关于 Web 应用系统安全防护,目前开源方案较多的是 WAF(Web Application Firewall) 和 RASP(Runtime Application Self-Protection),如下图所示

  • WAF,门卫模型,通常根据用户请求数据来进行攻击检测,开源项目有代表性的为 ModSecurity
  • RASP,管家模型,通常根据处理响应 Web 应用请求后与系统、数据库等相关交互行为特征来进行攻击检测,开源项目有代表性的为 百度 RASP

WAF

WAF,门卫模型,通常部署在 Web 应用系统的外部边界,所有正常或恶意流量都需要通过特征规则和模式识别,WAF 拒绝向高风险的 Web 请求提供服务。WAF 特征规则和模式需要频繁、及时升级,但通常仍存在误报率高、更新不及时问题。

WAF 防御原理

后面介绍的 WAF 防护原理介绍都是通过 ModSecurity WAF 来开展的,文章中 ModSecurity WAF 使用攻击评分模式,即当入站或出站超过设定的阈值,则拒绝为攻击用户提供服务。如下图为正常请求时 Web 应用系统响应的内容

如下图所示,当用户请求 <script>alert(1)</script>,用户收到的响应与上图正常请求不同,即已经被识别成攻击行为而拒绝提供服务。

根据 ModSecurity WAF 日志可以看出该 HTTP 请求入站请求的风险评分过高,导致请求被拒绝服务

在下图中可以看出,其连续触犯了多条 XSS 检测规则

ModSecurity WAF 在进行安全防护时会从下图所示的几个属性进行风险评估,包括

  • HTTP 请求参数、Header、UA、请求 Body 等
  • HTTP 响应内容等

WAF 规则编写

“假装”测试 Fastjson 反序列化 RCE 请求(后端应用反序列化操作未实现,所以响应的为 404),未添加 Fastjson 防护规则的 ModSecurity 无法阻止此攻击请求,如下图所示

新增 Fastjson 防护规则 932140,如下图所示,即检查请求参数中是否包含 @type 字段,若存在,则判定为攻击行为

新增防护规则后的 ModSecurity 防护成功,目标请求被拒绝服务

查看 ModSecurity 防护日志,其入站请求安全风险值太高,被拒绝服务

分析更具体的拦截请求,发现攻击请求被新增的 932140(上述操作添加的防护规则) 拦截成功

RASP

RASP,管家模型,一种新型应用安全防护技术,直接将防护引擎嵌入到应用内部,能够感知应用上下文;其在执行层面分析敏感函数是否被调用,在应用程序内部基于调用栈调用检测模型阻断攻击,误报率相对较低、绕过难度也较大。

如下图所示,在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 –javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序,动态修改 Java 代码插入攻击检测功能逻辑代码,测试代码

指定 应用启动时加载 javaopenrasp.jar javaagent 应用

如下所示,为相关检测模块输出及拦截日志

RASP 防御原理

在 premain 模块中,读取 RASP 配置文件,增加 transformer 插桩

根据配置文件中的所配置的 Hook 类,增加 Hook 代码

修改 Hook 的类,增加 RASP 过滤、检测模块

过滤、检测模块支持拦截、白名单、黑名单、记录模式

使用如上所示防护配置后,RASP 防护拦截日志如下所示,Fastjson RCE 操作被成功拦击,实现 “0day” 级别的安全防护

Web 安全过程

Web 安全过程需要在 Web 开发过程各环节中结合 Web 应用防御中介绍的风险点,进行持续、迭代评估,降低目标 Web 系统的风险面,提高整体项目的安全基线,增大攻击门槛。