安全RCE之未授权访问分析

白癜风微信群 http://cgia.cn/news/chanye/1663488.html
前言

安全研究员vakzz于4月7日在hackerone上提交了一个关于gitlab的RCE漏洞,在当时并没有提及是否需要登录gitlab进行授权利用,在10月25日该漏洞被国外安全公司通过日志分析发现未授权的在野利用,并发现了新的利用方式。根据官方漏洞通告页面得知安全的版本为13.10.3、13.9.6和13.8.8。本篇将复现分析携带恶意文件的请求是如何通过gitlab传递到exiftool进行解析的

gitlab介绍

GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。

1、份很多已经买不到的绝版电子书2、30G安全大厂内部的视频资料3、份src文档4、常见安全面试题5、ctf大赛经典题目解析6、全套工具包7、应急响应笔记8、网络安全学习路线

可以看到在gitlab的组成中包含的各种组件,可以通过两个关键入口访问,分别是HTTP/HTTPS(TCP80,)和SSH(TCP22),请求通过nginx转发到Workhorse,然后Workhorse和Puma进行交互,这里我们着重介绍下通过Web访问的组件GitLabWorkhorse。

Puma是一个用于Ruby应用程序的简单、快速、多线程和高度并发的HTTP1.1服务器,用于提供GitLab网页和API。从GitLab13.0开始,Puma成为了默认的Web服务器,替代了之前的Unicorn。而在GitLab14.0中,Unicorn从Linux包中删除,只有Puma可用。

GitLabWorkhorse介绍

GitLabWorkhorse是一个使用go语言编写的敏捷反向代理。在gitlab_features说明中可以总结大概的内容为,它会处理一些大的HTTP请求,比如文件上传、文件下载、Gitpush/pull和Git包下载。其它请求会反向代理到GitLabRails应用。可以在GitLab的项目路径lib/support/nginx/gitlab中的nginx配置文件内看到其将请求转发给了GitLabWorkhorse。默认采用了unixsocket进行交互。

这篇文档还写到,GitLabWorkhorse在实现上会起到以下作用:

理论上所有向gitlab-Rails的请求首先通过上游代理,例如NGINX或Apache,然后将到达gitlab-Workhorse。

workhorse能处理一些无需调用Rails组件的请求,例如静态的js/css资源文件,如以下的路由注册:

u.route(  "",`^/assets/`,//匹配路由//处理静态文件  static.ServeExisting(    u.URLPrefix,    staticpages.CacheExpireMax,    assetsNotFoundHandler,  ),  withoutTracing(),//Tracingonassetsisverynoisy)

workhorse能修改Rails组件发来的响应。例如:假设你的Rails组件使用send_file,那么gitlab-workhorse将会打开磁盘中的文件然后把文件内容作为响应体返回给客户端。

gitlab-workhorse能接管向Rails组件询问操作权限后的请求,例如处理gitclone之前得确认当前客户的权限,在向Rails组件询问确认后workhorse将继续接管的请求,如以下的路由注册:

u.route("GET",gitProjectPattern+`info/refs\z`,git.GetInfoRefsHandler(api)),u.route("POST",gitProjectPattern+`git-upload-pack\z`,contentEncodingHandler(git.UploadPack(api)),withMatcher(isContentType("application/x-git-upload-pack-request"))),u.route("POST",gitProjectPattern+`git-receive-pack\z`,contentEncodingHandler(git.ReceivePack(api)),withMatcher(isContentType("application/x-git-receive-pack-request"))),u.route("PUT",gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`,lfs.PutStore(api,signingProxy,preparers.lfs),withMatcher(isContentType("application/octet-stream")))

workhorse能修改发送给Rails组件之前的请求信息。例如:当处理GitLFS上传时,workhorse首先向Rails组件询问当前用户是否有执行权限,然后它将请求体储存在一个临时文件里,接着它将修改过后的包含此临时文件路径的请求体发送给Rails组件。

workhorse能管理与Rails组件通信的长时间存活的websocket连接,代码如下:

//Terminalwebsocket    u.wsRoute(projectPattern+`-/environments/[0-9]+/terminal.ws\z`,channel.Handler(api)),    u.wsRoute(projectPattern+`-/jobs/[0-9]+/terminal.ws\z`,channel.Handler(api)),

使用ps-aux

grep"workhorse"命令可以看到gitlab-workhorse的默认启动参数

go语言前置知识

我会简要介绍一下漏洞涉及的相关语言前置知识,这样才能够更深入的理解该漏洞,并将相关知识点串联起来,达到举一反三。

函数、方法和接口

在golang中函数和方法的定义是不同的,看下面一段代码

packagemain//Person接口typePersoninterface{  isAdult()bool}//Boy结构体typeBoystruct{  Namestring  Ageint}//函数funcNewBoy(namestring,ageint)*Boy{  returnBoy{    Name:name,    Age:age,  }}//方法func(p*Boy)isAdult()bool{  returnp.Age18}funcmain(){  //结构体调用  b:=NewBoy("Star",18)  println(b.isAdult())  //将接口赋值b,使用接口调用  varpPerson=b  println(p.isAdult())//false}

其中NewBoy为函数,isAdult为方法。他们的区别是方法在func后面多了一个接收者参数,这个接受者可以是一个结构体或者接口,你可以把他当做某一个"类",而就是实现了该类的方法。

通过取地址操作可以将一个结构体实例化,相当于new,可以看到在中函数封装了这种操作。在main函数中通过调用函数实例化Boy结构体,并调用了其方法。

关于接口的实现在Go语言中是隐式的。两个类型之间的实现关系不需要在代码中显式地表示出来。Go语言中没有类似于implements的关键字。Go编译器将自动在需要的时候检查两个类型之间的实现关系。**在类型中添加与接口签名一致的方法就可以实现该方法。**如的参数和返回值均与接口Person中的方法一致。所以在main函数中可以直接将定义的接口p赋值为实例结构体b。并进行调用。

net/


转载请注明:http://www.aierlanlan.com/tzrz/8823.html