Last active
March 18, 2023 18:39
-
-
Save jonrau1/5480c6db4ac4e8377a73783d11cc57cd to your computer and use it in GitHub Desktop.
AWS Shutdown Print Spooler to mitigate PrintNightmare (CVE-2021-34527) using AWS Systems Manager (SSM) Run Command
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import boto3 | |
import json | |
from botocore.config import Config | |
# Dynamic Retries & Exponential Backoff | |
config = Config( | |
retries = { | |
'max_attempts': 10, | |
'mode': 'adaptive' | |
} | |
) | |
# Boto3 Clients | |
ssm = boto3.client('ssm') | |
ec2 = boto3.client('ec2') | |
# SSM Doc Parameters | |
docName = 'AWS-RunPowerShellScript' | |
stopSpooler = 'Stop-Service -Name Spooler -Force' | |
stopSpoolerStartup = 'Set-Service -Name Spooler -StartupType Disabled' | |
# Get all Regions | |
print('Getting all AWS Regions') | |
# create empty list for all opted-in Regions | |
regionList = [] | |
try: | |
# Get all Regions we are opted in for | |
for r in ec2.describe_regions()['Regions']: | |
regionName = str(r['RegionName']) | |
optInStatus = str(r['OptInStatus']) | |
if optInStatus == 'not-opted-in': | |
pass | |
else: | |
regionList.append(regionName) | |
print('All Regions retrieved from EC2 service') | |
except Exception as e: | |
raise e | |
print('Got all AWS Regions') | |
for region in regionList: | |
windowsBoxes = [] | |
session = boto3.Session(region_name=region) | |
# Temporary Session-bound Boto3 Clients | |
tempEc2 = session.client('ec2',config=config) | |
tempSsm = session.client('ssm',config=config) | |
# Get all Running Instnaces | |
paginator = tempEc2.get_paginator('describe_instances') | |
iterator = paginator.paginate( | |
Filters=[ | |
{ | |
'Name': 'instance-state-name', | |
'Values': [ | |
'running' | |
] | |
} | |
] | |
) | |
for page in iterator: | |
for r in page['Reservations']: | |
for i in r['Instances']: | |
instanceId = str(i['InstanceId']) | |
# Find SSM Covered Instances | |
ssmfinder = tempSsm.describe_instance_information(Filters=[{'Key': 'InstanceIds','Values': [instanceId]}]) | |
if str(ssmfinder['InstanceInformationList']) == '[]': | |
print(instanceId, 'Not Covered by SSM!') | |
else: | |
for s in ssmfinder['InstanceInformationList']: | |
pingStatus = str(s['PingStatus']) | |
platformType = str(s['PlatformType']) | |
if pingStatus == 'Online' and platformType == 'Windows': | |
windowsBoxes.append(instanceId) | |
else: | |
continue | |
if len(windowsBoxes) != 0: | |
# Run SSM Doc at end of every loop | |
response = tempSsm.send_command( | |
Targets=[ | |
{ | |
'Key': 'InstanceIds', | |
'Values': windowsBoxes | |
}, | |
], | |
DocumentName=docName, | |
DocumentVersion='$LATEST', | |
TimeoutSeconds=360, | |
Comment='PrintNightmare Remediation', | |
Parameters={ | |
'commands': [ | |
stopSpooler, | |
stopSpoolerStartup | |
] | |
}, | |
MaxConcurrency='50', | |
MaxErrors='1', | |
CloudWatchOutputConfig={ | |
'CloudWatchOutputEnabled': True | |
} | |
) | |
print(json.dumps(response,indent=2,default=str)) | |
print('SSM Doc Ran in Region:', region) | |
else: | |
print('No Windows Instances in', region) | |
continue |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment