@app.route('/file', methods=['GET'])
def file():
path = request.args.get('path', None)
if path:
data = open('./files/' + path).read()
return data
return 'Error !'
/file 경로에서는 path 파라미터에 따라, 파일을 읽어온다. 먼저, /etc/passwd 파일을 읽어올 수 있는지 확인해 보았다.
API_KEY = os.environ.get('API_KEY', None)
def key_required(view):
@wraps(view)
def wrapped_view(**kwargs):
apikey = request.args.get('API_KEY', None)
if API_KEY and apikey:
if apikey == API_KEY:
return view(**kwargs)
return 'Access Denied !'
return wrapped_view
@app.route('/admin', methods=['GET'])
@key_required
def admin():
cmd = request.args.get('cmd', None)
if cmd:
result = subprocess.getoutput(cmd)
return result
else:
return 'Error !'
위 코드를 보면, /admin 경로 요청 시, @Key_required 데코레이터에 의해 요청이 검증된 후 apikey를 비교하여, 일치하지 않다면 Access Denied를 return 한다. 그렇다면 API_KEY는 어떻게 구할 수 있을까? 해당 키는 환경변수에서 가져와진다.
현재 실행 중인 프로세스의 환경 변수를 담고 있는 /proc/self/environ 경로를 아래와 같이 요청한다.
그 후, /admin 경로와 데코레이터 요청 기준에 따라 아래와 같은 요청을 보낸다.
cmd에 전달되는 명령에 의해 실행 결과가 return 되므로, 이제 flag를 찾을 수 있다. cmd = ls -l / 을 통해 flag를 확인한다. 이때, cat /flag로는 flag값을 얻을 수 없다. 접근 권한을 보면 실행권한 밖에 없어서 flag 파일 자체를 실행시켜야 한다.
추가적으로, /proc/self/environ 경로 외에도 API_KEY를 확인할 수 있는 경로가 존재한다.
.bash_history파일은 root를 포함하여 각 사용자들의 홈디렉터리에 존재하는 파일이며, 각 사용자들이 사용했던 명령어가 저장되어 있는 중요 파일이다. 만약 파일 용량이 0이라면 해킹가능성을 의심해봐야 하고, 특히 root의 경우에는 더 주의를 기울여야 한다.