[CTF] SECCON CTF 2022 - skipinx

2022. 11. 13. 20:27정보보안/CTFLOG

반응형

index.html

server {
  listen 8080 default_server;
  server_name nginx;

  location / {
    set $args "${args}&proxy=nginx";
    proxy_pass http://web:3000;
  }
}#default.conf
const app = require("express")();

const FLAG = process.env.FLAG ?? "SECCON{dummy}";
const PORT = 3000;

app.get("/", (req, res) => {
  req.query.proxy.includes("nginx")
    ? res.status(400).send("Access here directly, not via nginx :(")
    : res.send(`Congratz! You got a flag: ${FLAG}`);
});

app.listen({ port: PORT, host: "0.0.0.0" }, () => {
  console.log(`Server listening at ${PORT}`);
});
#index.js

 

 

토요일 오후 2시부터 24시간 동안 열린 seccon ctf 2022에 참여하고 

대회 내내 잡고 못푼채 끝났던 웹 문제인 skipinx 라이트업을 작성한다.

 

제공하는 파일은 분석하기 어렵거나 복잡하지 않았다. 

다만, nginx가 뭐하는 녀석인지 알아야 할 필요가 있다.

 

출처  : https://www.freecodecamp.org/news/an-introduction-to-nginx-for-developers-62179b6a458f/

nginx는 클라이언트로 부터 받은 파일을 해당하는 서버로 http 프로토콜을 사용하여 전달하는 역할을 수행하는 웹 서버 소프트웨어이다. 

 

즉,  proxy 역할을 해준다. 이를 이용해 로드벨런싱 같은걸 할 수도 있다. 

어쨌든 이 문제에서는 이 nginx의 프록시 기능을 활용해서 문제를 제작했다.

 

문제를 풀기위해서 제공해준 문제 링크로 접속하면 

Access here directly, not via nginx :( 라는 문구가 뜬다.

 

그 이유를 알아보자면, default.conf 소스를 확인해보면 locatin / 라고 적혀있는 부분이 있는데

이는 http://example.com/ 라는 URI가 있을때 /로 끝나는 부분에 대해서 요청을 처리한다는 뜻이다.

 

즉 우리는 문제의 링크를 클릭해서 접속하면 nginx를 경유하게 되고 http://skipinx.seccon.games:8080/ 뒤 부분에

proxy=nginx라는 parameter가 붙어서 proxy_pass에 지정해놓은 서버로 넘어가게 된다.

 

그리고 index.js에서는 proxy_pass에서 넘긴 서버의 url의 parameter에 nginx라는 문자열이 존재한다면

이는 nginx를 경유함을 의미하기 때문에, Access here directly, not via nginx :(  라는 문자열이 화면에 출력되는것이다.

 

참고로 $args는 nginx에서 사용할수 있는 변수들중 하나인데, 파라미터에 딸려오는 질의문 뒷부분만 가져온다

(예 : https://example.com/?hello=hi) 라고 한다면 $args에는 hello=hi라는 부분만 들어온다.

 

따라서 우리는  http://skipinx.seccon.games:8080/ 뒤에 뭔가를 해서 proxy=nginx

가 적용되지 않게끔 해야한다.

 

대회 중에 이 부분부터 막혀서 관련 cve나 해킹기법,버그들을 찾아보고 실행시켜 봤지만 할 수 있는게 없었다.

 

 

우리가 url 뒤에 적은 파라미터는 nginx로 이동한다.

그리고 index.js의 express는 파싱을 통해  URI를 읽어오는데, 이때 qs라는 모듈이 사용된다.

https://cyberx.tistory.com/138 << qs가 뭔지는 이 블로그를 참고

 

그리고 이 qs모듈의 소스를 확인해보면 (https://github.com/ljharb/qs/blob/main/dist/qs.js)

qs모듈은 Limit이 존재했다.

즉 limit이후의 값은 잘리고, 따라서 index.js가 파싱할때 포함되지 않는다.

 

import requests

a = requests.get('http://skipinx.seccon.games:8080/?proxy=a&'+'b=4&'*1001).text

여기서 'b=4&'은 뭔가요? 라고 의문을 가질 수 있다.

b=4&라는 부분이 1000 이상이 되면 뒤에 붙는 값이 파싱할때 포함되지 않는다.

따라서 proxy=a& 뒤에 하나의 파라미터를 더 생성하고 그것을 1000번 이상 곱한 값을 전송하는것이다.

(b=4&라는 부분에는 a=1&,c=4& 등 어떤 문자가 들어가도 상관없다.)

 

 

Congratz! You got a flag: SECCON{sometimes_deFault_options_are_useful_to_bypa55}

반응형

'정보보안 > CTFLOG' 카테고리의 다른 글

[CTF] B01ler_ctf - voidciphr  (0) 2023.03.20
[CTF] LOGCON - warmup  (0) 2023.01.17
[CTF] Blackhat 2022 CTF - naruto  (0) 2022.10.02
[WARGAME] los.rubiya.kr - Nightmare  (0) 2022.08.14
[WARGAME] los.rubiya.kr - zombie_assassin  (0) 2022.08.14