有趣的請求參數/請求頭

參考

前言

加一個參數就是一個洞。在挖洞的時候,我注意到一些特殊的請求參數,好比說 outputretypecallbackfunwidthheight 等等,更改其中一些數值,返回包中會出現明顯變化。看了大師傅們的文章,才逐漸瞭解到這些參數以及一些特殊的 http 頭的妙用。此文做爲一個筆記梳理,並本身嘗試寫了一個簡單腳本(經測試,BUG 巨多😵),以避免去使用 BURP 測試那麼複雜。php

各類類型

CORS

衆所周知,更改 HTTP 的 Origin 頭即可以測試 CORS 漏洞。因此在碰到包含敏感信息的頁面的時候,即可以從新發包,加一個 Origin 頭。
可是怎麼可能這麼容易就挖到呢?不少網站在 Origin 頭處作了限制,沒有匹配其後臺規則便不會返回 Access-Control-Allow-Origin 等字段。
常見限制以下:html

Origin: https://test.com  # 白名單,只容許固定的域名
Origin: http://whatever.com  # 未作限制
Origin: http://test.com.evil.vom  # 域名前綴或必須包含特定域名字符串
Origin: http://sub.test.com  # 容許子域名

若是沒有匹配上述中的某些規則,網站便不會返回 Access-Control-Allow-Origin 字段,也就沒法判斷是否存在 CORS
當只測試了一種規則但其沒有匹配網站規則,看到沒有返回該字段是否就應該放棄?
其實否則,咱們能夠一個個添加/修改,每個可能的規則都試一遍。python

Content-Type

不知道師傅們碰到過可修改返回數據類型的參數沒有,常見的有 retypeoutputformatdatatype 等。
好比說 output=html、output=json、output=script 或者 retype=一、retype=二、retype=3,1234分別表明不一樣數據類型
看到下面一個接口的請求包:git

GET /api.php?kw=<img/src/onerror=alert(!)> HTTP/1.1
Host: test.cn
···

返回包爲:github

HTTP/1.1 200 OK
Content-Type: application/json
···

{"wd":"<img/src/onerror=alert(!)>"}

因爲嚴格限定了 Content-Type 頭,因此瀏覽器只會將其做爲 json 格式解析。
這個時候是否是沒辦法了,其實能夠嘗試添加一些參數
好比說加一個 ?retype=html 參數,返回包可能就會變成 Content-Type: text/html;charset=utf-8
此時瀏覽器便會將其解析爲 html 格式,因而一個反射型 xss 便有了。
固然得認可這個狀況很難利用(參數跟值都沒法肯定),而且也十分少見,可是在 jsonp 劫持的時候就不見得了。json

jsonp 劫持

在請求 json 格式的數據時,請求中常見 callback=testcall=testcb=testfunc=testjsoncallback=test 等參數
且此時返回包數據爲 test({"paramer":"value"})
例如:
api

能夠看到,burp 識別其爲 script 格式,當一個個在 burp 中尋找可能的 jsonp 劫持漏洞時,單找 script 格式的數據就會讓人瘋。由於不少 script 數據內容都是 js 函數
咱們再次看到上圖,有沒有發如今 script 那一欄有兩個 JSON 格式的數據?其實不少網站返回信息都爲 json 格式。當其中的數據爲敏感數據時,因爲沒有看到回調函數,如 callback 時,是否是這個點就沒法利用?
其實此時能夠測試能不能利用這些 json 格式的數據造一個 jsonp 劫持呢?此時重點來了:瀏覽器

當請求爲:安全

GET /getUser.php HTTP/1.1
Host: test.cn
Cookie: xxxxx
···

網站返回一個這樣的 json 數據包cookie

HTTP/1.1 200 OK
Content-Type: application/json
···

{"name":"R0oKi3","phone":"13888888888","addr":"湖南省長沙市···"}

是否是就不能繼續測試下一步呢?其實否則:
此時能夠修改請求包爲:

GET /getUser.php?callback=test HTTP/1.1
Host: test.cn
Cookie: xxxxx
···

網站即可能會返回:

HTTP/1.1 200 OK
Content-Type: application/json
···

test({"name":"R0oKi3","phone":"13888888888","addr":"湖南省長沙市···"});

當其餘限制(referer、token)不嚴格時,一個 jsonp 劫持漏洞便有了。

固然,大多 json 格式的數據內容是不包含敏感信息的,那麼是否是就沒用了?其實也否則。
當用戶可控 Content-Type (也就是上一個點)時,而且也能構成不含敏感信息的 jsonp 劫持時,此時即可以考慮構成反射型 xss
http://test.cn/getUser.php?callback=<img/src/onerror=alerrt(1)>&retype=html 即可以造成反射型 xss,由於其返回的數據包中含:Content-Type: text/html;charset=utf-8,瀏覽器將該數據包解析成了 html 格式

驗證碼 Dos

右鍵打開驗證碼/二維碼等圖片的連接,若是看到參數中存在某些鍵值對,如 width=20&heigth=15 等,而且改變其數值大小時,驗證碼圖片大小也跟着改變時,即可能形成驗證碼 Dos
當沒有這些參數時,即可以考慮本身添加,如 https://test.com/captcha.php?width=2000&height=20000,fuzz 出這些參數,來形成 Dos
而且,當 fuzz 出一個能夠控制驗證碼位數的參數時,如 n=4,也能夠將其改成 0 等數字,嘗試是否能使驗證碼失效,或者改成很大的數值,若是圖片大小跟驗證碼位數相關的話,也能形成 Dos

在 cookie 中添加一些字段,可能會致使未受權訪問

admin=true
access=1
debug=true

具體可見:個人Web應用安全模糊測試之路

小腳本 EasyFuzz.py

"""
python3 EasyFuzz.py -u https://test.com -m jsonp
-u 或者 -url  指定 url
-m 或者 -method 指定要探測的可能漏洞,暫時有的選項有 cors jsonp img 三種漏洞的探測
注意,在傳輸 url 參數時,url中有 & 符號與要用雙引號包裹起來,不然會報錯
因爲沒有采用多線程,因此會丶慢
"""
import requests
import argparse
import re
from tld import get_fld

jsonps = ["callback", "_callback", "func", "cb", "_cb", "jsonp", "jsonpcallback", "jsonpcb", "json", "jsoncallback", "jbc", "jsonp_cb", "call", "callBack", "jsonCallback", "jsonpCb", "ca", "jsonp_Cb"]

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}


def send(url):
    rep = requests.get(url, headers=headers)
    return rep


def CorsFuzz(url):
    # 獲取本域名
    subdomin = re.findall(r'(http.*://[^/]*)', url, re.DOTALL)[0]
    protocol = re.findall(r'(http.*://)', url, re.DOTALL)[0]
    # 獲取主域名
    domain = get_fld(subdomin)
    # print(subdomin,domain)
    # 建立 cors 字典 自己 主域名 任意域名 以其開頭 其餘子域名
    cors = [subdomin, protocol + domain, protocol + "test.com", protocol + domain + ".test.com", protocol + "test." + domain]
    # print(cors)
    flag = 0
    for cor in cors:
        headers["Origin"] = cor
        print("------Origin: " + cor)
        try:
            # 獲取響應頭
            # print(url)
            reph = send(url).headers
            # print(reph)
            if "Access-Control-Allow-Origin" in str(reph):

                print(url + "存在 CORS,其 Origin 頭爲" + cor + "\n返回值爲 Access-Control-Allow-Origin:" + reph["Access-Control-Allow-Origin"])
                flag = 1
        except:
            print(url + " 請求錯誤")
    if flag == 0:
        print(url+" 不存在 CORS 漏洞")


def JsonpFuzz(url):
    flag = 0
    for jsonp in jsonps:
        jsonp = jsonp + "=myJsonpFunc"
        try:
            if "?" in url:
                newurl = url + "&" + jsonp
                print("------" + newurl)
                rep = send(newurl).content.decode("utf-8")
            else:
                newurl = url + "?" + jsonp
                print("------" + newurl)
                rep = send(newurl).content.decode("utf-8")
            if "myJsonpFunc" in rep:
                flag = 1
                print(url + "可能存在 jsonp 劫持,回調函數爲:" + jsonp)
                break
        except:
            print(url + " 請求錯誤")
    if flag == 0:
        print(url+" 不存在 jsonp 回調函數")

def ImgFuzz(url):
    # 獲取原數據大體大小
    repl = len(send(url).content)
    par = "height=250&width=250&w=250&h=250&size=250&margin=250&font_size&=250length=250"
    try:
        if "?" in url:
            print(url + "&" + par)
            newl = len(send(url + "&" + par).content)
        else:
            print(url + "&" + par)
            newl = len(send(url + "?" + par).content)
    except:
        print(url + " 請求錯誤")
    if abs(newl - repl) >= 1000:
        # 當數據大小相差 1000 時
        print(url + "可能存在驗證碼 Dos\n測試參數爲:" + par)



def main(url, method):
    if method=="cors":
        CorsFuzz(url)
    elif method=="jsonp":
        JsonpFuzz(url)
    else:
        ImgFuzz(url)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Easy Fuzz')
    parser.add_argument("-u", "--url", help="指定URL", default="img")
    parser.add_argument("-m", "--method", help="指定操做")
    args = parser.parse_args()
    url = args.url
    method = args.method
    # url = "https://baidu.com"
    # method = "cors"
    main(url, method)
相關文章
相關標籤/搜索