Fork me on GitHub

Google ctf2017

有时候看看国外的ctf比赛的wp还是挺好的

wp

Mindreder


可以通过f参数直接读取到想读的文件

那么如何确定flag的位置?

既然可以读文件,那么第一步的想法就是读源码

requirement

确定后端是flask

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from flask import Flask, request, abort
import re
import os
import logging

assert os.environ['FLAG']

app = Flask(__name__)

INDEX = open('index.html').read()

HALL_OF_SHAME = [
'173.171.203.59',
'2a02:6b8:b010:6026:84:201:185:197',
'35.185.158.159',
'81.17.25.8'
]

@app.route('/')
def index():
for ip in request.headers.get('X-Forwarded-For', '').split(','):
ip = ip.strip().lower()
if ip in HALL_OF_SHAME:
abort(403)

if 'f' in request.args:
try:
f = request.args['f']
if re.search(r'proc|random|zero|stdout|stderr', f):
abort(403)
elif '\x00' in f:
abort(404)
return open(f).read(4096)
except IOError:
abort(404)
else:
return INDEX

看到flag是藏在环境变量里面的,而环境变量就在/proc/environ

那就直接去读呗

但是限制了:

1
2
3
4
5
6
if 'f' in request.args:
try:
f = request.args['f']
if re.search(r'proc|random|zero|stdout|stderr', f):
abort(403)
elif '\x00' in f:

Linux中有一个叫做symlink method
也就是相当于一个快捷方式,但是却不同于Windows中的shortcut
而正好:/dev/fd这个指向了/proc/self/fd这样payload就不难理解了:
/dev/fd/../environ
访问/dev/fd就相当于访问了/proc/self之后回退一次就可以找到environ这个文件了

Linux中 /dev/fd/0运行效果是这样的,相当于你输入啥它就会回答啥

1
2
3
4
5
 ✘ pxy@LAPTOP-UBIEP4K5  ~  sudo cat /dev/fd/0
a
a
pxy
pxy

接下来了解一下ln命令

  • 软链接:英文symbolic link非常类似于Windows中的快捷方式
  • 硬链接:英文hard link这类文件会拥有自己的inode节点和名称,其inode会指向文件内容所在的数据块emmm后面不是很懂了

建立软链接的方式:
ln -s 源文件名称 软链接文件名称
目录和文件均可

现在当前目录下创建一个指向/proc/sys的链接

然后我们就可以通过目录遍历来进入到其他的目录了。

软链接还会存在这个问题:

链接的重复定义

这样就不会出问题了,加个-n选项

参考
GoogleCTF - Mindreader