<filename>BucketSnoopServer/server.py
import boto3
import json
import requests
from pprint import pprint
from botocore.exceptions import ClientError
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
from bs4 import BeautifulSoup

class bcolors:
	HEADER = '\033[95m'
	OKBLUE = '\033[94m'
	OKGREEN = '\033[92m'
	WARNING = '\033[93m'
	FAIL = '\033[91m'
	ENDC = '\033[0m'
	BOLD = '\033[1m'
	UNDERLINE = '\033[4m'

class MyServerProtocol(WebSocketServerProtocol):
	def onConnect(self, request):
		print("Client connecting: {0}".format(request.peer))

	def onOpen(self):
		print("WebSocket connection open.")

	def onMessage(self, payload, isBinary):
		msg = json.loads(payload.decode('utf8'))
		mtype = msg['type']
		if mtype == 1:
			bucket_name = msg['bucketName']
			origin_url = msg['originUrl']
			processBucket(bucket_name, origin_url)
		if mtype == 2:
			bucket_host = msg['bucketHost']
			origin_url = msg['originUrl']
			getS3BuckedNameFromHost(bucket_host, origin_url)
		if mtype == 3:
			azure_container = msg['azureContainer']
			origin_url = msg['originUrl']
			processAzureContainer(azure_container, origin_url)
		if mtype == 4:
			google_bucket = msg['googleBucket']
			origin_url = msg['originUrl']
			processGoogleBucket(google_bucket, origin_url)
		if mtype == 5:
			bucket_host = msg['bucketHost']
			origin_url = msg['originUrl']
			getGoogleBucketNameFromHost(bucket_host, origin_url)
	
	def onClose(self, wasClean, code, reason):
		print("WebSocket connection closed: {0}".format(reason))

def processGoogleBucket(google_bucket, origin_url):
	print("***********************************************************")
	print("Processing Google bucket: {0}".format(google_bucket))
	print("Origin: {0}".format(origin_url))
	try:
		r = requests.get('http://' + google_bucket + '.storage.googleapis.com/?acl')
		if r.status_code == 200:
			print('NEED TO ADD XML PARSING - ACL READ ALLOWED')
		else:
			print(bcolors.OKGREEN + "ACL Read Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)
	try:
		r = requests.get('http://' + google_bucket + '.storage.googleapis.com/?max-keys=1')
		if r.status_code == 200:
			print(bcolors.FAIL + "Object Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Object Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def processAzureContainer(azure_container, origin_url):
	print("***********************************************************")
	print("Processing Azure blob container: {0}".format(azure_container))
	print("Origin: {0}".format(origin_url))
	try:
		r = requests.get('http://' + azure_container + '?restype=container&comp=list&maxresults=1')
		if r.status_code == 200:
			print(bcolors.FAIL + "Blobs Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Blobs Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def processBucket(bucket_name, origin_url):
	print("***********************************************************")
	print("Processing S3 bucket: {0}".format(bucket_name))
	print("Origin: {0}".format(origin_url))
	try:
		client = boto3.client('s3')
		bucket_acl = client.get_bucket_acl(Bucket=bucket_name)
		for p in bucket_acl['Grants']:
			if 'URI' in p['Grantee']:
				if p['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers':
					if p['Permission'] == 'READ' or p['Permission'] == 'READ_ACP':
						print("All Users: " + bcolors.WARNING + p['Permission'] + bcolors.ENDC)
					if p['Permission'] == 'WRITE' or p['Permission'] == 'FULL_CONTROL' or p['Permission'] == 'WRITE_ACP':
						print("All Users: " + bcolors.FAIL + p['Permission'] + bcolors.ENDC)
				if p['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers':
					if p['Permission'] == 'READ' or p['Permission'] == 'READ_ACP':
						print("Authenticated Users: " + bcolors.WARNING + p['Permission'] + bcolors.ENDC)
					if p['Permission'] == 'WRITE' or p['Permission'] == 'FULL_CONTROL' or p['Permission'] == 'WRITE_ACP':
						print("Authenticated Users: " + bcolors.FAIL + p['Permission'] + bcolors.ENDC)
	except ClientError as e:
		if e.response['Error']['Code'] == 'AccessDenied':
			print(bcolors.OKGREEN + "ACL Read Denied" + bcolors.ENDC)
	try:
		client = boto3.client('s3')
		a_list = client.list_objects(
			Bucket=bucket_name,
			MaxKeys=1
		)
		if a_list:
			print(bcolors.FAIL + "Authenticated Object Listing Allowed!" + bcolors.ENDC)
	except ClientError as e:
		if e.response['Error']['Code'] == 'AccessDenied':
			print(bcolors.OKGREEN + "Authenticated Object Listing Denied" + bcolors.ENDC)
	try:
		r = requests.get('http://' + bucket_name + '.s3.amazonaws.com' )
		if r.status_code == 200:
			print(bcolors.FAIL + "Public Object Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Public Object Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def getS3BuckedNameFromHost(bucket_host, origin_url):
	try:
		r = requests.get("http://" + bucket_host)
		if r.status_code == 200 and r.headers['content-type'] == 'application/xml' and r.headers['Server'] == 'AmazonS3':
			soup = BeautifulSoup(r.text, 'xml')
			processBucket(soup.Name.text, origin_url)
		else:
			print(bcolors.OKBLUE + bucket_host + " points to S3 but no bucket name could be parsed" + bcolors.ENDC)			
	except requests.RequestException as e:
		print(e)

def getGoogleBucketNameFromHost(bucket_host, origin_url):
	try:
		r = requests.get('http://' + bucket_host)
		if r.status_code == 200 and r.headers['content-type'] == 'application/xml' and r.headers['server'] == 'UploadServer':
			soup = BeautifulSoup(r.text, 'xml')
			processGoogleBucket(soup.Name.text, origin_url)
		else:
			print(bcolors.OKBLUE + bucket_host + " points to Google storage but no bucket name could be parsed" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

if __name__ == '__main__':
	import sys
	from twisted.python import log
	from twisted.internet import reactor

	log.startLogging(sys.stdout)
	factory = WebSocketServerFactory("ws://127.0.0.1:9000")
	factory.protocol = MyServerProtocol
	reactor.listenTCP(9000, factory)
	reactor.run()
<filename>BucketSnoopServer/server.py
import boto3
import json
import requests
from pprint import pprint
from botocore.exceptions import ClientError
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
from bs4 import BeautifulSoup

class bcolors:
	HEADER = '\033[95m'
	OKBLUE = '\033[94m'
	OKGREEN = '\033[92m'
	WARNING = '\033[93m'
	FAIL = '\033[91m'
	ENDC = '\033[0m'
	BOLD = '\033[1m'
	UNDERLINE = '\033[4m'

class MyServerProtocol(WebSocketServerProtocol):
	def onConnect(self, request):
		print("Client connecting: {0}".format(request.peer))

	def onOpen(self):
		print("WebSocket connection open.")

	def onMessage(self, payload, isBinary):
		msg = json.loads(payload.decode('utf8'))
		mtype = msg['type']
		if mtype == 1:
			bucket_name = msg['bucketName']
			origin_url = msg['originUrl']
			processBucket(bucket_name, origin_url)
		if mtype == 2:
			bucket_host = msg['bucketHost']
			origin_url = msg['originUrl']
			getS3BuckedNameFromHost(bucket_host, origin_url)
		if mtype == 3:
			azure_container = msg['azureContainer']
			origin_url = msg['originUrl']
			processAzureContainer(azure_container, origin_url)
		if mtype == 4:
			google_bucket = msg['googleBucket']
			origin_url = msg['originUrl']
			processGoogleBucket(google_bucket, origin_url)
		if mtype == 5:
			bucket_host = msg['bucketHost']
			origin_url = msg['originUrl']
			getGoogleBucketNameFromHost(bucket_host, origin_url)
	
	def onClose(self, wasClean, code, reason):
		print("WebSocket connection closed: {0}".format(reason))

def processGoogleBucket(google_bucket, origin_url):
	print("***********************************************************")
	print("Processing Google bucket: {0}".format(google_bucket))
	print("Origin: {0}".format(origin_url))
	try:
		r = requests.get('http://' + google_bucket + '.storage.googleapis.com/?acl')
		if r.status_code == 200:
			print('NEED TO ADD XML PARSING - ACL READ ALLOWED')
		else:
			print(bcolors.OKGREEN + "ACL Read Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)
	try:
		r = requests.get('http://' + google_bucket + '.storage.googleapis.com/?max-keys=1')
		if r.status_code == 200:
			print(bcolors.FAIL + "Object Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Object Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def processAzureContainer(azure_container, origin_url):
	print("***********************************************************")
	print("Processing Azure blob container: {0}".format(azure_container))
	print("Origin: {0}".format(origin_url))
	try:
		r = requests.get('http://' + azure_container + '?restype=container&comp=list&maxresults=1')
		if r.status_code == 200:
			print(bcolors.FAIL + "Blobs Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Blobs Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def processBucket(bucket_name, origin_url):
	print("***********************************************************")
	print("Processing S3 bucket: {0}".format(bucket_name))
	print("Origin: {0}".format(origin_url))
	try:
		client = boto3.client('s3')
		bucket_acl = client.get_bucket_acl(Bucket=bucket_name)
		for p in bucket_acl['Grants']:
			if 'URI' in p['Grantee']:
				if p['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers':
					if p['Permission'] == 'READ' or p['Permission'] == 'READ_ACP':
						print("All Users: " + bcolors.WARNING + p['Permission'] + bcolors.ENDC)
					if p['Permission'] == 'WRITE' or p['Permission'] == 'FULL_CONTROL' or p['Permission'] == 'WRITE_ACP':
						print("All Users: " + bcolors.FAIL + p['Permission'] + bcolors.ENDC)
				if p['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers':
					if p['Permission'] == 'READ' or p['Permission'] == 'READ_ACP':
						print("Authenticated Users: " + bcolors.WARNING + p['Permission'] + bcolors.ENDC)
					if p['Permission'] == 'WRITE' or p['Permission'] == 'FULL_CONTROL' or p['Permission'] == 'WRITE_ACP':
						print("Authenticated Users: " + bcolors.FAIL + p['Permission'] + bcolors.ENDC)
	except ClientError as e:
		if e.response['Error']['Code'] == 'AccessDenied':
			print(bcolors.OKGREEN + "ACL Read Denied" + bcolors.ENDC)
	try:
		client = boto3.client('s3')
		a_list = client.list_objects(
			Bucket=bucket_name,
			MaxKeys=1
		)
		if a_list:
			print(bcolors.FAIL + "Authenticated Object Listing Allowed!" + bcolors.ENDC)
	except ClientError as e:
		if e.response['Error']['Code'] == 'AccessDenied':
			print(bcolors.OKGREEN + "Authenticated Object Listing Denied" + bcolors.ENDC)
	try:
		r = requests.get('http://' + bucket_name + '.s3.amazonaws.com' )
		if r.status_code == 200:
			print(bcolors.FAIL + "Public Object Listing Allowed!" + bcolors.ENDC)
		else:
			print(bcolors.OKGREEN + "Public Object Listing Denied" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

def getS3BuckedNameFromHost(bucket_host, origin_url):
	try:
		r = requests.get("http://" + bucket_host)
		if r.status_code == 200 and r.headers['content-type'] == 'application/xml' and r.headers['Server'] == 'AmazonS3':
			soup = BeautifulSoup(r.text, 'xml')
			processBucket(soup.Name.text, origin_url)
		else:
			print(bcolors.OKBLUE + bucket_host + " points to S3 but no bucket name could be parsed" + bcolors.ENDC)			
	except requests.RequestException as e:
		print(e)

def getGoogleBucketNameFromHost(bucket_host, origin_url):
	try:
		r = requests.get('http://' + bucket_host)
		if r.status_code == 200 and r.headers['content-type'] == 'application/xml' and r.headers['server'] == 'UploadServer':
			soup = BeautifulSoup(r.text, 'xml')
			processGoogleBucket(soup.Name.text, origin_url)
		else:
			print(bcolors.OKBLUE + bucket_host + " points to Google storage but no bucket name could be parsed" + bcolors.ENDC)
	except requests.RequestException as e:
		print(e)

if __name__ == '__main__':
	import sys
	from twisted.python import log
	from twisted.internet import reactor

	log.startLogging(sys.stdout)
	factory = WebSocketServerFactory("ws://127.0.0.1:9000")
	factory.protocol = MyServerProtocol
	reactor.listenTCP(9000, factory)
	reactor.run()