Execute ffuf from an Orgmode Babel source code block by providing a raw HTTP request.
Write your HTTP request (or use one obtained via an intercepting proxy) inside a source code block with wordlist input denoted by FUZZ
(or custom keywords, see ffuf). Input either comes from an Orgmode table or a wordlist file.
Further configuration may come either by specifying a user config file or by naming another source code block with configuration inside it.
Checkout the repository and add the resulting directory in your Emacs load-path
(see C-h v load-path
) and then (require 'ob-ffuf)
.
(add-to-list 'load-path "/path/to/ob-ffuf")
(require 'ob-ffuf)
#+NAME: dirs
| admin |
| uploads |
| private |
\#+BEGIN_SRC ffuf :wordlist-table dirs
GET http://example.com/FUZZ HTTP/1.1
Host: example.com
User-Agent: ob-ffuf
Accept: text/html
Accept-Language: en-US
Connection: keep-alive
\#+END_SRC
This will result in three requests:
http://example.com/admin
http://example.com/uploads
http://example.com/private
NOTE: Because the table has only one column, no header is needed. The fuzzing keyword defaults to FUZZ
, thus the above table is equivalent to:
#+NAME: dirs
| FUZZ |
|---------|
| admin |
| uploads |
| private |
Multiple ad-hoc wordlists are specified like the following. The table headers will be the keywords:
#+NAME: asdf
| FOO | BAR |
|-------+-------|
| hello | world |
| good | day |
NOTE: Tables with more than one column must have one header per column.
If further configuration is required, a config block can be used:
#+NAME: config
\#+BEGIN_SRC toml
[general]
quiet = true
[input]
inputmode = "pitchfork"
\#+END_SRC
\#+BEGIN_SRC ffuf :wordlist-table asdf :config-block config
GET http://example.com/FOO/BAR HTTP/1.1
Host: example.com
User-Agent: ob-ffuf
Accept: text/html
Accept-Language: en-US
Connection: keep-alive
\#+END_SRC
NOTE: Every input from within Orgmode must have a #+NAME
tag and supplied via the custom header arguments.
If existing wordlist files and / or configuration need to be supplied, do it like so:
\#+BEGIN_SRC ffuf :wordlist-files ("/first/wordlist.txt:FOO" "/second/wordlist.txt:BAR") :config-file "/path/to/config.toml"
GET http://example.com/FOO/BAR HTTP/1.1
Host: example.com
User-Agent: ob-ffuf
Accept: text/html
Accept-Language: en-US
Connection: keep-alive
\#+END_SRC
NOTE: If there is only a single wordlist file, it can be specified as a single string: =:wordlist-files “/path/to/wordlist.txt”=.
:wordlist-table | Named Orgmode table which will be converted into wordlist and fed into ffuf . |
:wordlist-files | A list of paths to wordlist files, or a single string, if it is a only one wordlist file. Will be combined with :wordlist-table . |
:config-block | An Orgmode source code block in ffuf config file format. See ffufrc.example. These are intended to not overburden the block header with arguments. |
:config-file | A path to a custom config file. |
ob-ffuf
starts an asynchronous process, thus Emacs does not block. The result is collected inside a temporary buffer and inserted below the block after ffuf exited. I have no idea yet what happens, if two runs are started at the same time.
ffuf’s error stream is captured in the *ob-ffuf stderr*
buffer. So if errors are encountered, they may be investigated there.
ob-ffuf
was not made with long fuzzing campaigns in mind, although I guess it is possible to log into a remote machine which is running an Emacs server with the ob-ffuf
package installed.
I document my pentesting work with Orgmode anyway, so if I want to try a few very specific payloads, I can do it with ob-ffuf
and later export my findings.
:)
ob-ffuf
is licensed under the GNU General Public License Version 3.