Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
bonifield committed Aug 18, 2021
1 parent b26d4df commit 295e277
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 57 deletions.
78 changes: 42 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ scan a URL using a given wordlist with optional URL transformations
pip install requestinjector
```

### Usage (Command Line Tool or Standalone Script Somewhere in $PATH)
```
requestinjector -u "http://example.com/somepath/a/b/c" -w "/path/to/wordlist.txt" -t 10 -m True -r 2 \
-p '{"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}' \
-H '{"Content-Type": "text/plain"}' \
--color True --simple_output True
Arguments:
REQUIRED: -u [URL] = provide a URL
REQUIRED: -w [WORDLIST] = provide a path to a wordlist (note: when importing as a module, this can also be a Python list)
-t [NUM] = number of threads (default 10); each thread uses every URL mutation to check the current word
-m True = mutate the path to check all subpaths, ex. check "http://example.com/WORD", "http://example.com/somepath/WORD", "http://example.com/somepath/a/WORD", "http://example.com/somepath/a/b/WORD", and "http://example.com/somepath/a/b/c/WORD"
-r [NUM] = number of retries to check a domain that can't be reached, before continuing on with other URLs (default 1)
-H [HEADERDICT] = dictionary of header information
- MUST use single-quotes to wrap the dictionary, and double-quotes to wrap the keys and values, ex. '{"Content-Type": "application/json"}'
- defaults added unless otherwise specified:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
-p [PROXYDICT] = dictionary of proxy information
- MUST use single-quotes to wrap the dictionary, and double-quotes to wrap the keys and values, ex. '{"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}'
--color True = colorize stdout, forces simple_output format
--simple_output True = only show the response status code, and the URL checked
```

### Usage (Importable Module)
```
from requestinjector import RequestInjector
Expand All @@ -18,47 +42,29 @@ x = RequestInjector(url=url, wordlist="/path/to/wordlist.txt", threads=10, mutat
x.run()
```

### Usage (Command Line Tool) COMING SOON
```
requestinjector.py -u "http://example.com/somepath/a/b/c" -w "/path/to/wordlist.txt" -m True -r 2 -p '{"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}' -H '{"Content-Type": "text/plain"}' --color True --simple_output True
-u [URL] = provide a URL
-w [WORDLIST] = provide a path to a wordlist (note: when importing as a module, this can also be a Python list)
-m True = mutate the path to check all subpaths, ex. check ""http://example.com/WORD", "http://example.com/somepath/WORD", "http://example.com/somepath/a/WORD", "http://example.com/somepath/a/b/WORD", and "http://example.com/somepath/a/b/c/WORD"
-r [NUM] = number of retries to check a domain that can't be reached, before continuing on with other URLs
-H [HEADERDICT] = dictionary of header information, with single-quotes wrapping the dictionary and double-quotes wrapping the keys and values, ex. '{"Content-Type": "application/json"}'
-p [PROXYDICT] = dictionary of proxy information, with single-quotes wrapping the dictionary and double-quotes wrapping the keys and values, ex. '{"Content-Type": "application/json"}'
--color True = colorize stdout, forces simple_output format
--simple_output True = only show the response status code, and the URL checked
```

### Example Output
```
# Standard Format
status_code:404 bytes:12 word:x ip:127.0.0.1 port:8080 url:http://example.com/x
status_code:404 bytes:12 word:z ip:127.0.0.1 port:8080 url:http://example.com/z
status_code:404 bytes:12 word:test ip:127.0.0.1 port:8080 url:http://example.com/test
status_code:200 bytes:411 word:somepath ip:127.0.0.1 port:8080 url:http://example.com/somepath
status_code:404 bytes:12 word:doesnotexist ip:127.0.0.1 port:8080 url:http://example.com/doesnotexist
status_code:200 bytes:556 word:u ip:127.0.0.1 port:8080 url:http://example.com/somepath/u
# Provided URL: http://example.com/somepath/exists
status_code:404 bytes:12 word:contactus ip:127.0.0.1 port:8080 url:http://example.com/contactus
status_code:404 bytes:12 word:contactus ip:127.0.0.1 port:8080 url:http://example.com/somepath/contactus
status_code:200 bytes:411 word:contactus ip:127.0.0.1 port:8080 url:http://example.com/somepath/exists/contactus
status_code:404 bytes:12 word:admin ip:127.0.0.1 port:8080 url:http://example.com/admin
status_code:200 bytes:556 word:admin ip:127.0.0.1 port:8080 url:http://example.com/somepath/admin
status_code:200 bytes:556 word:admin ip:127.0.0.1 port:8080 url:http://example.com/somepath/exists/admin
# Simplified Format (simple_output)
404 http://example.com/somepath/v
200 http://example.com/somepath
200 http://example.com/somepath/u
404 http://example.com/contactus
404 http://example.com/somepath/contactus
200 http://example.com/somepath/exists/contactus
404 http://example.com/admin
200 http://example.com/somepath/admin
200 http://example.com/somepath/exists/admin
```

### Future Improvements
- Add "Modes" to try various requests
- query mode
- fragment mode
- body mode
- multiple request methods

### TODO
- better injection handlers
- map get history length against head history length to check body redirects
- body POST/PUT JSON objects, using a config possible
- encodings
- query/fragment/body modes
- better output handling to support response body content, headers sent/received, etc
- query/fragment/body modes, recursive grep, method select/switching
- redirect history handling
- body POST/PUT objects, possibly using a config
- optional encodings
- better output handling to support response body content, headers sent/received, etc
50 changes: 31 additions & 19 deletions requestinjector.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
#!/usr/bin/python3

#=======================================================
#
# last updated 2021-08-17
# Request Injector by Bonifield (https://github.com/bonifield)
#
# v0.9.2
# Last Updated: 2021-08-18
#
# requestinjector.py -u "http://example.com/somepath/a/b/c" -w "/path/to/wordlist.txt" -t 10 -m True -r 2 \
# -p '{"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}' \
# -H '{"Content-Type": "text/plain"}' \
# --color True --simple_output True
#
# or import as a module (from requestinjector import RequestInjector)
#
#=======================================================

import argparse
import json
Expand Down Expand Up @@ -263,7 +275,6 @@ def run(self):
threads = []
# begin loading words into queuein
f = Filler(queuein, self.wordlist)
#f = Filler(queuein, "/home/kali/ri-words.txt")
f.name = "Filler"
f.start()
threads.append(f)
Expand All @@ -288,20 +299,8 @@ def run(self):



#=========================================



if __name__ == "__main__":

# requestinjector.py -u "http://example.com/somepath/a/b/c" -w "/path/to/wordlist.txt" -m True -r 2
# -p '{"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}'
# -H '{"Content-Type": "text/plain"}'
# dictionary MUST be wrapped in single-quotes, and keys and values MUST be wrapped in double-quotes

# time script execution
startTime = time.time()

def tool_entrypoint():
"""this function handles argparse arguments and serves as the entry_points reference in setup.py"""
# collect command line arguments
parser = argparse.ArgumentParser(description="RequestInjector: scan a URL using a given wordlist with optional URL transformations")
# optional arguments
Expand All @@ -327,13 +326,26 @@ def run(self):
wordlist = args["wordlist"]
color = args["color"]
simple_output = args["simple_output"]

x = RequestInjector(url=url, wordlist=wordlist, threads=threads, mutate_path=mutate_path, headers=headers, proxy=proxy, retries=retries, simple_output=simple_output, color=color) #, simple_output=True)
x.run()



#=========================================



# this allows the script to be invoked directly (if the repo was cloned, if just this file was downloaded and placed in some bin path, etc)
# note the time message gets sent to stderr, just 2> /dev/null or comment it out if undesired
if __name__ == "__main__":

# time script execution
startTime = time.time()

tool_entrypoint()

# time script execution
endTime = time.time()
totalTime = endTime - startTime
sys.stderr.write(f"took {totalTime} seconds\n")
sys.exit(0)

sys.exit(0)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = requestinjector
version = 0.9.1
version = 0.9.2
author = James Bonifield
author_email = bonifield.tools@gmail.com
description = scan a URL using a given wordlist with optional URL transformations
Expand Down
9 changes: 8 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
from setuptools import setup

setup(py_modules=["requestinjector"])
setup(
py_modules=["requestinjector"],
entry_points={
"console_scripts":[
"requestinjector = requestinjector:tool_entrypoint"
]
}
)

0 comments on commit 295e277

Please sign in to comment.