리눅스 서버 운영체제
• 서버 시장에서 점유율 높음
• 대용량 서버 시장(Unix) 및 클라우드 환경(Linux)
• 클라우드 환경에서는 대부분 리눅스 기반으로 동작
• 웹에서 리눅스 사용 : https://bellard.org/jslinux/

시스템 보안
- 계정관리
- 사용자 식별을 위한 가장 기본적인 인증
수단은 ID/PW
- 세션 관리
- 일정 시간이 지나면 세션을 종료하고,
비인가자의 세션 가로채기를 통제
- 접근 제어
- 네트워크 안에서 시스템을 다른
시스템으로부터 적절히 보호할 수 있도록
접근 통제
- 권한 관리
- 시스템의 각 사용자가 적절한 권한으로
정보자산에 접근하도록 통제
- 로그 관리
- 시스템 내부나 네트워크를 통해 외부에서
시스템에 어떤 영향을 미칠 경우 그 내용을
기록 및 관리
- 취약점 관리
계정관리
- 보안의 네 가지 인증방법
- 알고 있는 것
- 머릿속에 기억하고 있는 정보를 통한 인증
- (예) ID/PW
- 가지고 있는 것
- 신분증이나 OTP 장치 등으로 인증
- (예) 출입카드
- 자신의 모습
- 생체정보를 통한 인증
- (예) 지문 인식, 홍채 인식
- 위치하는 곳
- 현재 접속을 시도하는 위치를 확인
- 콜백(call back)을 사용해 인증
※ 콜백 : 접속을 요청한 사람을 확인하기 위해 등록된 전화번호로 전화를 되걸어 본인 확인
계정관리
- 사용자 계정
- 시스템 접근(로그인)을 위해서는 계정(account)이 필요
- 운영체제는 계정별 자원(프로세스, 파일 등)에 할당된 접근 권한으로 운영을 허용
- 운영체제는 사용자(user)별 접근 권한 및 그룹(group)별 접근 권한을 지원
- 시스템 내 모든 계정은 그룹에 포함되어 관리
- 관리자(root) 계정 & 일반 사용자 계정
- 리눅스에서 관리자 계정 : root
- 리눅스의 기본 관리자 계정
- 컴퓨터를 전체적으로 관리할 수 있는 막강한 권한이 있는 계정
- 복잡한 비밀번호 사용 등 엄격한 관리 필요
- 관리자 계정의 관리 지침
- Root 계정으로 원격 접속 금지
- 비밀번호 파일을 shadow 파일로 보호
- 잘못된 비밀번호를 계속 입력하면, 그 계정은 잠겨야 함
- 원격에서 root 계정으로 접속 금지
- 원격지에서 서버에 접속하기 위해 ssh, telnet 등의 프로그램을 이용
- 네트워크를 통해 root 계정을 원격 접속 허용하면 1차 공격 대상으로써 위험!
- Ubuntu에서는 root 로그인이 안되도록 기본 설정되어 있음
- 필요하다면, 일반 유저로 접속한 후 root 계정을 불러오는 좋음

(참고) 리눅스에서 ssh 서버 설치

시스템의 패키지 목록을 최신화 : ~$ sudo apt update
ssh-server 설치 : ~$ sudo apt install openssh-server
ssh 동작 확인

- root 원격접근 차단위한 설정 :
- 설정 파일 : /etc/ssh/sshd_config
- 임의의 port 설정
- PermitRootLogin no 로 설정
- root 사용자의 로그인 허용 여부 설정을 위해 (yes / no / prohibit-password /without-password / forced-commands-only) 중 하나 설정
- yes : root 계정으로 원격 로그인 가능
- no : root 계정으로 원격 로그인 불가
- prohibit-password : 비밀번호를 사용한 로그인 불가, key 파일을 사용해 로그인 (default)
- without-password : 원격에서 키 로그인은 허용하며, 원격 패스워드 로그인은 금지
- forced-commands-only : 원격에서 키 로그인은 허용하지만, 로그인 대신 command를 사용해서 명령만 전달 가능
- MaxAuthTries
계정관리
- 비밀번호 파일을 shadow 파일로 보호
- 계정정보와 암호화된 패스워드를 별도의 파일로 관리
- 사용 권한을 오직 root 사용자만 읽어볼 수 있음
- 계정 관리 명령어
- 사용자 추가 : adduser [계정명]
- 비밀번호 설정 : passwd [계정명]
- 사용자 삭제 : deluser [계정명] ( → 관리자(root) 권한으로만 실행 가능)

- 비밀번호 파일을 shadow 파일로 보호
- 설정 파일 : /etc/passwd
- 다양한 사용자 관련 정보가 저장됨
- 계정 이름
- 사용자의 비밀번호 정보
- 사용자 ID
- 그룹 ID
- 사용자 코멘트(시스템 설정에 영향을 주지 않음)
- 사용자의 홈 디렉터리
- 사용자가 기본적으로 사용한 쉘 종류 등도 저장 (ex) /bin/bash

- 비밀번호 파일을 shadow 파일로 보호
- 설정 파일 : /etc/shadow
- 사용자 계정 별 비밀번호를 관리
(백업파일 : /etc/shadow-)
- 파일은 시스템관리자(root)만 접근이 가능
- 비밀번호는 암호화되어 관리됨(“!” 문구가 앞에있으면 접근 불가 상태가 됨)



- 그룹 정보
- 설정 파일 : /etc/group & /etc/gshadow
- 그룹별 비밀번호를 관리(백업 파일 : /etc/gshadow-)
- 파일은 시스템 관리자(root)만 접근 가능
- 비밀번호는 암호화되어 관리
- 그룹 관리 명령어
- 그룹 추가 : addgroup [그룹명]
- 그룹 삭제 : delgroup [그룹명]
- 그룹 확인 : groups

- 사용자 전환
- su [계정명] 혹은 su – [계정명]
- 시스템 관리자(root) 로 전환시 [계정명] 입력하지 않아도 됨
- 사용자 전환 시 반드시 해당 계정의 비밀번호를 입력해야 함
- 단, 시스템 관리자(root)가 다른 계정으로 전환할 때는 비밀번호 입력 X

-
대리 실행
- sudo [-u user][명령어]
- 지정한 사용자 계정으로 명령어 실행
- 지정한 계정이 없을 경우 입력한 명령어는 시스템 관리자(root) 계정으로 실행됨
- 지정된 명령어만 해당 계정으로 동작함
- 시스템에서 별도로 지정된 계정만 이용할 수 있음
- /etc/sudo.conf, /etc/sudoers, /etc/sudoers.d/*
-
su와 sudo의 차이
- su는 지정된 사용자 계정으로 전환
- sudo는 일시적으로 지정된 사용자 계정으로 명령어 실행

- 패스워드 관리
- 부적절한 패스워드
- 길이가 너무 짧거나 널(Null)인 패스워드
- 사전에 나오는 단어나 그 조합 또는 변형
- 키보드 자판의 일련 나열
- 사용자 계정 정보로 유추할 수 있는 단어
- 적절한 패스워드
- 패스워드 정책
- 패스워드의 길이와 복잡도 설정
ex) 8자 이상, 숫자 & 알파벳 & 특수문자 혼합 등
- 패스워드 변경 정책 : 60일 혹은 90일 간격으로 패스워드 변경하도록 설정
- 잘못된 패스워드 입력시 계정 잠금
그밖의 계정관리
- 데이터베이스의 계정 관리
- 데이터베이스에도 운영체제처럼 계정이 존재
- MS-SQL의 관리자 계정은 sa, 오라클의 관리자 계정은 sys, system
- 둘 다 관리자 계정이지만 sys와 달리 system은 데이터베이스를 생성할 수 없음
- 응용 프로그램의 계정 관리
- 취약한 응용 프로그램을 통해 공격자가 운영체제에 접근하여 민감한 정보를 습득한 뒤 운영체제를 공격
하는 데 이용할 수 있음
- TFTP처럼 사용자 인증 없이 파일 전송하는 응용 프로그램-은 더욱 세심한 주의가 필요 → cf) SFTP
- 네트워크 장비의 계정 관리
- 네트워크 장비는 보통 패스워드만 알면 접근이 가능
- 시스코 장비의 계정의 모드 구별
- 네트워크 장비의 상태만 확인할 수 있는 사용자 모드
- 네트워크에 대한 설정 변경이 가능한 관리자 모드
- 처음 접속시 사용자 모드로 로그인 되며, 사용자 모드에서 관리자 모드로 로그인하려면 enable 명령어와 함께 별도의 패스워드를 입력

세션관리
패치관리
- 패치의 필요성
- 운영체제도 일종의 소프트웨어
- 새로운 버그 및 취약점이 발견됨
- 발견된 취약점을 악용하는 보안 공격 발생
- 패치 적용을 통한 보안성 및 시스템 안정성 확보
- (예) Ubuntu LTS에 대해 19개의 보안취약점을 해결하는 업데이트 실시(2023년)

로그 관리
-
개요
- 시스템 로그
- 시스템의 성능, 오류, 경고 및 운영 정보 등이 기록
- 서버 보안 관리자의 역할
- 시스템 로그를 정기적으로 분석
- 침입 유무 파악, 침입 시도 의심 사례의 분석 및 보고
- 유닉스의 표준적 로그 인터페이스: syslog

- syslog.conf
- 어떤 로그를 어디에 남길지에 대한 로그 저장 규칙을 정의
- syslog.conf 의 예
| 로그 수준 | 설정 | 설명 |
|---|
| Emergency (emerg) | *.emerg * | 모든 형태(*)로 로그 저장 (로그 파일, 콘솔 포함) |
| Alert (alert) | *.alert /var/adm/syslog.log | 심각한 에러 발생 시 파일(/var/adm/syslog.log)에 저장 |
| None (authpriv) | authpriv.none /var/log/messages | 보안 로그(authpriv)는 어떤 수준에서도 저장하지 않음 |
| All (authpriv) | authpriv.* /var/log/messages | 보안 로그(authpriv)의 모든 수준(*)을 /var/log/messages에 저장 |
- syslog 의 로그 수준
- 모든 로그를 남기는 것은 성능과 부하 측면에서 현실적으로 불가능
- 어느 이상의 심각한 수준에 대해서 선별적으로 로그를 남기는 것을 권장
- 서버에서 다루고 있는 보안 수준에 따라 로그 수준(level)을 결정
| 수준(Level) | 설명 |
|---|
| Emergency | 시스템이 전면 중단되는 패닉(panic)이 발생할 정도로 심각한 수준 |
| Alert | 주의가 필요한 심각한 오류가 발생한 수준 |
| Critical | 하드웨어 등의 심각한 오류가 발생한 경우 |
| Error | 일상적인 오류가 발생한 경우 |
| Warning | 경고 수준 |
| Notice | 오류는 아니지만 관리자의 조치가 필요한 경우 |
| Informational | 의미 있는 정보가 있는 경우 |
| Debug | 문제가 있는 것은 아니고 문제 해결을 돕기 위해 부가적인 정보를 제공하기 위한 경우 |
- syslog 로그 파일의 종류 및 경로
- 대부분 로그 파일의 경로가 미리 약속되어 있음
| 구분 | 로그 생성 시스템(facility) | 파일 경로 | 설명 |
|---|
| 시스템 로그 | (기본) | /var/adm/syslog.log | 운영체제에 의해 생성되는 메인 로그 |
| | /var/adm/messages | |
| | /var/log/messages | |
| 보안 로그 | auth | /var/adm/auth.log | 로그인의 실패 등 보안과 관련된 로그 |
| authpriv | /var/log/secure | |
| 메일 로그 | mail | /var/adm/mail.log | (sendmail 등에 의한) 메일 관련 로그 |
| | /var/log/maillog | |
| 부팅 로그 | local0 ~ local7 | /var/adm/ras/bootlog | 운영체제 부팅 시의 로그 |
| | /var/log/boot.log | |
| 커널 로그 | Kern | /dev/console | 운영체제가 콘솔에 출력하는 로그 |
서비스 관리
- 이메일 서비스를 관리하라
- 리눅스의 이메일 서비스 : sendmail 서비스
- 이메일을 보내거나(발송) 받는(수신) 등의 역할 수행
- 보안 취약점이 많이 알려져 있음
(예) 버퍼 오버플로우 공격에 의한 시스템 권한 획득
- 가능한 sendmail을 비활성화 권장
- 서비스 정지 : systemctl stop sendmail
- 서비스 비활성화 : systemctl disable sendmail
- 추천 스택 : Postfix(SMTP 서버용) + Dovecot(IMAP/POP3 서버용) + 추가적인 보안도구(스팸 필터링, 바이러스 검사 등)
- 반드시 사용해야만 하는 경우: 최신의 sendmail 버전을 유지 필요 (보안 취약점 보완)
- 최신 버전 정보: 한국인터넷진흥원 (KISA) 홈페이지를 통해 확인 가능

- 안전한 소프트웨어 개발을 위해 소스코드에서 보안 취약점을 제거
- 동의어 : 안전한 코딩 또는 시큐어 코딩 (Secure Coding)
- 시큐어 코딩이 적용된 소프트웨어 개발 과정

소스코드의 보안 취약점을 이용한 사이버 공격은 방화벽, 침입 차단 시스템, 침입 방지 시스템 등의 일반적인 보안 장비로는
대응이 어려움 → 보안장비들은 ‘정상’으로 인식
- 대표적인 시큐어 코딩 가이드
- CERT(컴퓨터 비상 대응팀, Computer Emergency Response Team) 의 가이드
- 우리나라 : 행정안전부의 소프트웨어 보안 개발 가이드
- boho.or.kr
① 메모리 버퍼 오버플로(Memory Buffer Overflow) 공격
- 프로그램이 실행되는 도중에 메모리 오류가 발생하여 의도하지 않는 동작이 일어나는 보안 취약점
- 개발자가 예상한 범위를 벗어난 입력 값이 전달
- 지정된 크기의 저장 공간(버퍼, Buffer)보다 넘치게(오버플로, Overflow) 저장
- 이렇게 넘치게 저장된 값으로 시스템에 보안 문제를 일으키는 보안 공격

- 버퍼 오버플로가 발생할 수 있는 안전하지 않은 C 소스코드의 예제
01: #include <stdio.h>
02: int main(int argc, char* argv[])
03: {
04: char buffer[10] = {0};
05: if (argv[1] != NULL)
06: strcpy(buffer, argv[1]);
07: printf("%s\n",buffer);
08: }
a.out 012345 [엔터]
012345
- 사용자가 입력한 값의 길이가 10보다 클 때
- 0123456789…0123456789ABCD
- 보안 공격자가 버퍼 오버플로 결함을 통해 공격
- 전달하는 데이터의 길이와 내용을 적절히 조정해서 프로그램이 의도하지 않는 방식으로 실행 가능
- 예) buffer에 인접한 메모리 영역 : 프로그램 흐름 제어와 관련된 값을 저장하는 곳
- 다음 단계로 이동되어야 할 메모리 주소 저장
- 메모리 주소 0xABCD로 설정하여, 함수 auth_success()가 다음 단계에서 실행되도록 함

- 대응 방안
- 최신 운영체제의 자체 방어
- 예)
- 스택 실행 권한 해제(Non-Executable Stack),
- 랜덤 스택(ASLR: Address Space Layout Randomization),
- 데이터실행 방지(DEP: Data Execution Prevention),
- 스택 가드(Stack Guard),
- 스택 실드(Stack Shield) 등
- 오피스, 어도비(Adobe) 등의 보안 패치
- 보안 공격자들이 새롭게 찾아낸 메모리 버퍼 오버플로 공격을 막으려고 프로그램을 수정
- 시큐어 코딩 : 개발자는 개발 단계에서부터 이러한 메모리 버퍼 오버플로가 발생하지 않도록 안전한 코딩을
하는 것이 필요
- 보안 대책 1: 입력 값에 대한 길이(크기) 검증
05: if (argv[1] != NULL && strlen(argv[1]) < sizeof(buffer) )
06: strcpy(buffer, argv[1]);
- 보안 대책 2: 오버플로에 안전한 라이브러리 사용

- 보안 대책 3: 정적 소스 분석 도구로 미리 수정하기
- 예) valgrind, cppch eck, mudflap 등과 같은 상용이나 공개 분석 도구 사용
② 포맷 스트링 공격

01: #include <stdio.h>
02: int main(int argc, char* argv[])
03: {
04: int a = 100;
05: printf("%x \n", a);
06: printf("%d \n", a);
07: }
01: #include <stdio.h>
02: int main(int argc, char* argv[])
03: {
04: printf( argv[1] );
05: }
【실행 예】
$ a.out addr-%x [엔터]
addr-eec41a10
현재 실행되고 있는 메모리 주소 확인
04: printf("%s", argv[1] );
【실행 예】
$ a.out addr-%x [엔터]
addr-%s
- 포맷 스트링을 이용한 메모리 변조
- %n은 메모리 값을 읽은 것이 아닌,
현재까지 화면에 출력된 문자 수를 저장!
01: #include <stdio.h>
02: int main(int argc, char* argv[])
03: {
04: int value = 100, target = 0;
05: printf("%d%n \n", value, &target);
06: printf("%d \n", target);
07: printf("%16d%n\n", value, &target);
08: printf("%d \n", target);
07: }
【실행 예】
$ a.out [엔터]
100
3
100
16
- 포맷 스트링을 이용한 메모리 변조
- 포맷 스트링 파라미터 %n은 메모리의 값 저장 : 메모리 변조 가능
- 변경하려는 값이 메모리 주소 0xeec41a10 (10진수로는 4005829136) 라면, %4005829136d로 설정
- 자신이 전달하는 데이터의 길이와 내용을 조절해서 프로그램이 의도하지 않은 방식으로 동작 가능해짐
eec41a10 → %4005829136d

(참고) vi 에디터
- vi 에디터 실행 및 모드
- vi 에디터의 실행
- 모드
- 삽입 모드 : 원하는 글자를 입력하는 상태
- 명령어 모드 : 방향키로 이동하거나, 글자 삭제 등의 편집이 가능한 상태
- 라인 편집 모드 : 파일을 저장하거나 종료할 수 있는 상태
![업로드중..]()
vi 에디터 명령어(계속)
| 명령어 | 의미 | 비고 |
|---|
h | 왼쪽으로 한 칸 이동 | |
j | 아래 줄로 이동 | |
k | 윗 줄로 이동 | |
l | 오른쪽으로 한 칸 이동 | |
0 | 현재 줄의 처음으로 이동 | 숫자 0 |
L | 화면의 마지막 라인으로 이동 | |
Ctrl+f | 한 페이지 아래로 이동 | |
Ctrl+b | 한 페이지 위로 이동 | |
| 명령어 | 의미 | 비고 |
|---|
set nu | Vim에서 라인 번호 출력 | |
set nonu | Vim에서 라인 번호 출력 취소 | |
| 명령어 | 의미 | 비고 |
|---|
:w | 현재 편집하는 파일을 저장 | Write |
:q | 현재 편집하는 파일을 저장하지 않고 종료 | Quit |
:wq | 현재 편집하는 파일을 저장하고 종료 | Write & Quit |
:q! | 현재 편집하는 파일을 저장하지 않고 강제 종료 | Quit (Force) |
| 명령어 | 의미 | 비고 |
|---|
i | 현재 커서가 있는 곳에 글자를 추가 | Insert |
a | 커서의 우측에 글자를 추가 | Append |
x | 현재 커서가 있는 곳의 글자를 삭제 | |
dd | 현재 커서가 위치한 라인(한 줄)을 삭제 | Delete Line |
yy | 현재 줄을 버퍼로 복사 | Ctrl + C |
p | 현재 커서가 있는 줄 바로 아래에 붙여넣기 | Ctrl + V |
(참고) vi 에디터 실습
• vi로 test.c 생성 후 컴파일
![업로드중..]()