# web
## ez_path
在文章中给出了一个 result.pyc
,先对其进行反编译
```python
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.6
import os
import uuid
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
ARTICLES_FOLDER = 'articles/'
articles = []
class Article:
def init(self, article_id, title, content):
self.article_id = article_id
self.title = title
self.content = content
def generate_article_id():
return str(uuid.uuid4())
def index():
return render_template('index.html', articles, **('articles',))
index = app.route('/')(index)
def upload():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
article_id = generate_article_id()
article = Article(article_id, title, content)
articles.append(article)
save_article(article_id, title, content)
return redirect('/')
return None('upload.html')
upload = app.route('/upload', [
'GET',
'POST'], **('methods',))(upload)
def article(article_id):
for article in articles:
if article.article_id == article_id:
title = article.title
sanitized_title = sanitize_filename(title)
article_path = os.path.join(ARTICLES_FOLDER, sanitized_title)
with open(article_path, 'r') as file:
content = file.read()
return render_template('articles.html', sanitized_title, content, article_path, **('title', 'content', 'article_path'))
return render_template('error.html')
article = app.route('/article/<article_id>')(article)
def save_article(article_id, title, content):
sanitized_title = sanitize_filename(title)
article_path = ARTICLES_FOLDER + '/' + sanitized_title
with open(article_path, 'w') as file:
file.write(content)
def sanitize_filename(filename):
sensitive_chars = [
':',
'*',
'?',
'"',
'<',
'>',
'|',
'.']
for char in sensitive_chars:
filename = filename.replace(char, '_')
return filename
if name == '__main__':
app.run(True, **('debug',))
```
其中利用了 os.path.join
的方法进行路径拼接,但实际上这个方法存在路径穿越漏洞(python 3.6)
例如
```
# os.path.join >>> os.path.join('/micdy/', '../../../etc/passwd')
>
/micdy/../../../etc/passwd
```
这样就可以回溯路径直接访问 /etc/passwd
,达到目录穿越的效果
python 3.6 中此方法还有一个机制,在拼接的过程中,如果某个路径的部分为绝对路径,则会抛弃之前所有的部分,直接使用绝对路劲的部分继续拼接。于是可以使用此方法穿越到任何路径
```
os.path.join('/micdy/home', '/opt/app/')
>
/opt/app
```
在源代码中
```python
article_path = os.path.join(ARTICLES_FOLDER, sanitized_title)
"""
其中对ARTICLES_FOLDER 和 sanitized_title 进行拼接
ARTICLES_FOLDER = 'articles/', 根据源码 title 由我们直接传入。
也对一些非法字符进行替换,但对我们没有什么影响
"""
```
题目也提示我们要穿越的路径
```
<!--secret在根目录f14444文件里面,别忘记了-->
```
路径为根目录,文章路径的拼接为全局变量和我们传入的文章title进行拼接,由于拼接到根目录,所以之前的路径会全部被抛弃
```
os.path.join('articles/', '/f14444')
>
/f14444
```
将上传的title设置为flag路径即可
```
# /f14444
GEEK{d6d4b9c8-d543-420d-8857-a0645d2db109}
Article Path: /f14444
```