다음과 같이 서버 코드를 작성하고, 웹 서버에 접속하면 접속한 클라이언트의 아이피를 가져올 수 있다.
var express = require('express');
var requestIp = require('request-ip');
var app = express();
app.get('/main', function(req, res){
res.send('main page')
console.log("client IP: " +requestIp.getClientIp(req));
})
app.listen(3003, function(){
console.log("Express server started at port 3003");
});
request-ip 모듈의 getClientIP() 함수를 사용하여 접속자의 아이피를 가져올 수 있다.
쿠키는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터다. 브라우저는 이 데이터(쿠키)들을 저장해 두었다가 동일한 서버에서 재 요청 시 저장된 데이터(쿠키)들을 같이 전송한다.
http 프로토콜은 하나의 요청에 하나의 응답을 한 후 네트워크 연결을 끊는 connectionless의 특징과 네트워크가 연결이 끝맺을 때 상태를 유지하지 않는 stateless 속성을 갖기 때문에 http 요청마다 새로운 커넥션을 열어 인증을 계속 해야한다는 단점 때문에 쿠키라는 개념이 생겼다.
SSRF는 Server-Side Request Forgery를 줄인 말로 서버에서 이루어지는 요청을 변조해 공격자가 의도한 서버로 요청을 가게 하거나 요청 자체를 변경할 수 있는 공격이다.
일반적으로 웹 서버를 운영하는 곳은 웹 서버만 공개적으로 열어두고, 내부에서 사용하는 다른 서버(ssh, 파일서버, 메일서버 등)는 외부에서 접속하지 못하도록 설정한다.
그러나 어떤 문제에 의해 외부에서 웹 서버를 통해 내부의 다른 서버로 접근이 가능하게 되면, SSRF 취약점이 발생할 수 있다.
웹 서버가 SSRF 취약점을 가지고 있다면 첫째로 특정 웹 서버로부터 정보를 획득할 수 있다.
해커는 원하는 URL로 접근 후 그 응답 데이터를 획득할 수 있다.
외부에서 접근이 금지된 내부의 중요한 시스템이 주 공격 대상으로 설정된다.
둘째로 조작된 HTTP Request를 특정 서버로 전송할 수 있다.
해커가 원하는 요청을 원하는 서버로 전송할 수 있으며 주로 취약한 버전을 사용하는 내부 시스템을 찾아 공격한다.
셋째로 내부 네트워크 스캐닝을 할 수 있다.
사설 IP로 구성된 내부 네트워크 정보를 획득하기 위해 응답 값 또는 응답 시간의 차이를 이용해 IP와 Port의 Open여부가 파악 가능하다.
위 그림에서 정상적인 요청은 외부에서 접근 가능한 http:website.com/?url=http://111.222.11.12 으로 요청을 보내는 것이지만, 비정상 적인 요청은 외부에서는 접근할 수 없는 내부의 주소인 http:website.com/?url=http://10.12.13.18 로 요청을 보내는 것이다.
SSRF취약점은 입력 받은 데이터(url, script등)가 올바른지 검증하지 않거나 부실하게 검증하여 발생한다.
따라서 SSRF 취약점을 예방하려면 입력 받은 데이터를 검증하여 허용되는 부분이 아니라면 필터링을 하여 막아야 한다. 필터링 하는 방식에는 Whitelist 방식과 Blacklist 방식이 있는데, Whitelist 방식은 사용자가 입력한 데이터에 대해 허용할 리스트를 설정하고 리스트에 속하지 않는 경우에는 모두 에러페이지로 연결하는 방식이고, Blacklist 방식은 허용하지 않는 리스트를 작성하여 입력 받은 데이터가 리스트 안에 있으면 에러 페이지를 연결하는 방식이다.
위 두가지 방식 중 비교적Blacklist 방식이 우회할 수 있는 방법이 많기 때문에 Whitelist 방식을 사용하는 것이 더 좋다.