본문 바로가기

Wargame(hacking)/Dreamhack

Level 1 : File Vulnerability Advanced for linux

 

@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 파일을 읽어올 수 있는지 확인해 보았다. 

 

그림 1

 

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 경로를 아래와 같이 요청한다. 

 

그림 2

 

그 후, /admin 경로와 데코레이터 요청 기준에 따라 아래와 같은 요청을 보낸다. 

 

그림 3

 

cmd에 전달되는 명령에 의해 실행 결과가 return 되므로, 이제 flag를 찾을 수 있다. cmd = ls -l / 을 통해 flag를 확인한다. 이때, cat /flag로는 flag값을 얻을 수 없다. 접근 권한을 보면 실행권한 밖에 없어서 flag 파일 자체를 실행시켜야 한다. 

 

 

추가적으로, /proc/self/environ 경로 외에도 API_KEY를 확인할 수 있는 경로가 존재한다. 

 

그림 4

 

.bash_history파일은 root를 포함하여 각 사용자들의 홈디렉터리에 존재하는 파일이며, 각 사용자들이 사용했던 명령어가 저장되어 있는 중요 파일이다. 만약 파일 용량이 0이라면 해킹가능성을 의심해봐야 하고, 특히 root의 경우에는 더 주의를 기울여야 한다.