리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 26 / 50 · Part 3. Linux 명령어 활용
실습 환경: 21편 실습용 샘플 로그 (secure, access_log)
이전 글: 25. cut과 awk

1. 들어가며

sed(stream editor)는 입력을 한 줄씩 읽어 치환·삭제·추출 한 결과를 출력하는 도구다. 설정 파일 수정 도구로 많이 알려져 있지만, 관제·분석 업무에서는 다음 네 가지 용도가 특히 유용하다.

  1. 구간 추출: 특정 이벤트부터 다른 이벤트까지의 로그만 잘라 보기
  2. 마스킹: 보고서나 공유 자료에 넣기 전에 IP·계정·비밀번호 가리기
  3. 디코딩: URL 인코딩된 웹 공격 요청을 사람이 읽을 수 있게 바꾸기
  4. 정규화: 버전·배포판마다 다른 로그 형식을 하나로 맞추기

그리고 반드시 기억해야 할 금지 사항이 하나 있다. 분석 대상 원본 파일에 sed -i를 쓰지 않는다.


2. 핵심 개념

2-1. 기본 문법

sed [옵션] '[주소]명령' 파일
명령의미예
p출력 (-n과 함께)sed -n '10,20p'
d삭제sed '/^#/d' (주석 줄 제거)
s/A/B/A를 B로 치환 (첫 번째만)s/root/****/
s/A/B/g줄 안의 모든 A 치환
=줄 번호 출력sed -n '/Accepted/='

2-2. 주소 (어느 줄에 적용할지)

주소의미
1010번째 줄
10,2010~20번째 줄
/패턴/패턴과 일치하는 줄
/A/,/B/A가 나온 줄부터 B가 나온 줄까지
$마지막 줄

2-3. 옵션

옵션의미
-n자동 출력 끄기 (p로 지정한 줄만 출력)
-E확장 정규식 ((), +, {n})
-i원본 파일을 직접 수정 — 증거 파일에는 사용 금지
-e여러 명령 지정 (;로도 연결 가능)

치환의 \1, \2는 -E의 괄호로 묶은 부분(캡처 그룹)을 다시 쓰는 것이다.


3. 동작 원리

sed 로그 분석 활용 4가지 — 그리고 절대 하지 말 것

sed는 한 줄을 패턴 공간(pattern space) 이라는 버퍼에 읽어 명령을 적용하고, 결과를 표준 출력으로 내보낸다. 원본 파일은 읽기만 한다.

-i 옵션을 쓰면 동작이 달라진다. GNU sed는 결과를 임시 파일에 쓴 뒤 원본 이름으로 교체 한다. 즉 11편에서 본 mv와 같은 효과가 생겨서 inode가 바뀌고, mtime·ctime이 현재 시각으로 갱신 된다. 원본 로그에 sed -i를 한 번이라도 실행하면 "분석가가 증거를 수정했다"는 문제가 생기고, 그 파일을 쓰고 있던 프로세스(rsyslog)는 옛 inode에 계속 기록하게 된다.


4. 실습

cd ~/lab

# 1) 구간 추출: 로그인 성공부터 su 실패까지
sed -n '/Accepted password for devuser/,/FAILED SU/p' secure

# 2) 줄 번호로 자르기 (grep -n / sed -n '=' 로 위치 확인)
sed -n '/Accepted password/=' secure
sed -n '127,131p' secure

# 3) 마스킹 — IP 마지막 자리, 계정명
grep "Accepted password" secure \
  | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+/\1.xxx/g; s/for [a-z]+/for ****/'

# 4) 설정 파일의 비밀번호 마스킹 (출력만, 원본 유지)
printf 'db_host=10.0.0.200\ndb_user=webapp\ndb_pass=S3cr3t!2026\n' > app.conf
sed -E 's/^(db_pass=).*/\1********/' app.conf

# 5) URL 디코딩 (%XX → 문자)
grep -E '%2f|%27|%20' access_log | awk '{print $7}' \
  | while read -r u; do printf '%b\n' "$(echo "$u" | sed 's/%/\\x/g')"; done

# 6) 형식 정규화: 호스트명·PID 제거, sshd-session 통일
sed -E 's/sshd-session\[/sshd[/; s/^([A-Z][a-z]{2} +[0-9]+ [0-9:]+) [^ ]+ ([a-z]+)\[[0-9]+\]: /\1 \2: /' secure | head -3

# 7) 주석·빈 줄 제거로 설정 파일 핵심만 보기
sed -E '/^\s*(#|$)/d' /etc/ssh/sshd_config

5. 결과 분석

샘플 로그에 실행한 실제 결과다.

① 구간 추출

Sep 23 02:19:21 rocky sshd[5224]: Accepted password for devuser from 10.0.0.128 port 51514 ssh2
Sep 23 02:19:21 rocky sshd[5224]: pam_unix(sshd:session): session opened for user devuser(uid=1001) by (uid=0)
Sep 23 02:21:21 rocky sudo[5233]:  devuser : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/devuser ; USER=root ; COMMAND=/bin/bash
Sep 23 02:22:21 rocky su[5270]: pam_unix(su-l:auth): authentication failure; logname=devuser uid=1001 euid=0 tty=pts/1 ruser=devuser rhost=  user=root
Sep 23 02:22:21 rocky su[5270]: FAILED SU (to root) devuser on pts/1

시작 줄과 끝 줄을 이벤트 이름 으로 지정할 수 있어서, 줄 번호를 몰라도 사건 구간을 보고서에 그대로 옮길 수 있다.

② 마스킹

Sep 23 02:19:21 rocky sshd[5224]: Accepted password for **** from 10.0.0.xxx port 51514 ssh2
db_pass=********

③ URL 디코딩

/view.php?file=../../../etc/shadow
/board.php?id=1' OR '1'='1
/board.php?id=1 UNION SELECT user,pass FROM members--

인코딩된 원문(..%2f..%2f, 1%27%20OR%20%271%27=%271)만 보면 공격 의도가 잘 보이지 않는다. 디코딩하면 경로 탐색 과 SQL Injection(항상 참 조건, UNION 기반 조회) 시도가 명확해진다. 보고서에는 원문과 디코딩 결과를 함께 적는다.

④ 정규화

Sep 23 01:47:45 sshd: Failed password for root from 203.0.113.150 port 51662 ssh2
Sep 23 02:10:09 sshd: Failed password for root from 10.0.0.128 port 59219 ssh2
Sep 23 02:10:18 sshd: Failed password for root from 10.0.0.128 port 40083 ssh2

6. 보안 관점

상황위험올바른 방법
원본 로그에 sed -iinode·시각 변경, 증거 훼손, 기록 중단사본에서 작업, 결과는 > 새파일
설정 파일 일괄 수정문법 오류로 서비스 중단 (sshd 등)-i.bak로 백업, 수정 후 문법 검사 (sshd -t)
보고서에 원문 그대로계정·내부 IP·비밀번호 노출마스킹 규칙 적용
디코딩 결과만 기록원래 요청을 재현·검색할 수 없음원문 + 디코딩 결과 병기
탐욕적 정규식.*가 의도보다 많이 치환[^ ]+처럼 범위 제한

설정 파일을 sed로 바꾸는 것은 운영에서 흔하지만, 보안 설정(예: PermitRootLogin)을 바꿀 때는 백업 → 수정 → 문법 검사 → 재시작 → 접속 확인 순서를 지킨다.

sudo sed -i.bak -E 's/^#?PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshd

7. SOC / 보안관제 활용

7-1. 보고서용 로그 정리 파이프라인

# 사건 구간 추출 → 호스트·PID 정리 → 내부 IP 마스킹 → 새 파일로 저장
sed -n '/02:10:0/,/FAILED SU/p' secure \
  | sed -E 's/ rocky ([a-z]+)\[[0-9]+\]:/ \1:/' \
  | sed -E 's/10\.0\.0\.([0-9]+)/10.0.0.x/g' \
  > incident_20260923_timeline.txt
sha256sum incident_20260923_timeline.txt

7-2. 분석 흐름

[입력]     원본 secure / access_log (읽기 전용, 사본)
   ↓
[sed 추출]  사건 구간 /Accepted/,/FAILED SU/
   ↓
[sed 디코딩] 웹 공격 URL → 경로 탐색, SQLi 확인
   ↓
[sed 정규화] 서버별 형식 차이 제거 → 여러 서버 로그를 한 타임라인으로
   ↓
[sed 마스킹] 계정·내부 IP·비밀번호 가림
   ↓
[출력]     보고서 첨부 파일 + 해시

8. 핵심 정리

  • sed는 한 줄씩 치환(s)·삭제(d)·출력(p) 하며, 기본적으로 원본을 바꾸지 않는다.
  • /A/,/B/p로 이벤트 기준 구간 추출 이 가능하다.
  • -E와 캡처 그룹(\1)으로 마스킹·정규화 규칙을 만든다.
  • URL 인코딩은 sed 's/%/\\x/g' + printf '%b'로 디코딩해 공격 의도를 확인한다.
  • sed -i는 inode·시각을 바꾼다. 증거 원본에는 절대 쓰지 않고, 설정 파일에는 -i.bak + 문법 검사를 함께 쓴다.

9. 다음 글

다음 글 「27. 파이프라인과 리다이렉션」 에서는 지금까지 당연하게 써 온 |, >, 2>/dev/null의 원리를 정리한다. 표준 입력·출력·오류(파일 디스크립터 0·1·2)의 흐름을 이해하고, 분석 결과를 안전하게 저장하고 기록하는 방법(tee, set -o pipefail) 을 다룬다.


참고 자료

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글