codeql php,使用codeql 挖掘 ofcms

203674

前言

网上关于codeql的文章并不多,国内现在对codeql的研究相对比较少,可能是因为codeql暂时没有中文文档,资料也相对较少,需要比较好的英语功底,但是我认为在随着代码量越来越多,传统的自动化漏洞挖掘工具的瓶颈无法突破的情况下,codeql相当于是一种折中的办法,通过codeql的辅助,来减少漏洞挖掘人员的工作,更加关注漏洞的发现和利用过程

之所以选ofcms,是因为有p0desta师傅之前的审计经验,而且使用codeql审计cms尚属第一次,所以选用了ofcms审计

ql构造

在ql中,漏洞挖掘是根据污点追踪进行的,所以我们需要知道我们的挖掘的cms的source点在哪里,sink点在哪里,相对来说,source点比较固定,一般就是http的请求参数,请求头这一类的

但是sink比较难以确定,由于现在的web应用经常使用框架,有些文件读取,html输出其实是背后的框架在做,所以这就导致了我们的sink定义不可能是一成不变的,要对整个web应用有一个大致的了解,才能定义对应的sink

source点的ql

source点很清楚,对于一个web应用来说,http请求参数,http请求头,我们关注ofcms中对请求参数的获取方式:

ofcms使用了jfinal这个框架,而ofcms继承了jfinal的controller来获取参数,在整个ofcms中大体有三种类型来获取请求参数:

BaseController

203674

Controller(Jfinal提供)

203674

ApiBase

203674

所以我们的source都是根据这几个类展开的,在观察这几个类之后很容易发现,所有的获取http参数的方法都是getXXX()这样的命名方式,所以我们可以这样定义source的ql语法:

class OfCmsSource extends MethodAccess{

OfCmsSource(){

(this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.admin.controller", "BaseController") and

(this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("com.jfinal.core", "Controller") and

(this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("javax.servlet.http", "HttpServletRequest") and (this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.api", "ApiBase") and

(this.getMethod().getName().substring(0, 3) = "get"))

}

}

到这一步,我们的source就算定义完了,接下来就是定义对应的sink了

sink点的ql

相对于source的固定,sink就很不固定了,常见的web漏洞一般来说都可以作为sink,而且因为框架的不同,同一种漏洞在不同框架下的ql都是不一样的,所以我们需要略微分析一下整个web应用在做文件读取,模版渲染等操作的时候一般都用的是什么方法

模版渲染的问题

Jfinal中对模版渲染有一系列的render方法:

203674

可以看到,所有都是render开头,所以我们对方法名的判断很简单,截取前面6个字符,判断是否为render,随便找一个项目使用render的地方,可以发现render其实是在com.jfinal.core.Controller里面定义的方法,所以现在我们唯一确定了模版渲染的方法,所以我们的sink也就呼之欲出了,也就是这些render方法的参数,所以构造ql:

class RenderMethod extends MethodAccess{

RenderMethod(){

(this.getMethod().getDeclaringType*().hasQualifiedName("com.jfinal.core", "Controller") and

this.getMethod().getName().substring(0, 6) = "render") or (this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.core.plugin.freemarker", "TempleteUtile") and this.getMethod().hasName("process"))

}

}

在上面的ql中我添加了TempleteUtile这个类,因为这个类的process第一个参数可控的话也会造成模版的问题,所以我们可以随时去到ql中添加我们认为可能出现问题的模版渲染方法

文件类的问题

在ofcms中,文件的创建一般都是new File()这种形式创建的,所以我们的sink点应该为new File的参数为我们的sink点,所以构造ql:

class FileContruct extends ClassInstanceExpr{

FileContruct(){

this.getConstructor().getDeclaringType*().hasQualifiedName("java.io", "File")

}

}

污点追踪

codeql提供了几种数据流的查询:

local data flow

local taint data flow

global data flow

global taint data flow

local data flow基本是用在一个方法中的,比如想要知道一个方法的入参是否可以进入到某一个方法,就可以用local data flow

global data flow是用在整个项目的,也是我们做污点追踪用的最多的

简单解释一下taint和非taint有什么区别:taint的dataflow会在数据流分析的基础上加上污点分析,比如

String a = "evil";

String b = a + a;

在使用taint的dataflow中,b也会被标记为被污染的变量

构造configure

class OfCmsTaint extends TaintTracking::Configuration{

OfCmsTaint(){

this = "OfCmsTaint"

}

override predicate isSource(DataFlow::Node source){

source.asExpr() instanceof OfCmsSource

}

override predicate isSink(DataFlow::Node sink){

exists(

FileContruct rawOutput |

sink.asExpr() = rawOutput.getAnArgument()

)

}

}

当我们需要去做污点分析的时候,我们需要继承TaintTracking::Configuration这个类,来重写两个方法isSource和isSink,在这里,dataflow中的Node节点和我们直接使用的节点是不一样的,我们需要使用asExpr或者asParamter来将其转换为语法节点

这里可以看到,我们的source为我们之前定义的http参数的输入地方,sink为我们之前定义的new File的这种实例化

结果分析

codeql只能给出从source到sink的一条路径,但是这条路径中的一些过滤和条件是无法被判断的,这也就需要一部分的人工成本,让我们来运行一下我们刚刚写的ql:

import ofcms

from DataFlow::Node source, DataFlow::Node sink, OfCmsTaint config

where config.hasFlow(source, sink)

select source, sink

最后的查询结果:

203674

可以看到找到了11个可能存在问题的地方,我们来依次看一看是否有问题:

ReprotAction

第一个在ReprotAction这个类的expReport方法中:

203674

可以很明显看到,在获取j参数之后,对jrxmlFileName没有任何的校验,导致我们可以穿越到其他目录,但是文件后缀名必须为jrxml,而且在JasperCompileManager的compileReport函数中,对xml文档没有限制实体,导致可以造成XXE漏洞,这里很尴尬的利用点是:

需要一个文件上传

后缀名必须为jrxml

TemplateController

在TemplateController这个类的getTemplates方法中:

203674

在这里对获取的参数没有任何的校验,导致可以跨越目录列文件并且修改文件,但是在后面的实现中,我们只能修改和查看特定的文件

203674

假设我们在tmp目录下有着a.html和a.xml文件,我们可以跨越到tmp目录下读取并修改这两个文件

203674

TemplateController

还有一个地方就是save函数,这个函数在p0desta师傅的博客中也挖掘出了任意文件上传漏洞:

203674

很明显的一任意文件上传,文件名,路径,文件内容全部可控,直接getshell

剩下的一个并不能造成影响,就不多说了

后记

在render的sink定义中,如果运行可以发现很多地方的前台的一个小问题,也就是我们可以指定模版文件,ofcms使用了freemarker模版引擎,如果可以包含到我们自定义的模版文件,即可导致RCE,但是并没有发现有一个文件上传的点可以上传文件到模版目录下(除了上面的一个任意文件上传),所以不太好前台RCE

顺手测了下发现前台评论地方有存储XSS,但是和codeql无关就不多说了

整个ql:

ofcms.qll

import java

import semmle.code.java.dataflow.TaintTracking

class OfCmsSource extends MethodAccess{

OfCmsSource(){

(this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.admin.controller", "BaseController") and

(this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("com.jfinal.core", "Controller") and

(this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("javax.servlet.http", "HttpServletRequest") and (this.getMethod().getName().substring(0, 3) = "get"))

or

(this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.api", "ApiBase") and

(this.getMethod().getName().substring(0, 3) = "get"))

}

}

class RenderMethod extends MethodAccess{

RenderMethod(){

(this.getMethod().getDeclaringType*().hasQualifiedName("com.jfinal.core", "Controller") and

this.getMethod().getName().substring(0, 6) = "render") or (this.getMethod().getDeclaringType*().hasQualifiedName("com.ofsoft.cms.core.plugin.freemarker", "TempleteUtile") and this.getMethod().hasName("process"))

}

}

class SqlMethod extends MethodAccess{

SqlMethod(){

this.getMethod().getDeclaringType*().hasQualifiedName("com.jfinal.plugin.activerecord", "Db")

}

}

class FileContruct extends ClassInstanceExpr{

FileContruct(){

this.getConstructor().getDeclaringType*().hasQualifiedName("java.io", "File")

}

}

class ServletOutput extends MethodAccess{

ServletOutput(){

this.getMethod().getDeclaringType*().hasQualifiedName("java.io", "PrintWriter")

}

}

class OfCmsTaint extends TaintTracking::Configuration{

OfCmsTaint(){

this = "OfCmsTaint"

}

override predicate isSource(DataFlow::Node source){

source.asExpr() instanceof OfCmsSource

}

override predicate isSink(DataFlow::Node sink){

exists(

FileContruct rawOutput |

sink.asExpr() = rawOutput.getAnArgument()

)

}

}

test.ql

import ofcms

from DataFlow::Node source, DataFlow::Node sink, OfCmsTaint config

where config.hasFlow(source, sink)

select source, sink

不足

感觉一个很大的问题是sink的定义,因为框架的变换以及一些开发者自己的工具类,以及一些漏洞可能根本不存在,导致sink的定义有时候挖不出来漏洞

像p0desta师傅测的CSRF漏洞,暂时想不到有什么好的办法来定义sink,人工可能很好去看出来,但是不好用codeql语言定义这种漏洞

太菜了,有个点的任意文件读取写不出来ql,2333

203674

师傅们教教我

感觉在定义的时候要尽量找共性,但是也不能找太深

参考文章:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 连接符.,PHP怎么在数字之间添加连接符

PHP实现数字之间添加连接符,我们可以通过PHP中的for循环思想来实现。这里的连接符指的是“-”符号。推荐参考:《PHP教程》那么对于新手来说,可能有一定难度。下面我们就通过简单的代码示例,给大家介绍PHP给数字之间添加连字符的实…

嵌入式linux 时间同步,解决嵌入式Linux中的时区问题

如果说让我做上层软件的工作,我做起来可以得心应手,但是让我做平台方面的工作(系统问题解决、驱动编写、软件移植等工作),确实不熟悉。所以很多问题都是摸着石头过河,没有经验。许多问题在有经验的朋友那里是小菜一碟,…

bzoj2243

2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6753 Solved: 2496[Submit][Status][Discuss]Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1、将节点a到节点b路径上所有点都染成颜色c; 2、询问节点…

eclipse linux windows 乱码,Ubuntu下Eclipse打开Windows下的工程文件乱码解决办法

Eclipse在Windows下默认使用的是GBK(包括GB2312)编码,而在Linux系统默认使用的是UTF-8编码,并且eclipse编码设置下拉列表不提供GBK编码可选项。如果eclipse打开工程或者文本乱码,基本可以肯定(因为常用的就这两种)这个工程/文本使用的是GBK编…

linux桌面旋转了180度,[多图]回顾每一款默认Ubuntu壁纸

每个默认的Ubuntu壁纸Ubuntu 4.10’Warty Warthog’当人们抱怨Ubuntu发行版中的“ 褐色 ”时,我经常想回到Ubuntu的第一张墙纸,以便他们的意见可以转变为“上下文”。事后看来,这只墙纸完全是一块毫无生气的带有徽标的棕色块。当然&#xff0…

【转】Apache 配置虚拟主机三种方式

Apache 配置虚拟主机三种方式 原文博客http://www.cnblogs.com/hi-bazinga/archive/2012/04/23/2466605.html一、基于IP 1. 假设服务器有个IP地址为192.168.1.10,使用ifconfig在同一个网络接口eth0上绑定3个IP: [rootlocalhost root]# ifconfig eth0:1 1…

linux weblogic 防火墙,本地访问weblogic控制台无反应,关闭linux操作系统防火墙

有时候,我们在Linux操作系统上成功启动了weblogic,也查看了7001端口的状态是开启的。但是访问weblogic控制台没有反应,也没有报错。使用 netstat -ano | grep 7001 查看端口的状态可是访问weblogic控制台,还是没有反应。我们在本地…

fedora linux搜狗输入法,在Fedora 28系统下安装搜狗输入法

以下介绍在Fedora 28系统下安装搜狗输入法,也适用在Fedora 27下的安装,亲测可以。先声明一下,在Fedora 27及以后版本中出现的输入框候选词界面变形但不影响使用。第一步:安装fzug软件源具体方法如下:1.添加 FZUG 源Fed…

linux reboot命 过程,IDRAC安装dell服务器操作系统(linux or windows),用到生命周期管理器...

1、首先给服务器装上idrac模块,然后给idrac配置一个远程IP,用作管理2、在web界面输入IP,弹出以下界面,输入账号密码登录3、认证成功后,点击虚拟控制台启动4、进入如下界面,点击菜单栏的《虚拟介质》&#x…

DroidPlugin插件化开发

360手机助手使用的 DroidPlugin,它是360手机助手团队在Android系统上实现了一种插件机制。它可以在无需安装、修改的情况下运行APK文件,此机制对改进大型APP的架构,实现多团队协作开发具有一定的好处。 它是一种新的插件机制,一种免安装的运行…

io wait linux,另辟蹊径-诊断工具之 IO wait

导读最近在做日志的实时同步,上线之前是做过单份线上日志压力测试的,消息队列和客户端、本机都没问题,但是没想到上了第二份日志之后,问题来了:1、问题:集群中的某台机器 top 看到负载巨高,集群…

Oracle第二天

Oracle第二天 整体安排(3天) 第一天:Oracle的安装配置(服务端和客户端),SQL增强(单表查询)。 第二天:SQL增强(多表查询、子查询、伪列-分页)&…

linux搭建虚拟化平台报告,部署KVM虚拟化平台------搭建(示例代码)

一 、部署KVM虚拟化平台hyper-v是windows中的虚拟化1、KVM模块直接整合在Linux内核中,kvm是内核模块,虚拟机与kvm模块之间为管理工具2、KVM组成1.KVM Driver---虚拟机创建---虚拟机内存分配---虚拟CPU寄存器读写---虚拟CPU运行2.QEMU (经过简化与修改)--…

linux 选择文件指定的行数据类型,06练习题

1.如何删除一个非空子目录/tmp? BA. del /tmp/*B. rm -rf /tmpC. rm -Ra /tmp/*D. rm -rf /tmp/*2.存放linux默认系统日志文件是 BA./var/log/dmesg #系统启动时日志B./var/log/messages #系统日志C./var/log/secure #登录相关 安全3.用命令ls -l显示出来文件txt的描…

C#多线程编程

C#多线程编程 一、使用线程的理由 1、可以使用线程将代码同其他代码隔离,提高应用程序的可靠性。 2、可以使用线程来简化编码。 3、可以使用线程来实现并发执行。 二、基本知识 1、进程与线程:进程作为操作系统执行程序的基本单位,拥有应用程…

《DSP using MATLAB 》示例Example6.3

代码: C0 0; B1 [2 4; 3 1]; A1 [1 1 0.9; 1 0.4 -0.4]; B2 [0.5 0.7; 1.5 2.5; 0.8 1]; A2 [1 -1 0.8; 1 0.5 0.5; 1 0 -0.5]; [b1, a1] par2dir(C0, B1, A1)[b2, a2] par2dir(C0, B2, A2)b conv(b1, b2) % Overall direct form numerator a conv(a1…

简单说明c语言程序步骤,C语言的入门简介和三个简单的C语言程序详细说明

学习一种编程语言,最重要的是建立一个练习环境,边学边练才能学好。Keil软件是目前最流行开发80C51系列单片机的软件,Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成…

java入门,学习笔记

编译 通过javac编译java程序,会编译出一个后缀为class的文件,我们再通过java虚拟机(jvm)执行编译后的java程序。 在java中始终有一个main函数,它作为程序的入口,程序从这个入口开始执行一直到结束。 public…

linux命令之ifconfig详细解释

依赖于ifconfig命令中使用一些选项属性,ifconfig工具不仅可以被用来简单地获取网络接口配置信息,还可以修改这些配置。 1.命令格式: ifconfig [网络设备] [参数] 2.命令功能: ifconfig 命令用来查看和配置网…

loadrunner controller:实时查看VUser的运行情况

1) 如下图,在Run标签页,点击“Vusers...”打开Vuser窗口; 2) 如下图选中一个Vuser点击按钮可以打开Run-Time Viewer窗口,RTV窗口页面显示的就是该Vuser当前的操作; 3) 如下图所示,…