일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 생성형
- kubernetes
- 리트코드
- BFS
- 솔루션조사
- POD
- Machine Learning
- 컨설턴트
- 도커
- Python
- 로깅
- 머신러닝
- fast api
- LLaMa
- GPT
- jpa
- 오픈시프트
- fastapi
- 생성형 AI
- 메세지큐
- Docker
- vue.js
- vuejs
- SpringBoot
- Redis
- k8s
- LeetCode
- 쿠버네티스
- OpenShift
- 컨설팅
- Today
- Total
수 많은 우문은 현답을 만든다
시스템 보안(container) 설정 본문
안녕하세요 조영호입니다.
오늘은 Container 환경에서 개발한 웹 어플리케이션에 보안 설정하는 방법에 대해 포스팅하겠습니다.
웹 서비스는 front container(vue + nginx)와 server container(springboot)로 구성되어 있습니다.
1. 주요 디렉토리, 파일 권한 설정 미흡
[내용]
컨테이너 환경에서는 기본적으로 최소한의 권한 설정이 필요합니다. 필자는 처음엔 단순하게 NGINX에서 웹서비스를 띄우도록 서비스를 구성했지만, NGINX 설정 폴더/파일에 권한 설정이 미흡하여 다른 사용자(Other)로 부터 열람이 가능하다는 것을 파악했습니다.
[ 확인사항 ]
대상 : docker image: web-front
# ls -al /etc/nginx | grep
conf.d drwxr-xr-x 1 root root 4096 Dec 16 03:34 conf.d
# ls -al /etc/nginx/conf.d
-rw-r--r-- 1 root root 849 Nov 16 06:22 default.conf
[ 대응방법 ]
이에 대해 타 사용자(other)로부터 열람이 불가능하도록 권한 설정을 아래 방식으로 Dockerfile에 추가했습니다.
1. '웹 서버 설정파일'의 타 사용자 접근권한 제거
RUN chmod 700 /etc/nginx/conf.d
RUN chmod 700 /etc/nginx/conf.d
2. '웹 홈 디렉토리' 하위 파일들은 타 사용자에 실행권한 제거
RUN chmod -R o-x /usr/share/nginx/html/spa/*
1-1. 권한 설정시 장애 발생
위와같이 설정하고 웹 서비스를 실행해보니 '< is undefined'라는 front-error 메세지와 함께 화면이 뜨지 않았습니다.
커맨드를 하나씩 확인해보니 RUN chmod -R o-x /usr/share/nginx/html/spa/* 커맨드가 있을때만 화면이 뜨지 않는 것을 확인했습니다. 실제로 docker container에 접속을 해보면 해당 경로에는 index.html, js, css, fonts 등의 웹 서비스 파일들이 들어있습니다.
/usr/share/nginx/html/spa # ls -l
total 44
drwxr-xr-- 1 root root 4096 Jan 4 06:41 css
drwxr-xr-- 1 root root 4096 Jan 4 06:41 fonts
drwxr-xr-- 1 root root 4096 Jan 4 06:41 img
-rw-r--r-- 1 root root 986 Jan 4 06:41 index.html
drwxr-xr-- 1 root root 4096 Jan 4 06:41 js
drwxr-xr-- 1 root root 4096 Jan 4 06:41 statics
일반적으로 왼쪽의 10개 필드는 다음과 같은 의미들을 가집니다.
1필드 : 타입
- 인 경우 : 파일
d 인 경우 : 디렉토리
| 인 경우 : 다른 파일을 가리키는 링크
p 인 경우 : pipe. 두 개의 프로그램을 연결하는 파이프 파일.
b 인 경우 : block device. 블럭 단위로 하드웨어와 반응하는 파일
c 인 경우 : character device. 스트림 단위로 하드웨어와 반응하는 파일
2~4필드 : 소유주 (USER) 권한
5~7필드 : 그룹 (Group) 권한
8~10필드 : 나머지 (Others) 권한
제가 실행한 커맨드는 chmod o-x로, o:others의 권한에서 -x(실행 권한을 뺀다)를 의미합니다. 분명 others의 권한을 뺐는데 왜 접속이 안되는 것일까요?
1-2. NGINX 실행 권한 설정
NGINX는 하나의 마스터 프로세스와 여러 워커 프로세스로 구성되어 있으며 마스터 프로세스는 주로 설정 파일을 읽고 적용하며 워커 프로세스들을 관리하는 역할을 합니다. 워커 프로세스는 실질적인 웹서버의 역할을 수행하는데, 이 때 소유주 권한(user)이 워커프로세스의 권한을 지정합니다. 즉, 워커 프로세스를 악의적으로 사용자가 제어하게 된다면 해당 머신을 루트 사용자의 권한으로 원격제어하게 되는 셈이기 때문에 보안상 위험하기 때문에 user의 값이 root로 되어 있다면 일반 계정으로 변경하는 것이 좋습니다.
user 설정의 값으로는 대표성있는 이름(예를 들어 nginx)로 사용하고, 이 계정은 일반 유저의 권한으로 쉘에 접속할 수 없어야 안전합니다. 지금은 웹 서비스 폴더(/spa)의 소유자가 root로 되어있기 때문에 웹 서비스가 실행 되지 않는 것 입니다. 소유자를 바꿔보겠습니다.
RUN chown nginx:nginx -R spa/*
그리고 다시 권한을 확인해보면 소유자와 그룹이 변경된 것을 확인하실 수 있습니다.
/usr/share/nginx/html/spa # ls -l
total 44
drwxr-xr-- 1 nginx nginx 4096 Jan 4 06:41 css
drwxr-xr-- 1 nginx nginx 4096 Jan 4 06:41 fonts
drwxr-xr-- 1 nginx nginx 4096 Jan 4 06:41 img
-rw-r--r-- 1 nginx nginx 986 Jan 4 06:41 index.html
drwxr-xr-- 1 nginx nginx 4096 Jan 4 06:41 js
drwxr-xr-- 1 nginx nginx 4096 Jan 4 06:41 statics
드디어 서비스가 정상적으로 동작하게 되었습니다.
2. 컨테이너 내 어플리케이션 root 권한으로 실행 금지
[ 내용 ]
컨테이너 내 특정 애플리케이션이 root 사용자로 구동되고 있음을 발견했습니다. 해당 컨테이너는 ReadOnlyRootfs가 false인 상태로 루트권한 사용은 위험할 수 있기 때문에 일반 사용자 계정으로 애플리케이션 구동 전환이 필요합니다.
[ 확인 내용 ]
대상: docker image: web-server
UID PID PPID C STIME TTY TIME CMD
root 25108 25078 99 14:18 pts/0 00:01:58 java -javaagent:/monitor/agent.jar -jar /app.jar
[ 대응방법 ]
쉘 권한이 제거 된 일반 사용자 계정을 생성합니다.
RUN useradd --user-group --create-home --shell /bin/false deploy
RUN usermod --shell /sbin/nologin deploy
RUN chown -R deploy:deploy /monitor
USER deploy
3.비정상 클라이언트 제한
[내용]
보안 취약점 스캔 도구 등을 활용한 악의적인 공격 시도가 발생할 수 있으므로 아래 내용을 참고하여 비정상 클라이언트 요청을 사전에 제한해야합니다.
[대응 방법]
# vi nginx.conf
server {
listen 80;
server_name www.dodghek.com
root /usr/local/nginx/html;
# User-Agent 제한
if ($http_user_agent ~* "Paros|ZmEu|nikto|dirbuster|sqlmap|openvas|w3af|Morfeus|Zollard|Arachni|Brutus|bsqlbf|Grendel-Scan|Havij|Hydra|N-Stealth|Netsparker|Pangolin|pmafind|webinspect") {
return 404;
}
# 특정 헤더로 제한 (본 예제는 Acunetix-Product 헤더를 제한합니다.)
if ($http_acunetix_product) {
return 404;
}
}
감사합니다.
참고 링크 :