๊ธ€ ์ž‘์„ฑ์ž: heogi

python์˜ starlette ํ”„๋ ˆ์ž„์›Œํฌ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ๋ฉ”๋ชจ ๊ธฐ๋Šฅ์˜ ํŽ˜์ด์ง€์ด๋‹ค.

 

๋ฉ”์ธ ํŽ˜์ด์ง€์™€ /view, /reset, /save ์˜ ๊ฒฝ๋กœ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

 

path traversal ์ทจ์•ฝ์ ์„ ํ†ตํ•ด flag๋ฅผ ํš๋“ํ•ด์•ผํ•˜๋Š”๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

 

์ทจ์•ฝํ• ๊ฑฐ๊ฐ™์€ ๋ถ€๋ถ„์„ ํ™•์ธํ•ด๋ณด๋ฉด ์•„๋ž˜ /view ํŽ˜์ด์ง€๊ฐ€ ์ทจ์•ฝํ•ด ๋ณด์ธ๋‹ค.

def view(request):
    context = {}

    try:
        context['request'] = request
        clientId = getClientID(request.client.host)

        if '&' in request.url.query or '.' in request.url.query or '.' in unquote(request.query_params[clientId]):
            raise
        
        filename = request.query_params[clientId]
        path = './memo/' + "".join(request.query_params.keys()) + '/' + filename
        
        f = open(path, 'r')
        contents = f.readlines()
        f.close()
        
        context['filename'] = filename
        context['contents'] = contents
    
    except:
        pass
    
    return templates.TemplateResponse('/view/view.html', context)

request.url.query์— &, . ์ด ํฌํ•จ๋˜์–ด์žˆ์œผ๋ฉด ์•ˆ๋˜์–ด์„œ ์šฐํšŒํ•  ๋ฐฉ๋ฒ•์ด๋‚˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์ด ํ•„์š”ํ•œ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

ํ•˜์ง€๋งŒ starlette ์˜ ๊นƒํ—™ํŽ˜์ด์ง€์— ๋ณด๋ฉด ์ด๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ ์ด ์ด์Šˆ๋กœ ์˜ฌ๋ผ์˜จ๊ฒƒ์ด์žˆ๋‹ค.

 

https://github.com/encode/starlette/issues/1325

 

Incorrect handling query parameters containing semicolons · Issue #1325 · encode/starlette

Describe the bug It seems Starlette treats the semicolon as a parameter separator, which is incorrect. IMHO, this is a critical bug that makes it impossible to use Starlette in many scenarios. Othe...

github.com

;(์„ธ๋ฏธ์ฝœ๋ก )์ด ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ตฌ๋ถ„์ž๋กœ ์ธ์‹๋˜๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋‹ค๋Š” ๋‚ด์šฉ์ด๋‹ค.

ํ•ด๋‹น ์ทจ์•ฝ์ ์„ ํ†ตํ•ด ์•„๋ž˜ ํŽ˜์ด๋กœ๋“œ๋กœ ๊ณต๊ฒฉ์„ ์ง„ํ–‰ํ•ด๋ณด๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.

/view?d54a71d5bcf9c5b93756ad0c97b2d830=flag;/%2e%2e

ํ•ด๋‹น ๋ฒ„๊ทธ๋Š” starlette์—์„œ ๋ฐœ์ƒํ•˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํŠน์ • urllib์—์„œ ๋ฐœ์ƒํ•˜๋Š”๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

https://python-security.readthedocs.io/vuln/urllib-query-string-semicolon-separator.html

 

urllib parse_qsl(): Web cache poisoning - semicolon as a query args separator — Python Security 0.0 documentation

The urlparse module treats semicolon as a separator, whereas most proxies today only take ampersands as separators. When the attacker can separate query parameters using a semicolon ;, they can cause a difference in the interpretation of the request betwee

python-security.readthedocs.io

๊ฐ„๋‹จํžˆ docker ํ™˜๊ฒฝ ๊ตฌ์„ฑํ•˜์—ฌ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๋‹ˆ

from flask import Flask, request, render_template_string
from urllib.parse import urlparse, parse_qs, parse_qsl

app = Flask(__name__)

@app.route("/")
def index():
	data = request.args.to_dict()
	data2 = urlparse(request.url)
	data2 = parse_qs(data2.query)

	print(data)
	template = '''<h1> what is template ?? is <span style="color:grey">{}</span>//**//<span style="color:grey">{}</span></h1>'''.format(data,data2)
	return render_template_string(template)

if __name__=="__main__":
	app.run()

flask์˜ request๋กœ ํ™•์ธํ•œ ๋ถ€๋ถ„๊ณผ urllib์„ ํ†ตํ•ด parse ํ–ˆ์„๋•Œ flask์—์„œ๋Š” ; ์ด ๊ตฌ๋ถ„์ž๋กœ ์‚ฌ์šฉ์ด ์•ˆ๋˜์ง€๋งŒ

urllib์œผ๋กœ parse ํ–ˆ์„๋•Œ๋Š” ; ๋„ ๊ตฌ๋ถ„์ž๋กœ ์‚ฌ์šฉ๋˜๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

http://172.17.0.3:5000/?data=213;test=213&t1=222

 

'๐Ÿ›ก๏ธCTF > LineCTF' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

LineCTF(2023) - Adult Simple GoCurl  (0) 2023.08.13
LineCTF(2023) - Baby Simple GoCurl  (0) 2023.08.13
LineCTF 2022 - gotm  (0) 2022.03.29