TheButterZone (OP)
Legendary

Activity: 3304
Merit: 1156
RIP Mommy
|
 |
October 25, 2026, 01:50:11 AM Last edit: October 26, 2026, 06:14:14 AM by TheButterZone |
|
Midway through learning how to CTF for the first time, I'm getting 504 Gateway Time-out, don't have time to sit around waiting for the DoS to resolve. Server: nginx Flag address to capture: https://mempool.space/address/bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqyIf you're successful, I'd appreciate a tip for bringing this CTF to your attention... <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="theme-color" content="#edf4fb"> <meta name="description" content="A PHP security challenge. Find the hidden bitcoin key. First person to get the wallet wins."> <title>Steal My Bitcoin</title> <link rel="icon" href="/favicon.svg" type="image/svg+xml"> <style> :root { color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #243b53; background: #edf4fb; } * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; min-height: 100svh; display: grid; place-items: center; padding: 32px 20px; background: radial-gradient(ellipse at 15% 15%, #dcecfb 0, transparent 55%), radial-gradient(ellipse at 90% 90%, #e0eafa 0, transparent 50%), #edf4fb; } main { width: 100%; max-width: 1000px; } .card { background: #fff; border: 1px solid #dbe6f0; border-radius: 22px; padding: clamp(28px, 6vw, 52px); box-shadow: 0 20px 70px -30px #486f9838; } h1 { color: #183957; font-size: clamp(30px, 6vw, 40px); letter-spacing: -.045em; line-height: 1.15; margin: 0 0 24px; font-weight: 650; } p { font-size: 16px; line-height: 1.8; margin: 0 0 18px; } strong { font-weight: 650; color: #1f568b; } code { background: #eef4fa; color: #245886; border: 1px solid #e0eaf4; border-radius: 5px; padding: 2px 6px; font-size: .88em; overflow-wrap: anywhere; } .finish { margin: 28px 0 0; padding-top: 23px; border-top: 1px solid #e8eef5; color: #235a8d; font-weight: 600; } footer { margin-top: 22px; text-align: center; font-size: 12px; letter-spacing: .025em; color: #58738d; } .notice { margin-top: 24px; padding: 18px 20px; background: #f0f5fb; border: 1px solid #dce7f2; border-radius: 10px; } .notice p { margin: 0; font-size: 13px; line-height: 1.75; color: #45617b; } .layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; } .wallet { margin: 0; padding: 24px; min-width: 0; border-radius: 18px; } .wallet-heading { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px; align-items: baseline; font-size: 14px; } .wallet a { color: #235a8d; text-underline-offset: 3px; font-size: 13px; } .wallet-address { overflow-wrap: anywhere; font-family: monospace; font-size: 12px; color: #58738d; margin: 8px 0 0; } #wallet-balance { font-size: 13px; margin: 18px 0 4px; line-height: 1.5; font-variant-numeric: tabular-nums; color: #58738d; } #wallet-usd { font-size: 30px; font-weight: 600; letter-spacing: -.04em; line-height: 1.2; color: #183957; margin: 0 0 18px; font-variant-numeric: tabular-nums; } #wallet-refresh { font: inherit; font-size: 12px; color: #346595; background: transparent; border: 0; border-top: 1px solid #e8eef5; border-radius: 0; padding: 14px 0 0; width: 100%; text-align: left; cursor: pointer; } #wallet-refresh:disabled { opacity: .6; cursor: wait; } .wallet-address a { font-family: monospace; font-size: 13px; text-decoration: none; } a:hover { text-decoration: underline; } @media (max-width: 780px) { .layout { grid-template-columns: 1fr; } main { max-width: 620px; } .wallet { padding: 24px; } } .challenge-clock { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; margin: -8px 0 24px; color: #58738d; } #challenge-clock { font-size: 13px; font-weight: 400; font-variant-numeric: tabular-nums; color: #58738d; } article.challenge-solved { border-color: #e3b0b6; background: #fffafa; } .challenge-solved .challenge-clock { background: #fcecef; border-radius: 6px; padding: 8px 12px; margin-top: -8px; } .challenge-solved #challenge-clock { color: #a52f3b; font-weight: 600; } .challenge-solved #prize-copy strong { color: #a52f3b; } </style> <!-- SITE-AUTHORSHIP-PROOF { "algorithm": "Ed25519", "public_key_spki_base64": "MCowBQYDK2VwAyEAEXObSx+XQvc/5vOeAVqcHpY5Gu0BN67Fv0726iGJ0nc=", "message_utf8_base64": "U2l0ZSBhdXRob3JzaGlwIGNsYWltCkRvbWFpbjogc3RlYWxteWJpdGNvaW4uY29tClN0YXRlbWVudDogVGhlIGhvbGRlciBvZiB0aGUgY29ycmVzcG9uZGluZyBwcml2YXRlIGtleSBjcmVhdGVkIGFuZCBvcGVyYXRlcyB0aGlzIGNoYWxsZW5nZSB3ZWJzaXRlLgpJc3N1ZWQ6IDIwMjYtMTAtMjRUMTg6NTA6MDFaCk5vbmNlOiBjYjE2NzEyMjA2YmE4NjY1OGYyMWExYmI2YTlhMWNjMWY5MDliNmM2N2ZjYmRhNDgK", "signature_base64": "S6N38mGD/S8Hx07SfAtw1iEZ21q0KaC7IkzOrWDdmHfHMsHQcdfBs4ehU9y9EfKnD11KBqdJVIqabWn82uIACw==" } END-SITE-AUTHORSHIP-PROOF --> </head> <body> <main> <div class="layout"> <article class="card" aria-labelledby="challenge-title"> <h1 id="challenge-title">Steal my Bitcoin</h1> <div class="challenge-clock" aria-label="Challenge duration"><span id="challenge-clock">0.00 hours without a successful hack</span></div> <p id="prize-copy"><span id="prize-tense">There is</span> a bitcoin key hidden on this server worth <strong id="prize-value">about $500</strong>.</p> <p>It is accessible to the PHP user account through the <code>print-flag</code> binary.</p> <p>This PHP version was selected from before the PHP2SHELL CVEs were released.</p> <p class="finish">First person to get the wallet wins. If you don’t need the money, consider donating it to those who do: <a href="https://www.givewell.org/" target="_blank" rel="noopener noreferrer" style="color: inherit; text-underline-offset: 3px;">givewell.org</a>.</p>
<aside class="notice" aria-label="Security and monitoring notice"> <p>All traffic is logged. This is a known vulnerable machine, so we cannot guarantee privacy. Other attackers may access or monitor activity and data beyond our control. Do not submit anything you want to keep private.</p> </aside> </article> <section class="card wallet" aria-label="Challenge wallet"> <div class="wallet-heading"><strong>Challenge wallet</strong><a href="https://mempool.space/address/bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy" target="_blank" rel="noopener noreferrer">Explorer ↗</a></div> <p class="wallet-address"><a href="https://mempool.space/address/bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy" target="_blank" rel="noopener noreferrer" title="bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy" aria-label="View wallet bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy on mempool.space">bc1qlnu5…t3cxqy</a></p> <p id="wallet-balance" role="status" aria-live="polite">Checking balance…</p> <p id="wallet-usd" role="status" aria-live="polite"></p> <button id="wallet-refresh" type="button">Refresh ↻</button> <noscript><p>JavaScript is off. Use the explorer link to check the balance.</p></noscript> </section> </div> <footer>stealmybitcoin.com · <a href="/terms.html" style="color: inherit; text-underline-offset: 3px;">Terms of participation</a></footer> </main> <script> (() => { const address = 'bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy'; const api = 'https://mempool.space/api'; const start = Date.parse('2026-10-24T20:30:00Z'); const output = document.getElementById('wallet-balance'); const button = document.getElementById('wallet-refresh'); const usdOutput = document.getElementById('wallet-usd'); const clock = document.getElementById('challenge-clock'); const timing = document.querySelector('.challenge-clock'); let finish = null; let prizeDollars = null; const btc = sats => (sats / 100000000).toFixed(8) + ' BTC'; function tick() { document.getElementById('prize-value').textContent = finish !== null || !(prizeDollars > 0) ? 'about $500' : 'about ' + new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD', maximumFractionDigits: 0}).format(prizeDollars); document.getElementById('prize-tense').textContent = finish !== null ? 'There was' : 'There is'; document.querySelector('article.card').classList.toggle('challenge-solved', finish !== null); const hours = Math.max(0, ((finish ?? Date.now()) - start) / 3600000).toFixed(2); clock.textContent = finish !== null ? (finish < start ? 'Wallet claimed before the challenge started' : 'Successfully hacked after ' + hours + ' hours') : hours + ' hours without a successful hack'; } async function get(path, signal) { const response = await fetch(api + path, { signal, credentials: 'omit', referrerPolicy: 'no-referrer', cache: 'no-store' }); if (!response.ok) throw new Error('Explorer unavailable'); return response.json(); } // Walk confirmed history backwards to find the spend that crossed below $10. // The finish time comes from that transaction's block, never the visitor's clock. async function findFinish(confirmed, price, signal) { let balance = confirmed; let cursor = ''; const seen = new Set(); while (true) { const batch = await get('/address/' + address + '/txs/chain' + (cursor ? '/' + cursor : ''), signal); if (!Array.isArray(batch)) throw new Error('Invalid transaction history'); for (const tx of batch) { if (seen.has(tx.txid)) throw new Error('Repeated transaction history'); seen.add(tx.txid); const received = tx.vout.filter(v => v.scriptpubkey_address === address).reduce((sum, v) => sum + v.value, 0); const spent = tx.vin.filter(v => v.prevout?.scriptpubkey_address === address).reduce((sum, v) => sum + v.prevout.value, 0); const before = balance - received + spent; if (spent > received && before * price / 1e8 >= 10 && balance * price / 1e8 < 10 && tx.status?.confirmed && Number.isFinite(tx.status.block_time)) { return {time: tx.status.block_time * 1000, txid: tx.txid}; } balance = before; } if (batch.length < 25) return null; cursor = batch[batch.length - 1].txid; } } async function refresh() { if (button.disabled) return; button.disabled = true; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 20000); try { const data = await get('/address/' + address, controller.signal); const values = [data.chain_stats?.funded_txo_sum, data.chain_stats?.spent_txo_sum, data.mempool_stats?.funded_txo_sum, data.mempool_stats?.spent_txo_sum]; if (!values.every(v => Number.isSafeInteger(v) && v >= 0)) throw new Error('Invalid balance'); const confirmed = values[0] - values[1]; const pending = values[2] - values[3]; output.textContent = btc(confirmed) + (pending ? ' · Pending: ' + (pending > 0 ? '+' : '') + btc(pending) : ''); output.title = 'Confirmed balance · Checked ' + new Date().toLocaleTimeString(); let prices; try { prices = await get('/v1/prices', controller.signal); if (!Number.isFinite(prices.USD) || prices.USD <= 0) throw new Error('Invalid price'); } catch (error) { usdOutput.textContent = 'USD estimate unavailable'; return; } const dollars = confirmed / 1e8 * prices.USD; prizeDollars = dollars; usdOutput.textContent = '≈ ' + new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(dollars) + ' USD'; usdOutput.title = 'Approximate confirmed balance; excludes pending changes and fees.'; if (dollars < 10 && values[1] > 0) { const result = await findFinish(confirmed, prices.USD, controller.signal); finish = result?.time ?? null; timing.title = result ? 'Finish based on the spending transaction’s block timestamp: ' + new Date(finish).toUTCString() : 'No qualifying confirmed spend found.'; if (result && finish < start) { tick(); } else tick(); } else { finish = null; timing.title = pending < 0 ? 'Outgoing payment pending; finish time awaits confirmation.' : 'Total time since the scheduled challenge start.'; tick(); } } catch (error) { output.textContent = 'Update unavailable. Check the explorer.'; timing.title = 'Wallet verification unavailable; showing the last verified timer state.'; } finally { clearTimeout(timeout); button.disabled = false; } } button.addEventListener('click', refresh); tick(); setInterval(() => { if (finish !== null && finish < start) { tick(); } else tick(); }, 1000); setInterval(() => { if (!document.hidden) refresh(); }, 60000); document.addEventListener('visibilitychange', () => { if (!document.hidden) refresh(); }); refresh(); })(); </script> </body> </html>
<!doctype html> <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#edf4fb"><title>Terms of participation | The Bitcoin Challenge</title><style> :root { color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #243b53; background: #edf4fb; } * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; min-height: 100svh; display: grid; place-items: center; padding: 32px 20px; background: radial-gradient(ellipse at 15% 15%, #dcecfb 0, transparent 55%), radial-gradient(ellipse at 90% 90%, #e0eafa 0, transparent 50%), #edf4fb; } main { width: 100%; max-width: 620px; } .card { background: #fff; border: 1px solid #dbe6f0; border-radius: 22px; padding: clamp(28px, 6vw, 52px); box-shadow: 0 20px 70px -30px #486f9838; } .eyebrow { display: flex; align-items: center; gap: 9px; margin: 0 0 24px; color: #346595; font-size: 12px; font-weight: 650; letter-spacing: .13em; text-transform: uppercase; } .dot { width: 7px; height: 7px; background: #4988c6; border-radius: 50%; } h1 { color: #183957; font-size: clamp(30px, 6vw, 40px); letter-spacing: -.045em; line-height: 1.15; margin: 0 0 24px; font-weight: 650; } p { font-size: 16px; line-height: 1.8; margin: 0 0 18px; } strong { font-weight: 650; color: #1f568b; } code { background: #eef4fa; color: #245886; border: 1px solid #e0eaf4; border-radius: 5px; padding: 2px 6px; font-size: .88em; overflow-wrap: anywhere; } .finish { margin: 28px 0 0; padding-top: 23px; border-top: 1px solid #e8eef5; color: #235a8d; font-weight: 600; } footer { margin-top: 22px; text-align: center; font-size: 12px; letter-spacing: .025em; color: #58738d; } main { max-width: 800px; } body { display: block; } main { margin: 32px auto; } h2 { font-size: 20px; color: #183957; margin: 30px 0 10px; letter-spacing: -.02em; } p, li { font-size: 15px; line-height: 1.8; } ul { padding-left: 22px; } li { margin-bottom: 8px; } a { color: #235a8d; text-underline-offset: 3px; } .updated { font-size: 13px; color: #58738d; } </style><link rel="icon" href="/favicon.svg" type="image/svg+xml"></head><body><main><article class="card"><p><a href="/">← Back to the challenge</a></p><h1>Terms of participation</h1><p>This is a free challenge of technical skill, not a random drawing or sweepstakes. No purchase or payment is required. Only participate if it is legal for you to do so.</p> <h2>The wallet</h2> <p>First person to get the wallet wins. Someone else may empty it before you do, even if you find the key. The displayed dollar value is approximate; bitcoin prices and fees change. There is no guaranteed payout or replacement of funds already claimed. Do not send your own money to the wallet.</p> <h2>Play within the challenge</h2> <p>Test the web application and run <code>print-flag</code> inside the PHP container. Do not attack the host, SSH, Docker, Nginx, other people, or third-party services. No container escapes, denial of service, resource exhaustion, persistence, or sabotage.</p> <h2>Use at your own risk</h2> <p>This server is intentionally insecure. Use an isolated testing environment and do not submit passwords, private keys, or personal information.</p> <h2>Privacy</h2> <p>All traffic is logged. This is a known vulnerable machine, so we cannot guarantee privacy. Other attackers may access or monitor activity and data beyond our control. Do not submit anything you want to keep private.</p> <p>The challenge may go offline, change, or end at any time. Uptime, solvability, saved progress, and recovery are not guaranteed.</p> <p>To the extent the law allows, we provide this challenge as is and accept no liability for losses or damage from taking part.</p> <p>By participating, you agree to these rules.</p></article><footer>stealmybitcoin.com</footer></main></body></html>
|