Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update mssqlclient.py #1381

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion impacket/examples/mssqlshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
import cmd
import sys

# for "do_upload"
import hashlib
import base64
import shlex

class SQLSHELL(cmd.Cmd):
def __init__(self, SQL, show_queries=False, tcpShell=None):
if tcpShell is not None:
Expand Down Expand Up @@ -65,6 +70,7 @@ def do_help(self, line):
sp_start_job {cmd} - executes cmd using the sql server agent (blind)
use_link {link} - linked server to use (set use_link localhost to go back to local or use_link .. to get back one step)
! {cmd} - executes a local shell cmd
upload {from} {to} - uploads file {from} to the SQLServer host {to}
show_query - show query
mask_query - mask query
""")
Expand Down Expand Up @@ -133,6 +139,60 @@ def sql_query(self, query, show=True):
def do_shell(self, s):
os.system(s)

def do_upload(self, line):
BUFFER_SIZE = 5 * 1024
try:
# validate "xp_cmdshell" is enabled
self.sql.sql_query("exec master.dbo.sp_configure 'show advanced options', 1; RECONFIGURE;")
result = self.sql.sql_query("exec master.dbo.sp_configure 'xp_cmdshell'")
self.sql.sql_query("exec master.dbo.sp_configure 'show advanced options', 0; RECONFIGURE;")
if result[0].get('run_value') != 1:
print("[-] xp_cmdshell not enabled. Try running 'enable_xp_cmdshell' first")
return

args = shlex.split(line, posix=False)
local_path = args[0]
remote_path = args[1]

# upload file
with open(local_path, 'rb') as f:
data = f.read()
md5sum = hashlib.md5(data).hexdigest()
b64enc_data = b"".join(base64.b64encode(data).split()).decode()
print("[+] Data length (b64-encoded): %.2f KB with MD5: %s" % (len(b64enc_data) / 1024, str(md5sum)))
print("[+] Uploading...")
for i in range(0, len(b64enc_data), BUFFER_SIZE):
cmd = 'echo ' + b64enc_data[i:i+BUFFER_SIZE] + ' >> "' + remote_path + '.b64"'
self.sql.sql_query("EXEC xp_cmdshell '" + cmd + "'")
result = self.sql.sql_query("EXEC xp_fileexist '" + remote_path + ".b64'")
if result[0].get('File Exists') != 1:
print("[-] Error uploading file. Check permissions in the configured remote path")
return
print("[+] Uploaded")

# decode
cmd = 'certutil -decode "' + remote_path + '.b64" "' + remote_path + '"'
self.sql.sql_query("EXEC xp_cmdshell '" + cmd + "'")
print("[+] " + cmd)

# remove encoded
cmd = 'del "' + remote_path + '.b64"'
self.sql.sql_query("EXEC xp_cmdshell '" + cmd + "'")
print("[+] " + cmd)

# validate hash
cmd = 'certutil -hashfile "' + remote_path + '" MD5'
result = self.sql.sql_query("EXEC xp_cmdshell '" + cmd + "'")
print("[+] " + cmd)
md5sum_uploaded = result[1].get('output').replace(" ", "")
if md5sum == md5sum_uploaded:
print("[+] MD5 hashes match")
else:
print("[-] ERROR! MD5 hashes do NOT match!")
print("[+] Uploaded file MD5: %s" % md5sum_uploaded)
except:
pass

def do_xp_dirtree(self, s):
try:
self.sql_query("exec master.sys.xp_dirtree '%s',1,1" % s)
Expand Down Expand Up @@ -277,4 +337,4 @@ def emptyline(self):
def do_exit(self, line):
if self.shell is not None:
self.shell.close()
return True
return True