Profile

i love cat

as3617

TokyoWesterns CTF 2020 Web Writeup

urlcheck1 - 98 points

app.re_ip = re.compile('\A(\d+)\.(\d+)\.(\d+)\.(\d+)\Z')

def valid_ip(ip):
    matches = app.re_ip.match(ip)
    if matches == None:
        return False

    ip = list(map(int, matches.groups()))
    if any(i > 255 for i in ip) == True:
        return False
    # Stay out of my private!
    if ip[0] in [0, 10, 127] \
        or (ip[0] == 172 and (ip[1] > 15 or ip[1] < 32)) \
        or (ip[0] == 169 and ip[1] == 254) \
        or (ip[0] == 192 and ip[1] == 168):
        return False
    return True

def get(url, recursive_count=0):
    r = requests.get(url, allow_redirects=False)
    if 'location' in r.headers:
        if recursive_count > 2:
            return '&#x1f914;'
        url = r.headers.get('location')
        if valid_ip(urlparse(url).netloc) == False:
            return '&#x1f914;'
        return get(url, recursive_count + 1) 
    return r.text

@app.route('/admin-status')
def admin_status():
    if flask.request.remote_addr != '127.0.0.1':
        return '&#x1f97a;'
    return app.flag

코드를 주고 있는데 중요한 부분은 위와 같다.
간단하게 로직을 우회하여 /admin-status에 접근하는 것이 가능하다.
exploit : http://0177.0.0.1/admin-status

FLAG: TWCTF{4r3_y0u_r34dy?n3x7_57463_15_r34l_55rf!}

Urlcheck v2 - 128 points

Urlcheck v2 문제다.

def valid_ip(ip):
    try:
        result = ipaddress.ip_address(ip)
        # Stay out of my private!
        return result.is_global
    except:
        return False

def valid_fqdn(fqdn):
    return valid_ip(socket.gethostbyname(fqdn))

코드를 주고 있는데 필터링 로직이 위의 코드로 변경되었다.
달라진 점은 도메인을 받은 뒤 socket 모듈을 이용하여 dns resolves를 수행하기 때문에 위에서 사용한 방식으로는 공격하기가 힘들다.

따라서 DNS rebinding을 이용하여 공격을 진행하면 된다.

이런 식으로 도메인에다가 DNS 연결을 내 서버로 한다.

그 다음에 바로 내서버에서 127.0.0.1로 DNS 연결을 바꾼 다음에 어느 정도 DNS 캐시가 남아있기 때문에 계속 url을 넘겨주다보면
어느 순간 플래그를 얻을 수 있다.

FLAG : TWCTF{17_15_h4rd_70_55rf_m17164710n_47_4pp_l4y3r:(}

Angular of the Universe - (139,149) points

이 문제도 소스코드를 주고 있는데 한 문제 안에 2개의 플래그가 있다고 한다.

맨 처음에는 서버에다가 환경을 세팅한 뒤에 풀이를 진행하려고 했지만 빌드 도중에 계속 오류가 발생해서
그냥 코드 분석만 하고 그것을 토대로 풀이를 진행했다.

  location /debug {
    # IP address restriction.
    # TODO: add allowed IP addresses here
    allow 127.0.0.1;
    deny all;
  }

nginx 설정은 위와 같다. 내부에서만 /debug/* 에 접근할 수 있고 그외의 /debug/*로의 요청은 서버에서 차단한다.

    if (process.env.FLAG && req.path.includes('debug')) {
      return res.status(500).send('debug page is disabled in production env')
    }

메인 코드를 확인해보면 request path에 debug라는 문자열이 들어있으면 500을 출력한다고 한다.

이것은 간단하게 우회하는 것이 가능한데
http://~~~/\debug 와 같이 요청하게 되면 nginx는 /\debug라는 디렉토리로 요청했다고 인식한 뒤
http://app 뒤에 path를 붙여서 서버로 넘겨주게 된다.

그러면 http://app/\debug 로 서버로 넘겨주고 angular.js는 \를 /로 인식하기 때문에
최종적으로는 http://app//debug로 요청하게 된다.
이를 이용하여 http://app/\debug/answer로 요청하면 플래그를 얻을 수 있을 것이다.
하지만 요청 path에 debug라는 문자열이 있기 때문에 500 page가 뜨는 것을 확인할 수 있다.
이것도 간단하게 urlencoding을 이용하여 e를 %65로 바꿔서 요청을 날리면 된다.

FLAG1 :TWCTF{ky0-wa-dare-n0-donna-yume-ni?kurukuru-mewkledreamy!}

2번째 플래그를 얻으려면
/api/true-answer로 요청을 보내야한다.

우리가 봐야할 부분은

location / {
    proxy_pass http://app;
    proxy_set_header Host $host;
  }

이 부분이다. 여기서 보면 우리가 요청할 때 보낸 Host를 그대로 백엔드로 넘겨줄 때 사용하는 것을 알 수 있다.

 getAnswer() {
    return this.http.get('/api/answer')
  }

angular.js에서 이런식으로 http 요청을 보내고 있는데 이때 angular.js는 host를 사용하여 요청을 보낸다.
그럼 우리가 host를 조작하여 외부로의 요청을 만들고 redirection을 이용하여 내부서버로 접근하게 한다면 플래그를 얻을 수 있을 것이다.

옛날에 이 글을 읽었던 기억이 나서 문제푸는 것에 사용했다. -> https://www.hahwul.com/2019/02/22/bypass-ssrf-protection-using-http-redirect/

 

FLAG2 : TWCTF{you-have-to-eat-tomato-yume-chan!}

Angular of another Universe - 239 points (not solve....)

https://github.com/angular/angular/blob/1801d0c6500ea5e677e753fbcfb73dbd3675f054/packages/router/src/url_tree.ts#L586
이 부분을 보면 풀 수 있었다고 한다.

http://aaa/(outlet_name:c/d) 이런식으로 요청을 보낼 수 있다고 한다.
여기서 outlet_name은 angular 문서에 따르면 설정이 따로 되있지 않는다면 기본값은 primary로 설정되있다고 한다.

따라서 http://another-universe.chal.ctf.westerns.tokyo/(primary:debug/answer)로 요청을 하면
내부에선 /debug/answer로 요청한 것으로 해석하고 FLAG를 얻을 수 있다고 한다.

FLAG : TWCTF{theremightbeanotheranotheranotherissuesinuniverse}

'web hacking' 카테고리의 다른 글

DarkCON CTF web Writeup - DarkCON Challs  (0) 2021.02.21
SQL Injection 정리  (0) 2020.11.08
PHP object injection  (0) 2020.08.13
Python Pickle Deserialization Vulnerability (Python pickle 취약점)  (0) 2020.04.22
디미고 benedu 취약점  (0) 2020.03.06