java URL class를 이용한 내부 파일 읽기
올해 codegate 2022 웹 문제 중에서 java에 `URL class`를 이용한 SSRF 문제가 나왔다.
아래 코드는 `URL class`를 이용하여 외부 사이트에 요청 및 응답 값을 출력하는 코드 이다.
import java.net.URL;
import java.net.MalformedURLException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
public class test{
public static void main(String[] args){
String url = "https://lactea.kr";
String result = "";
try {
BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
while (true) {
String inputLine = in.readLine();
if (inputLine != null) {
result = result + inputLine + "\n";
} else {
in.close();
try {
System.out.println("== result ==");
System.out.println(result);
} catch (Exception e) {
System.out.println("error 1");
}
}
}
} catch (Exception e2) {
System.out.println("error 2");
}
}
}
위 코드를 실행하면 `url` 변수에 저장된 주소로 요청 및 응답 값을 출력하게 된다.
URL class에서 사용 가능한 scheme 종류는 다음과 같다.
https://stackoverflow.com/questions/41784555/print-all-supported-url-schemes-in-java8#:~:text=want%20more%20than-,http%2C%20https%2C%20file%2C%20and%20jar,-%2C%20you%20need%20to
http:// | https:// | file:// | jar:// |
따라서 위 코드에서 `url` 변수의 값을 `file:///etc/passwd` 라고 변경한 뒤 실행하면 아래 사진처럼 내부 파일을 읽을 수 있다.
만약, 위 코드에서 `file://` scheme 문자열을 검증하는 코드가 추가가 된다면, 내부 파일을 읽을 수 가 없을 것이다.
if (url.startsWith("file")) {
System.out.println("No");
}
이를 우회하기 위해 `URL class` 파일을 보면 다음과 같다.
`spec` 변수는 url 주소 값이 들어간다. 아래 사진을 보면 575번째 줄에 `url:` 이라는 문자열로 시작하면 `start` 변수에 4를 더해준다. 이는 url 구조를 분석하기 위해 `start` 변수로 시작 index를 정하는 것이다.
즉, 위 코드를 통해 공격자가 `file:///etc/passwd` 에서 `file://` scheme 검증 절차를 우회하기 위해
`url:file:///etc/passwd` 라고 변경하면 내부 코드를 읽을 수 있다.