diff --git a/.gitignore b/.gitignore index 68eedb8..d68a8dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,94 @@ -.DS_Store -*.pyc -*.egg-info +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python build/ +develop-eggs/ dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Environments +.env +.venv +env/ venv/ -.idea/ \ No newline at end of file +ENV/ +env.bak/ +venv.bak/ + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# IDE +.vscode/ +.idea/ + +# macOS +.DS_Store + +# Run Outputs +asm_run_*/ diff --git a/README.md b/README.md index 0bdb215..c7ad8a3 100755 --- a/README.md +++ b/README.md @@ -6,49 +6,58 @@ ![Attack Surface Mapper Logo](https://npercoco.typepad.com/.a/6a0133f264aa62970b0240a49c6ba4200d-800wi "Attack Surface Mapper Logo") # AttackSurfaceMapper -AttackSurfaceMapper (ASM) is a reconnaissance tool that uses a mixture of open source intellgence and active techniques to expand the attack surface of your target. You feed in a mixture of one or more domains, subdomains and IP addresses and it uses numerous techniques to find more targets. It enumerates subdomains with bruteforcing and passive lookups, Other IPs of the same network block owner, IPs that have multiple domain names pointing to them and so on. -Once the target list is fully expanded it performs passive reconnaissance on them, taking screenshots of websites, generating visual maps, looking up credentials in public breaches, passive port scanning with Shodan and scraping employees from LinkedIn. +AttackSurfaceMapper (ASM) is a reconnaissance tool that uses a mixture of open source intelligence and active techniques to expand the attack surface of your target. You feed in a mixture of one or more domains, subdomains and IP addresses and it uses numerous techniques to find more targets. It enumerates subdomains with bruteforcing and passive lookups, Other IPs of the same network block owner, IPs that have multiple domain names pointing to them and so on. + +Once the target list is fully expanded it performs passive reconnaissance on them, taking screenshots of websites, generating visual maps, looking up credentials in public breaches, passive port scanning with Shodan/Censys and scraping employees from LinkedIn. ## Demo + [![Demo](https://img.youtube.com/vi/buIQSf_gmdE/0.jpg)](https://www.youtube.com/watch?v=buIQSf_gmdE) ## Setup + As this is a Python based tool, it should theoretically run on Linux, ChromeOS ([Developer Mode](https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices/generic)), macOS and Windows. -[1] Download AttackSurfaceMapper -``` -$ git clone https://github.com/superhedgy/AttackSurfaceMapper -``` +1. Download AttackSurfaceMapper -[2] Install Python dependencies +```sh +git clone https://github.com/superhedgy/AttackSurfaceMapper +cd AttackSurfaceMapper ``` -$ cd AttackSurfaceMapper -$ python3 -m pip install --no-cache-dir -r requirements.txt + +2. Install Python dependencies + +```sh +python3 -m pip install --no-cache-dir -r requirements.txt ``` -[3] Add optional API keys to enhance data gathering & analysis +3. Add optional API keys to enhance data gathering & analysis -Register and obtain an API key from: -* [VirusTotal](https://www.virustotal.com/gui/join-us) -* [ShodanIO](https://account.shodan.io/register) -* [HunterIO](https://hunter.io/users/sign_up) -* ~~[WeLeakInfo](https://weleakinfo.com/register)~~ -* [LinkedIn](https://www.linkedin.com/start/join) -* [GrayHatWarfare](https://buckets.grayhatwarfare.com/register) +Register and obtain an API key from: +- [VirusTotal](https://www.virustotal.com/gui/join-us) +- [Shodan.io](https://account.shodan.io/register) +- [Hunter.io](https://hunter.io/users/sign_up) +- ~~[WeLeakInfo](https://weleakinfo.com/register)~~ +- [LinkedIn](https://www.linkedin.com/start/join) +- [GrayHatWarfare](https://buckets.grayhatwarfare.com/register) +- [Censys.io](https://censys.io/account) Edit and enter the keys in keylist file -``` -$ nano keylist.asm -``` -### Example run command +```sh +nano keylist.asm ``` -$ python3 asm.py -t your.site.com -ln -w resources/top100_sublist.txt -o demo_run + +## Usage + +```sh +python asm.py -t your_site.com -ln -w resources/top100_sublist.txt -o demo_run ``` ### Optional Parameters + Additional optional parameters can also be set to choose to include active reconnaissance modules in addition to the default passive modules. ``` @@ -65,7 +74,7 @@ optional arguments: Sets the path of the output file. -sc, --screen-capture Capture a screen shot of any associated Web Applications. - -sth, --stealth Passive mode allows reconaissaince using OSINT techniques only. + -sth, --stealth Passive mode allows reconnaissance using OSINT techniques only. -t TARGET, --target TARGET Set a single target IP. -V, --version Displays the current version. @@ -74,18 +83,20 @@ optional arguments: -sw SUBWORDLIST, --subwordlist SUBWORDLIST Specify a list of child subdomains. -e, --expand Expand the target list recursively. - -ln, --linkedinner Extracts emails and employees details from linkedin. + -ln, --linkedinner Extracts emails and employees details from LinkedIn. -d, --debug Enables debugging information. - -v, --verbose Verbose ouput in the terminal window. + -v, --verbose Verbose output in the terminal window. Authors: Andreas Georgiou (@superhedgy) - Jacob Wilkin (@greenwolf) + Jacob Wilkin (@greenwolf) + Aidan Holland (@thehappydinoa) ``` ## Authors -* [Andreas Georgiou](https://twitter.com/superhedgy) -* [Jacob Wilkin](https://github.com/Greenwolf) + +- [Andreas Georgiou](https://twitter.com/superhedgy) +- [Jacob Wilkin](https://github.com/Greenwolf) ## Acknowledgments -* Thanks to `[Your Name Could Be Here, Come Help Out!]` for contributions to the project. +- Thanks to [Aidan Holland](https://github.com/thehappydinoa) for adding the Censys module. diff --git a/asm.py b/asm.py index 6794eef..31d9271 100755 --- a/asm.py +++ b/asm.py @@ -47,6 +47,7 @@ from modules import subhunter from modules import urlscanio from modules import whois_collector +from modules import censys # Constants __author__ = " Andreas Georgiou (@superhedgy)\n\t Jacob Wilkin (@greenwolf)" @@ -124,6 +125,7 @@ def __init__(self): self.screencapture = True self.webscraper = True self.linkedinner = False + self.censys = False self.expand = False self.stealth = False self.verbose = False @@ -156,7 +158,7 @@ def init_checks(master_switch, outpath): parser.add_argument("-o", "--output", help="Sets the path of the output file.", type=str, default=outpath) parser.add_argument("-sc", "--screen-capture", help="Capture a screen shot of any associated Web Applications.", action="store_true", default=False) - parser.add_argument("-sth", "--stealth", help="Passive mode allows reconaissaince using OSINT techniques only.", + parser.add_argument("-sth", "--stealth", help="Passive mode allows reconnaissance using OSINT techniques only.", action="store_true", default=False) parser.add_argument("-t", "--target", help="Set a single target IP.") parser.add_argument("targets", nargs='?', help="Sets the path of the target IPs file.", type=str, default="") @@ -167,10 +169,10 @@ def init_checks(master_switch, outpath): default="resources/top1000_sublist.txt") parser.add_argument("-e", "--expand", help="Expand the target list recursively.", action="store_true", default=False) - parser.add_argument("-ln", "--linkedinner", help="Extracts emails and employees details from linkedin.", + parser.add_argument("-ln", "--linkedinner", help="Extracts emails and employees details from LinkedIn.", action="store_true", default=False) parser.add_argument("-d", "--debug", help="Enables debugging information.",action="store_true",default=False) - parser.add_argument("-v", "--verbose", help="Verbose ouput in the terminal window.", action="store_true", + parser.add_argument("-v", "--verbose", help="Verbose output in the terminal window.", action="store_true", default=False) args = parser.parse_args() @@ -478,6 +480,12 @@ def keyloader(keychain, master_switch): "{0} VirusTotal Module : [{1}Disabled{2}]{3}".format(Fore.WHITE + Style.BRIGHT, Fore.RED, Fore.WHITE, Style.RESET_ALL)) master_switch.virustotal = False + if len(keychain["censys_id"]) > 0 and len(keychain["censys_secret"]) > 0: + print("{0} Censys Module : [{1}Enabled{2}]{3}".format(Fore.WHITE + Style.BRIGHT, Fore.GREEN, Fore.WHITE, Style.RESET_ALL)) + master_switch.censys = True + else: + print("{0} Censys Module : [{1}Disabled{2}]{3}".format(Fore.WHITE + Style.BRIGHT, Fore.RED, Fore.WHITE, Style.RESET_ALL)) + master_switch.censys = False if args.expand: print("{0} SubHunter Module : [{1}Recursive{2}]{3}".format(Fore.WHITE + Style.BRIGHT, Fore.YELLOW, Fore.WHITE, Style.RESET_ALL)) @@ -699,6 +707,9 @@ def main(keychain, switch, output_path, count): if switch.whois_collector is True and switch.stealth is False: whois_collector.wlookup(target_list[key]) # Active + if switch.censys is True: + censys.port_scan(target_list[key], keychain["censys_id"], keychain["censys_secret"], count) # Passive + # hosthunter.query_api(target_list[key]) # Passive hosthunter.org_finder(target_list[key]) # Passive @@ -920,7 +931,6 @@ def sig_handler(signal, frame): sys.exit(0) if __name__ == "__main__": - signal.signal(signal.SIGINT, sig_handler) # Signal Listener now = datetime.now() output_path = 'asm_run_' + str(datetime.now().strftime("%d.%m.%y_%H-%M-%S")) diff --git a/keylist.asm b/keylist.asm index 491e9a6..106c349 100644 --- a/keylist.asm +++ b/keylist.asm @@ -4,3 +4,5 @@ shodan = "" linkedin_username = "" linkedin_password = "" grayhatwarfare = "" +censys_id = "" +censys_secret = "" diff --git a/modules/censys.py b/modules/censys.py new file mode 100644 index 0000000..4cc07c0 --- /dev/null +++ b/modules/censys.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# Filename: censys.py +# Module: Censys +# Authors: Censys Team (support@censys.io) +# Aidan Holland (@thehappydinoa) + +# Standard Libraries +import time + +# External Libraries +from censys.ipv4 import CensysIPv4 + +__version__ = "v1.0" + +def port_scan(hostx, censys_id, censys_secret, counter): + c = CensysIPv4(censys_id, censys_secret) + + for ip in hostx.resolved_ips: + try: + response = c.view(ip.address) + ip.ports = response["ports"] + counter.ports = counter.ports + len(hostx.ports) + except: + time.sleep(1) + continue diff --git a/requirements.txt b/requirements.txt index 0d0fe17..16663bd 100755 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ tld>=0.9.3 trans>=2.1.0 validator_collection selenium>=3.141.0 +censys>=1.1.0