Skip to content

Commit

Permalink
Merge pull request #22 from codingo/codingo-stdin-wordlists
Browse files Browse the repository at this point in the history
Added support for piping in wordlists using stdin
  • Loading branch information
timkent authored Sep 26, 2017
2 parents 7adead3 + b709a21 commit 5111bea
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 24 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,26 @@ A virtual host scanner that can pivot over hosts, detect catch-all scenarios, al
![VHOSTScan Feature Map](https://github.com/codingo/codingo.github.io/blob/master/assets/featureMap.PNG)

## Examples

### Quick Example
The most straightforward example runs the default wordlist against example.com using the default of port 80:

```bash
$ VHostScan.py -t example.com
```

### Port forwarding
Say you have an SSH port forward listening on port 4444 fowarding traffic to port 80 on example.com's development machine. You could use the following to make VHostScan connect through your SSH tunnel via localhost:4444 but format the header requests to suit connecting straight to port 80:

```bash
$ VHostScan.py -t localhost -b example.com -p 4444 -r 80
```

### STDIN
If you want to pipe information into VHostScan you can use the ```-``` flag:
```bash
$ cat vhostname | VHostScan.py -t localhost -
```
### STDIN and WordList
You can still specify a wordlist to use along with stdin. In these cases wordlist information will be appended to stdin. For example:
```bash
$ cat vhostname | VhostScan.py -t localhost -w ./wordlists/wordlist.txt -
```
44 changes: 32 additions & 12 deletions VHostScan.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


def print_banner():
print("+-+-+-+-+-+-+-+-+-+ v. 0.3")
print("+-+-+-+-+-+-+-+-+-+ v. 0.4")
print("|V|H|o|s|t|S|c|a|n| Developed by @codingo_ & @__timk")
print("+-+-+-+-+-+-+-+-+-+ https://github.com/codingo/VHostScan\n")

Expand All @@ -17,7 +17,7 @@ def main():
print_banner()
parser = ArgumentParser()
parser.add_argument("-t", dest="target_hosts", required=True, help="Set a target range of addresses to target. Ex 10.11.1.1-255" )
parser.add_argument("-w", dest="wordlist", required=False, type=str, help="Set the wordlist to use (default ./wordlists/virtual-host-scanning.txt)", default="./wordlists/virtual-host-scanning.txt")
parser.add_argument("-w", dest="wordlist", required=False, type=str, help="Set the wordlist to use (default ./wordlists/virtual-host-scanning.txt)")
parser.add_argument("-b", dest="base_host", required=False, help="Set host to be used during substitution in wordlist (default to TARGET).", default=False)
parser.add_argument("-p", dest="port", required=False, help="Set the port to use (default 80).", default=80)
parser.add_argument("-r", dest="real_port", required=False, help="The real port of the webserver to use in headers when not 80 (see RFC2616 14.23), useful when pivoting through ssh/nc etc (default to PORT).", default=False)
Expand All @@ -27,15 +27,34 @@ def main():
parser.add_argument('--unique-depth', dest='unique_depth', type=int, help='Show likely matches of page content that is found x times (default 1).', default=1)
parser.add_argument("--ssl", dest="ssl", action="store_true", help="If set then connections will be made over HTTPS instead of HTTP (default http).", default=False)
parser.add_argument("-oN", dest="output_normal", help="Normal output printed to a file when the -oN option is specified with a filename argument." )
arguments = parser.parse_args()

if not os.path.exists(arguments.wordlist):
print("[!] Wordlist %s doesn't exist, ending scan." % arguments.wordlistt)
sys.exit()

print("[+] Starting virtual host scan for %s using port %s and wordlist %s" % (arguments.target_hosts,
str(arguments.port),
arguments.wordlist))
parser.add_argument("-", dest="stdin", action="store_true", help="By passing a blank '-' you tell VHostScan to expect input from stdin (pipe).", default=False)

arguments = parser.parse_args()
wordlist = list()

if(arguments.stdin and not arguments.wordlist):
input = list(line for line in sys.stdin.read().splitlines())
wordlist.extend(input)
print("[+] Starting virtual host scan for %s using port %s and stdin data" % (arguments.target_hosts,
str(arguments.port)))
elif(arguments.stdin and arguments.wordlist):
if not os.path.exists(arguments.wordlist):
print("[!] Wordlist %s doesn't exist and can't be appended to stdin." % arguments.wordlist)
print("[+] Starting virtual host scan for %s using port %s and stdin data" % (arguments.target_hosts,
str(arguments.port)))
else:
wordlist_file = open(arguments.wordlist).read().splitlines()
wordlist.extend(wordlist_file)
print("[+] Starting virtual host scan for %s using port %s, stdin data, and wordlist %s" % (arguments.target_hosts,
str(arguments.port),
arguments.wordlist))
else:
# if no stdin, or wordlist pass, open default wordlist location
wordlist_file = open("./wordlists/virtual-host-scanning.txt").read().splitlines()
wordlist.extend(wordlist_file)
print("[+] Starting virtual host scan for %s using port %s and wordlist %s" % (arguments.target_hosts,
str(arguments.port),
"./wordlists/virtual-host-scanning.txt"))

if(arguments.ssl):
print("[>] SSL flag set, sending all results over HTTPS")
Expand All @@ -45,7 +64,8 @@ def main():
if(arguments.ignore_content_length > 0):
print("[>] Ignoring Content length: %s" % (arguments.ignore_content_length))

scanner = virtual_host_scanner(arguments.target_hosts, arguments.base_host, arguments.port, arguments.real_port, arguments.ssl, arguments.unique_depth, arguments.ignore_http_codes, arguments.ignore_content_length, arguments.wordlist)
scanner = virtual_host_scanner( arguments.target_hosts, arguments.base_host, wordlist, arguments.port, arguments.real_port, arguments.ssl,
arguments.unique_depth, arguments.ignore_http_codes, arguments.ignore_content_length)

scanner.scan()
output = output_helper(scanner)
Expand Down
8 changes: 3 additions & 5 deletions lib/core/virtual_host_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ class virtual_host_scanner(object):
output: folder to write output file to
"""

def __init__(self, target, base_host, port=80, real_port=80, ssl=False, unique_depth=1, ignore_http_codes='404', ignore_content_length=0,
wordlist="./wordlists/virtual-host-scanning.txt"):
def __init__(self, target, base_host, wordlist, port=80, real_port=80, ssl=False, unique_depth=1, ignore_http_codes='404', ignore_content_length=0):
self.target = target
self.base_host = base_host
self.port = int(port)
Expand All @@ -40,16 +39,15 @@ def __init__(self, target, base_host, port=80, real_port=80, ssl=False, unique_d
# store associated data for discovered hosts in array for oN, oJ, etc'
self.hosts = []

def scan(self):
virtual_host_list = open(self.wordlist).read().splitlines()

def scan(self):
if not self.base_host:
self.base_host = self.target

if not self.real_port:
self.real_port = self.port

for virtual_host in virtual_host_list:
for virtual_host in self.wordlist:
hostname = virtual_host.replace('%s', self.base_host)

headers = {
Expand Down
18 changes: 13 additions & 5 deletions lib/helpers/output_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@ def write_normal(self, filename):
file.write_file(self.generate_header() + self.output_normal_likely() + self.output_normal_detail())

def output_normal_likely(self):
output = "\n[+] Most likely matches with a unique count of {} or less:".format(str(self.scanner.unique_depth))
for p in self.scanner.likely_matches(): output += "\n\t[>] {}".format(p)

return output
uniques = False
depth = str(self.scanner.unique_depth)
output = "\n[+] Most likely matches with a unique count of {} or less:".format(depth)

for p in self.scanner.likely_matches():
output += "\n\t[>] {}".format(p)
uniques = True

if(uniques):
return output
else:
return "\n[!] No matches with a unique count of {} or less.".format(depth)

def output_normal_detail(self):
output = "\n\n[+] Full scan results"
Expand All @@ -35,4 +43,4 @@ def generate_header(self):
output += "\n\tReal Port {}\n\tIgnore HTTP Codes: {}".format(self.scanner.real_port,self.scanner.ignore_http_codes)
output += "\n\tIgnore Content Length: {}\n\tWordlist: {}".format(self.scanner.ignore_content_length, self.scanner.wordlist)
output += "\n\tUnique Depth: {}\n\tSSL: {}\n\t".format(self.scanner.unique_depth, self.scanner.ssl)
return output
return output

0 comments on commit 5111bea

Please sign in to comment.