[第一章] web入门—N1book靶场详细思路讲解(二)

发布于:2025-09-15 ⋅ 阅读:(20) ⋅ 点赞:(0)

今天继续给大家带来N1book靶场的第一章讲解,这些题目虽然不难,但还是很好的基础练习题;


afr_1

这里我们进入靶场后,发现了页面所示:

在这里插入图片描述

url后面还跟着一个参数p,这个题目难道是可以什么命令执行吗?
我们先对他进行信息收集一波:
在这里插入图片描述

我们重点关注.php flag.php这两个目录,因为后面的两个都会重定向到p=hello,应该是存在身份认证之类的;

做题思路

(1)尝试访问那两个目录:
在这里插入图片描述
在这里插入图片描述
发现访问不了。。

(2)接下来我就想着p参数有什么用呢,应该如何让他显示别的东西(所以这里我就尝试进行命令执行

尝试了几个参数:

?p=system('ls');
?p=tac%09fla*;
?p=/bin/base64 flag.php

发现返回的都是空白页面;

(3)随后我就想着要不用命令包含,php伪协议等方法继续试试?

# payload
?p=php://filter/convert.base64-encode/resource=index

没想到尝试了index.php没有用,去除掉.php后缀后,出现了base64编码的源代码:
在这里插入图片描述

可以看到源代码显示如下:
在这里插入图片描述

页面源代码:

<?php

if(isset($_GET['p'])) {
    include (string)$_GET['p'] . ".php";
}
else{
    header('Location: /?p=hello');
}

我们可以看到代码是通过$_GET['p']传参,来访问文件的;如果目录中不存在文件,就会重定向到初始页面?p=hello

这不简单了嘛,之前信息收集不还有flag.php文件吗:
在这里插入图片描述

也是成功得到了flag:
在这里插入图片描述

n1book{afr_1_solved}

afr_2

这个开幕雷击,一进去就看到老艺术家(这是动图):

在这里插入图片描述
查看源代码也没发现什么,所以只能先扫一波了:

在这里插入图片描述

还真让我们扫出来几个目录,访问一下/img/

在这里插入图片描述

发现了当前目录,那么我们是不是可以进行任意目录访问了?

  • 任意目录访问
    • 任意目录访问是一种常见的网络安全漏洞,指攻击者通过构造特殊的访问路径(如利用“../”等目录遍历字符),绕过系统原本的目录访问限制;
    • 非法访问服务器或应用程序中本不应开放的目录(如系统根目录、用户隐私文件目录等),甚至可能进一步读取、修改或删除其中的敏感文件,对数据安全和系统稳定性造成威胁。
  • 常见的payload
  • Linux系统:
    • ../:单次返回上一级目录
    • ../../:两次返回上一级目录
    • ../../../:多次叠加,直到突破到系统根目录
  • Windows系统:
    • ..\:Windows 系统专用(路径分隔符为 “\”)
    • 例如 “..\..\windows\system32\drivers\etc\hosts”(读取 Windows 的 Hosts 文件)

解题过程

所以我们也可以构造payload,来访问它的根目录:/img…/

在这里插入图片描述

可以看到我们访问到了他的根目录,并发现了flag目录,那接下来干什么还不是手到擒来吗?

把它下载下来,用文本打开:

在这里插入图片描述
也是成功拿到flag:

n1book{afr_2_solved}

afr_3(新知识点)

这里我们打开看到页面如下:

在这里插入图片描述

然后我们发现了一个框,尝试随便输入什么,就会返回固定一段话:

在这里插入图片描述
在这里插入图片描述

正常来说我们遇到框不都是sql,xss等方法吗?(xss查看源代码,并没有前端代码,应该是做了分离)

那么sql注入呢?用bp抓了个包,但没测试出来:

python sqlmap.py -r 1.txt

尝试看看有没有漏洞:
在这里插入图片描述

显示结果:
在这里插入图片描述

那我没招了兄弟,只能尝试爆破一下路径了:
在这里插入图片描述

结果发现所有状态码都是200,不能吧

在这里插入图片描述

于是就一个个查看响应包,发现正常的包都会返回:“Hello : \\\\\bootini , why you don’t look at our <

在这里插入图片描述

但是接下来呢?

网上WP

参考文章:文章一
文章二

发现考点是linux /proc的相关内容:

发现人家通过GET访问article?name=../../../proc/self/cmdline 得到了一个文件名:

(而我之前都是尝试爆破POST方式的n1page参数,又没仔细审题)

article?name=../../../proc/self/cmdline

在这里插入图片描述

查看server.py文件:
在这里插入图片描述

#!/usr/bin/python
import os
from flask import (
    Flask,
    render_template,
    request,
    url_for,
    redirect,
    session,
    render_template_string
)
from flask_session import Session

app = Flask(__name__)

# 执行外部文件获取flag和密钥
execfile('flag.py')
execfile('key.py')
FLAG = flag
app.secret_key = key


@app.route("/n1page", methods=["GET", "POST"])
def n1page():
    if request.method != "POST":
        return redirect(url_for("index"))
    
    n1code = request.form.get("n1code") or None
    if n1code is not None:
        # 过滤掉特定字符:. _ { }
        n1code = n1code.replace(".", "").replace("_", "").replace("{", "").replace("}", "")
    
    # 将处理后的n1code存入session
    if "n1code" not in session or session['n1code'] is None:
        session['n1code'] = n1code
    
    template = None
    if session['n1code'] is not None:
        # 渲染包含用户输入的模板字符串
        template = '''
        <h1>N1 Page</h1>
        <div class="row">
            <div class="col-md-6 col-md-offset-3 center">
                Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>?
            </div>
        </div>
        ''' % session['n1code']
    
    # 清空session中的n1code
    session['n1code'] = None
    return render_template_string(template)


@app.route("/", methods=["GET"])
def index():
    return render_template("main.html")


@app.route('/article', methods=['GET'])
def article():
    error = 0
    if 'name' in request.args:
        page = request.args.get('name')
    else:
        page = 'article'
    
    # 禁止访问包含'flag'的文件
    if page.find('flag') >= 0:
        page = 'notallowed.txt'
    
    try:
        # 读取指定路径的文章文件
        template = open('/home/nu11111111l/articles/{}'.format(page)).read()
    except Exception as e:
        template = e  # 捕获异常并返回错误信息
    
    return render_template('article.html', template=template)


if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=False)

代码分析:

  • 初始化配置

    • 导入 Flask 及相关模块,创建 Flask 应用实例。
    • 通过execfile执行外部的flag.py和key.py,获取flag(可能是敏感信息)和key(作为 Flask 的 session 密钥)。
  • /n1page 路由(处理 GET 和 POST 请求)

    • 仅接受 POST 请求,若为 GET 请求则重定向到首页。
    • 从表单中获取n1code参数,过滤掉._{}这 4 种字符(可能是为了防御模板注入)。
    • 将处理后的n1code存入 session,然后使用render_template_string动态渲染包含n1code的 HTML 模板。
    • 渲染后清空 session 中的n1code,避免重复使用。
  • / 路由(首页)

    • 仅处理 GET 请求,返回main.html模板页面。
  • /article 路由(文章查看功能)

    • 过 URL 参数name指定要查看的文章(默认查看article文件)
    • 若参数中包含flag字符串,则强制改为查看notallowed.txt(防止直接访问包含 flag 的文件)。
    • 尝试读取**/home/nu11111111l/articles/**目录下的指定文件,若读取失败则返回异常信息。

SSTI(服务器端模板注入)介绍:

  • SSTI 是指攻击者通过构造恶意输入,注入到服务器端模板引擎中被执行,从而获取服务器权限、敏感数据或执行恶意操作的漏洞。
  • 核心原因是模板引擎未对用户输入做严格过滤,直接将用户可控内容拼接到模板代码中编译执行。

解题步骤

接下来考虑的是怎么样获得权限,去读取flag

  1. 先读一下key得到如下信息:#!/usr/bin/python key = 'Drmhze6EPcv0fN_81Bj-nA'

在这里插入图片描述

article?name=../../../proc/self/cwd/key.py
  1. 接下来用key开始伪造,伪造flask的session:flask-session-cookie-manager

(接下大家看这位师傅的文章吧,SSTI我也是第一次遇到,不懂怎么做题)

后面的步骤:

  • 大概就是通过生成SSTI语句
  • 并且配合上面的flask工具构造出一个伪造的session
  • bp抓包改包一下,即可得到flag;

总结

其实除了第三题,前面两题相信大家都能够做出了。(SSTI到底是什么啊,头都要晕了)