ModSecurity 2를 이용해 Apache 로그 관리 및 방화벽 설정하기
ModSecurity 2를 이용하면 Apache 웹 서버의 기본적인 웹 방화벽 설정을 할 수 있습니다. 또한 특정한 요청(Request)에 대한 로그를 진행하는 데에 도움을 얻을 수 있기 때문에 자주 사용됩니다. 대표적으로, 서버 오류를 발생시키는 요청에 대해서는 자동으로 로깅을 진행합니다. (POST 방식의 API의 파라미터를 이상하게 요청하여 500번 응답 코드를 받는 등)
설치는 다음과 같이 할 수 있습니다.
sudo apt install libapache2-mod-security2
이후에 추천 환경설정 파일을 /etc/modsecurity/modsecurity.conf의 위치로 옮기면, 기본적인 설정 그대로 ModSecurity를 이용할 수 있습니다. 그리고 아파치(Apache) 서버를 재시작합니다.
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sudo apachectl restart
이후에 /var/log/apache2/modsec_audit.log 파일에 로그 데이터가 기록됩니다. 이를 출력하도록 만들면 다음과 같이 로그가 출력되는 것을 확인할 수 있습니다.
tail -f /var/log/apache2/modsec_audit.log
물론 자신이 운영하고 있는 서비스에 따라서, 서로 다르게 방화벽 설정을 할 필요가 있기 때문에 실제로 로그가 찍히는 것을 보면서 환경 설정을 바꾸어가면서 쓰면 좋습니다.
'시큐어 코딩(Secure Coding)' 카테고리의 다른 글
우분투(Ubuntu) 리눅스 서버에서 IPtables를 활용해 방화벽 설정하기 (0) | 2019.03.26 |
---|---|
우분투(Ubuntu) 리눅스 서버에서 UFW를 활용해 방화벽 설정하기 (0) | 2019.03.26 |
서버 개발 보안 가이드 - 인증 수행 제한 (0) | 2019.03.26 |
우분투(Ubuntu) 리눅스 서버에서 IPtables를 활용해 방화벽 설정하기
※ IPtables 소개 ※
IPtables는 UFW와 마찬가지로 우분투(Ubuntu) 서버에 포함되어 있는 기본적인 방화벽 도구(Tool)입니다. IPtables를 이용하면 매우 다양한 방화벽 설정이 가능하다는 점에서 활용도가 매우 높습니다. 우리는 방화벽 설정을 할 때 매우 많이 고민한 뒤에 적용해야 합니다. 특히 클라우드 서비스를 이용하지 않는 경우 자기가 직접 서버의 방화벽 설정을 해야합니다. 또한 자칫 잘못 관리하면 사용자들이 접속조차 불가능할 수 있기 때문에 많은 부분을 고려하면서 방화벽 설정을 진행해야 합니다.
일단 IPtables를 이용하기 전에 UFW를 사용 중인 상태라면 UFW를 사용하지 않도록 처리합니다.
▶ UFW 비활성화: ufw disable
그리고 IPtables를 이용할 때는 IPtables의 현재 설정 정보를 확인할 때는 --list 옵션을 사용합니다.
▶ IPtables 규칙 확인: iptables --list
또한 기본적으로 방화벽 설정은 순차적으로 실행됩니다. 따라서 먼저 등록된 부분의 효력이 우선시 되기 때문에, 순서에 대해서 고려해야 합니다. 예를 들어 한 번 모든 패킷을 거부하는 설정이 진행되면 이후에 패킷을 허용하는 설정을 진행해도 의미가 없습니다.
그리고 기본적으로 방화벽 설정은 입력하자마자 바로 적용되기 때문에 많은 고민을 한 뒤에 명령어를 입력해야 합니다. 더불어 방화벽 설정이 수정되었으면, 이를 실제로 적용하기 위해서 규칙을 저장해주는 것을 잊으시면 안 됩니다. 규칙을 저장(Save)하지 않으면 서버를 재부팅하면 설정이 초기화됩니다.
▶ 규칙 저장: service iptables save
뿐만 아니라 규칙을 저장(Save)해 준 뒤에도 서버를 재부팅하면 규칙이 초기화 될 수 있습니다. 최신 버전의 우분투(Ubuntu)에서 자주 보이는 현상이며 이럴 때는 iptables-persistent 패키지를 이용하면 됩니다.
[ iptables-persistent 패키지 이용하기 ]
▶ 패키지 설치: sudo apt-get install iptables-persistent netfilter-persistent
▶ 저장: netfilter-persistent save
▶ 다시 로드: netfilter-persistent start
위 저장 및 로드 명령어를 IPtables의 저장(Save) 명령 이후에 수행해주시면 됩니다. 그러면 서버를 재부팅해도 그대로 IPtables 규칙 설정 정보가 남아 있습니다.
※ IPtables 주요 명령어 ※
-A: 새로운 규칙을 추가합니다.
-D: 기존의 규칙을 삭제합니다.
-R: 새로운 규칙으로 대체합니다.
-P: 기존의 규칙을 변경합니다.
-F: 모든 규칙을 삭제합니다.
※ IPtables 주요 옵션 ※
-p: 패킷의 포트 번호 혹은 프로토콜을 명시합니다.
-j: 패킷을 어떻게 처리할 지 명시합니다. (ACCEPT, DROP, LOG, REJECT)
-m: 확장 모듈을 활성화합니다. (ex) recent 모듈: 특정 시간 동안 특정 개수 이상의 패킷을 받았을 때를 처리할 수 있음
--dport: 패킷의 도착 포트 번호를 명시합니다.
--sport: 패킷의 발신 포트 번호를 명시합니다.
※ 자주 사용되는 예제 ※
1. 차단과 삭제
▶ 80번 포트 차단: iptables -A INPUT -p tcp --dport 80 -j DROP
▶ 80번 포트 차단 규칙 삭제: iptables -D INPUT -p tcp --dport 80 -j DROP
▶ 세 번째 라인의 규칙 삭제: iptables -D INPUT 3
2. 전체 방화벽 설정 초기화
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
3. 방화벽 서비스 부팅 관련 명령
▶ 서비스 시작: service iptables start
▶ 서비스 정지: service iptables stop
▶ 서비스 재시작: service iptables restart
▶ 서비스 저장: service iptables save
※ DoS 공격 차단 시나리오 ※
일반적으로 1초 동안 80번 포트에 똑같은 IP로 10번 이상의 SYN이 들어오는 경우는 적습니다. 따라서 10번 이상의 SYN이 들어오는 경우 이를 공격 시도로 판단할 수 있습니다. 그래서 그 이상의 패킷이 반복적으로 들어오는 경우 DROP 할 수 있도록 처리하는 경우가 많습니다. 이 때는 다음과 같은 명령어를 이용할 수 있습니다. (SSL이 적용된 서비스인 경우 443으로 설정해야 합니다.)
▶ 1초에 10번 이상 접근 저장 목적의 리스트 생성: iptables -A INPUT -p tcp --dport 80 -m recent --set --name HTTP_Flood
▶ 1초에 10번 이상 접근 로깅: iptables -A INPUT -p tcp --dport 80 -m recent --update --seconds 1 --hitcount 10 --name HTTP_Flood -j LOG --log-prefix "[Attack Detected]"
▶ 1초에 10번 이상 접근 차단: iptables -A INPUT -p tcp --dport 80 -m recent --update --seconds 1 --hitcount 10 --name HTTP_Flood -j DROP
▶ IPtables 규칙 확인: iptables --list
▶ 서비스 저장: service iptables save
위 명령어가 수행되면, 각 IP를 가지는 사용자가 1초에 10번 이상 서버에 접근했을 때 해당 IP를 차단하게 됩니다. 차단된 IP에 대한 정보는 로그로 남게 되며 마지막으로 차단된 시간으로부터 1초 뒤에는 다시 접속이 가능합니다. 또한 경우에 따라서 HTTPS 포트(443번 포트)에 대한 방화벽 설정이 필요할 수 있습니다. 본인이 이용하고 있는 서비스를 잘 확인하는 것이 중요합니다.
[ HTTPS 예제 코드 ]
동일 IP에서 1초에 25번 이상의 HTTP 및 HTTPS의 접근이 발생하면 차단하는 예제입니다.
iptables -A INPUT -p tcp --dport 80 -m recent --set --name HTTP_Flood
iptables -A INPUT -p tcp --dport 80 -m recent --update --seconds 1 --hitcount 25 --name HTTP_Flood -j LOG --log-prefix "[Flood Attack Detected]"
iptables -A INPUT -p tcp --dport 80 -m recent --update --seconds 1 --hitcount 25 --name HTTP_Flood -j DROP
iptables -A INPUT -p tcp --dport 443 -m recent --set --name HTTPS_Flood
iptables -A INPUT -p tcp --dport 443 -m recent --update --seconds 1 --hitcount 25 --name HTTPS_Flood -j LOG --log-prefix "[Flood Attack Detected]"
iptables -A INPUT -p tcp --dport 443 -m recent --update --seconds 1 --hitcount 25 --name HTTPS_Flood -j DROP
iptables --list
service iptables save
netfilter-persistent save
netfilter-persistent start
[ 저장된 로그 확인 ]
우분투(Ubuntu)에서 기본적으로 IPtables 관련 로그는 /var/log/kern.log의 위치에 저장됩니다. 따라서 일반적으로 다음과 같은 명령어로 로그에 기록되어 있는 공격 시도 패킷을 확인할 수 있습니다.
grep -r "Attack Detected" /var/log/kern.log
'시큐어 코딩(Secure Coding)' 카테고리의 다른 글
ModSecurity 2를 이용해 Apache 로그 관리 및 방화벽 설정하기 (0) | 2019.04.16 |
---|---|
우분투(Ubuntu) 리눅스 서버에서 UFW를 활용해 방화벽 설정하기 (0) | 2019.03.26 |
서버 개발 보안 가이드 - 인증 수행 제한 (0) | 2019.03.26 |
우분투(Ubuntu) 리눅스 서버에서 UFW를 활용해 방화벽 설정하기
※ UFW 기본 설정 ※
우분투(Ubuntu)에서는 기본적으로 UFW라는 툴이 설치되어 있어 방화벽을 쉽게 설정할 수 있습니다. 다만 기본적으로 우분투의 UFW 방화벽은 비활성화 상태이므로 UFW를 활성화 처리 해 줄 필요가 있습니다.
UFW는 기본적으로 모든 인 바운드(In-Bound) 패킷을 차단하므로 외부에서 우리 우분투 서버에 접근할 수 없습니다. 따라서 SSH에 해당하는 22번 포트는 열어 준 상태로 활성화를 시켜주셔야 합니다. 단순히 UFW를 활성화 처리 해주고 서버를 재부팅하면 서버 자체에 아예 접속이 불가능하게 되는 낭패를 볼 수 있으므로 유의하셔야 합니다.
ufw status: UFW 방화벽 상태 확인하기
ufw allow 22: UFW 방화벽 22번 포트 허용하기
ufw enable: UFW 방화벽 활성화 하기
ufw disable: UFW 방화벽 비활성화 하기
ufw reset: UFW 설정 초기화 하기
※ UFW 룰(Rule) 설정 ※
UFW를 활성화(Enable) 처리 하면, 기본 설정으로 모든 인 바운드 패킷을 차단하므로 외부에서 우리 우분투 서버에 접근할 수 없습니다. 따라서 UFW 활성화 이후에는 룰 설정을 진행해야 합니다. 자주 사용되는 룰 설정 방법은 다음과 같습니다.
ufw show raw: UFW 방화벽 룰(Rule) 확인하기
ufw allow [포트 번호]: 특정 포트 허용하기
ufw deny [포트 번호]: 특정 포트 거부하기
ufw delete allow [포트 번호]: 특정 포트 허용하기 설정을 제거하기ufw delete deny [포트 번호]: 특정 포트 거부하기 설정을 제거하기
※ 실 서버로 활용할 때 ※
만약 클라우드 서비스를 이용하지 않고 서버를 직접 관리하고 있다면 방화벽 설정은 필수에 가깝습니다. 다만 클라우드 서비스를 이용할 때 클라우스 서비스 단에서도 방화벽 설정을 할 수 있으므로 UFW 설정이 필요 없을 수 있답니다. 그럼에도 더욱 다채로운 방화벽 설정을 위해 UFW나 iptables 등의 유틸리티를 이용할 수 있습니다. (그런 경우 클라우드 서비스와 방화벽 설정을 흡사하게 진행해야 합니다.)
※ iptables와 함께 사용할 때 ※
기본적으로 iptables를 이용하여 방화벽 설정을 할 때는 UFW는 사용하지 않도록 처리하는 것이 일반적입니다.
'시큐어 코딩(Secure Coding)' 카테고리의 다른 글
ModSecurity 2를 이용해 Apache 로그 관리 및 방화벽 설정하기 (0) | 2019.04.16 |
---|---|
우분투(Ubuntu) 리눅스 서버에서 IPtables를 활용해 방화벽 설정하기 (0) | 2019.03.26 |
서버 개발 보안 가이드 - 인증 수행 제한 (0) | 2019.03.26 |
서버 개발 보안 가이드 - 인증 수행 제한
※ 취약점 설명 및 고려사항 ※
로그인 기능을 포함해 다양한 주요 인증 기능을 구현할 때에는 인증 시도 횟수를 제한해야 합니다. 주요기관의 소프트웨어 개발보안 가이드를 보면 로그인 시도 횟수를 3~5번 이내로 제한하고 이를 초과하여 로그인에 실패하는 경우 추가 입력값을 요구하거나 계정잠금을 수행하도록 설계해야 한다고 나옵니다.
※ 적용 예시 ※
현재 SMS 인증 API의 데이터베이스 컬럼은 다음과 같이 구성되어 있습니다.
- member_tel: 핸드폰 번호
- sms_token: 인증 번호
- sms_date: 인증 시도 날짜
가장 간단한 구현 방법은 [최근 10분 이내에 3회 이상 요청한 핸드폰 번호인지 체크]하여 10분 이내에 3회 이상 요청을 했다면 잠금 처리를 할 수 있도록 하는 것입니다. 따라서 다음과 같은 SQL 구문을 이용하면 좋습니다. (MySQL 기준)
SELECT COUNT(*) as cnt
FROM {SMS 인증 테이블}
WHERE sms_date > date_sub(now(), interval 600 second)
AND member_tel = {핸드폰 번호};
위 소스코드를 이용하면 최근 10분 이내에 SMS 인증 요청이 몇 번 발생했는지 확인할 수 있습니다. 그래서 컨트롤러(Controller)에서는 다음과 같은 형태로 처리할 수 있습니다. (PHP, REST API 기준)
$member_tel = $this->input_check('member_tel');
$result = $this->model_member->check_sms_repeat($member_tel );
if($result >= 3) {
$this->output->set_status_header(503); // 최근 10분 이내에 3회 이상 요청하여 잠금 처리 된 핸드폰 번호입니다.
exit;
}
'시큐어 코딩(Secure Coding)' 카테고리의 다른 글
ModSecurity 2를 이용해 Apache 로그 관리 및 방화벽 설정하기 (0) | 2019.04.16 |
---|---|
우분투(Ubuntu) 리눅스 서버에서 IPtables를 활용해 방화벽 설정하기 (0) | 2019.03.26 |
우분투(Ubuntu) 리눅스 서버에서 UFW를 활용해 방화벽 설정하기 (0) | 2019.03.26 |