Using the API for Live Response
Adding a file to the MDE Live Response Library and Running it on an Endpoint
Continuing to build on my previous posts…
One of my all-time favorite user containment methods is to change the BitLocker keys and shut the system down.
#Delete existing protections
manage-bde.exe -protectors -delete c: -Type TPMAndPIN
manage-bde.exe -protectors -delete c: -Type RecoveryPassword
#Now that all of the previous Protectors are gone, let's add our own.
#Let's add a new password that only the security team will need to know.
manage-bde.exe -protectors -add c: -TPMandPIN SuperDuperPassword
#As a backup, let's also add a couple of recovery keys
manage-bde.exe -protectors -add c: -RecoveryPassword 111111-111111-111111-111111-111111-111111-111111-111111
manage-bde.exe -protectors -add c: -RecoveryPassword 222222-222222-222222-222222-222222-222222-222222-222222
manage-bde.exe -on c:
shutdown /f /s /t 0
Making a function to Post Library Files
def postFileToLiveResponseLibrary(fileObjToUpload, description, parameters="", override = False, token=result["access_token"]):
headers = {'Authorization' : "Bearer " + token }
url = "https://api.securitycenter.windows.com/api/libraryfiles"
files={'file': fileObjToUpload}
params={
'Description': description,
'ParametersDescription': parameters,
'OverrideIfExists':override
}
response = requests.post(url, data=params, files=files, headers=headers, verify=False)
return response.json()
Adding a Containment Script to Your Live Response Library
from io import StringIO
script = """
#Delete existing protections
manage-bde.exe -protectors -delete c: -Type TPMAndPIN
manage-bde.exe -protectors -delete c: -Type RecoveryPassword
#Now that all of the previous Protectors are gone, let's add our own.
#Let's add a new password that only the security team will need to know.
manage-bde.exe -protectors -add c: -TPMandPIN SuperDuperPassword
#As a backup, let's also add a couple of recovery keys
manage-bde.exe -protectors -add c: -RecoveryPassword 111111-111111-111111-111111-111111-111111-111111-111111
manage-bde.exe -protectors -add c: -RecoveryPassword 222222-222222-222222-222222-222222-222222-222222-222222
manage-bde.exe -on c:
"""
#StringIO is a fun module that lets you treat strings like file objects.
fileobj = StringIO(script)
fileobj.filename = "contain.ps1"
postFileToLiveResponseLibrary(
fileObjToUpload = fileobj,
description = "BitLocker Containment Script",
parameters = "Parameter Info Would Go Here",
override = True
)
{'@odata.context': 'https://api.securitycenter.windows.com/api/$metadata#LibraryFiles/$entity',
'fileName': 'file',
'sha256': '8052835f7fcbca7b123e763b3e429f552cda4d6d3ddcf193d4b356ca01b9e7b4',
'description': 'BitLocker Containment Script',
'creationTime': '2022-03-10T13:35:27.841749Z',
'lastUpdatedTime': '2022-03-10T13:35:27.841749Z',
'createdBy': 'Jonathan Glass',
'hasParameters': False,
'parametersDescription': 'Parameter Info Would Go Here'}
Sweet! It worked!
Running your newly uploaded script against an endpoint
liveResponseCommands = {}
liveResponseCommands['Commands'] = []
command = {}
command['type'] = "RunScript"
command["params"] = [{"key":"ScriptName",
"value":"contain.ps1"}]
liveResponseCommands['Commands'].append(command)
liveResponseCommands['Comment'] = "Containing Endpoint via BitLocker"
liveResponseCommands
{'Commands': [{'type': 'RunScript',
'params': [{'key': 'ScriptName', 'value': 'contain.ps1'}]}],
'Comment': 'Containing Endpoint via BitLocker'}
machineID = "c6993a6c004946bf52d2d59237c18e6db4db7e5e"
MDErequest("machines/%s/runliveresponse" % (machineID),
liveResponseCommands)
{'@odata.context': 'https://api.securitycenter.windows.com/api/$metadata#MachineActions/$entity',
'id': '9509426d-490c-4f2b-90b4-4703674be8cf',
'type': 'LiveResponse',
'title': None,
'requestor': 'JonathanGlass@HalfFullofSecurity.onmicrosoft.com',
'requestorComment': 'Containing Endpoint via BitLocker',
'status': 'Pending',
'machineId': 'c6993a62004946bf52d2d59237c18e6db4db7e5e',
'computerDnsName': 'desktop-l3mnbj9',
'creationDateTimeUtc': '2022-03-10T14:36:51.8759111Z',
'lastUpdateDateTimeUtc': '2022-03-10T14:36:51.8759111Z',
'cancellationRequestor': None,
'cancellationComment': None,
'cancellationDateTimeUtc': None,
'errorHResult': 0,
'scope': None,
'externalId': None,
'requestSource': 'PublicApi',
'relatedFileInfo': None,
'commands': [{'index': 0,
'startTime': None,
'endTime': None,
'commandStatus': 'Created',
'errors': [],
'command': {'type': 'RunScript',
'params': [{'key': 'ScriptName', 'value': 'contain.ps1'}]}}],
'troubleshootInfo': None}
Deleting a file from your Live Response Library
def deleteFileFromLiveResponseLibrary(filename, token=result["access_token"]):
headers = {'Authorization' : "Bearer " + token }
url = "https://api.securitycenter.windows.com/api/libraryfiles/%s" % (filename)
response = requests.delete(url, headers=headers, verify=False)
return response
deleteFileFromLiveResponseLibrary("contain.ps1")
<Response [204]> means it worked!
