Step 97. Bandit 6~10 — find 조건 검색 마스터
Level 2 — 보안 입문과 공격 스킬 기초 | 난이도 ★★★☆☆ | 예상 소요 시간 3시간
전제: Step 96의 풀이 사이클과 Bandit 0→6 비밀번호 체인을 마쳤다. 파이프(
|)의 기본을 안다.
- 준비물: SSH 접속 환경, Step 96에서 찾은 비밀번호 기록, 로컬 실험용 리눅스/WSL.
- ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다.
- 합법 연습장 안내: OverTheWire Bandit은 운영자가 공식적으로 공격 연습을 허가한 합법 학습 플랫폼입니다. 오늘의 검색 명령들은 이 서버와 내 컴퓨터의 연습 폴더에서만 사용합니다.
서버에 처음 들어간 사람이 던지는 첫 질문은 "여기 뭐가 있지?"입니다. 그 질문에 답하는 도구의 왕이 find입니다. 이름, 크기, 주인, 그룹, 권한, 수정 시각 — 파일의 어떤 속성이든 조건으로 걸어 전수 조사하는 명령입니다. Bandit 6~10은 이 도구의 단련장입니다. "서버 전체에서 이 조건의 파일을 찾아라"는 문제의 연속이죠. 오늘의 진짜 수확은 명령이 아니라, 자연어 질문을 조건 조합으로 번역하는 사고 회로입니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
find의 조건(-user,-group,-size,-perm,-mtime,-writable)을 AND로 조합해 원하는 파일만 정확히 뽑는다2>/dev/null로 권한 에러를 걸러 내고, 그 원리를 설명한다grep,sort | uniq -u,strings,base64 -d로 데이터 속 정답을 건진다- SUID 파일이 무엇이며 왜 정찰의 단골 목표인지 설명하고 목록을 뽑는다
- "최근 바뀐 파일", "내가 쓸 수 있는 파일" 같은 실전 질문을 find 한 줄로 번역한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 리눅스 셸(Bandit 서버 + 로컬 WSL) |
| 오늘의 명령 | find, grep, wc, sort, uniq -u, strings, base64 -d |
| 필요한 개념 | 조건의 AND 조합, 리다이렉션(2>), SUID 권한 비트, 인코딩과 암호화의 구분 |
| 오늘의 산출물 | Bandit 6→11 비밀번호 체인 + find 조건 카드 문서 |
2-1. find의 문법 — 조건을 레고처럼
find 어디서 -조건1 -조건2 ...
조건은 나열할수록 AND로 좁아집니다. 오늘 쓸 조건 조각들입니다.
| 조건 | 뜻 | 예 |
|---|---|---|
-type f / -type d |
파일만 / 폴더만 | find . -type d |
-name 패턴 |
이름(와일드카드 가능) | -name "*.log" |
-user 이름 |
소유자 | -user bandit7 |
-group 이름 |
소속 그룹 | -group bandit6 |
-size Nc |
크기(c=바이트) | -size 33c |
-perm /4000 |
SUID 비트 켜진 것 | 뒤에서 자세히 |
-mtime -1 |
하루 안에 수정된 것 | -mtime -7 = 최근 1주 |
-writable |
내가 쓸 수 있는 것 | -writable -type f |
조건 앞의 !는 부정("~이 아닌")입니다. 그리고 서버 전체를 검색할 때 화면을 덮는 권한 에러를 버리는 꼬리표 2>/dev/null을 기억하세요. 2는 에러 출력 통로의 번호, /dev/null은 버리는 구멍입니다.
2-2. SUID — find의 진짜 사냥감
리눅스 파일 권한 중 특수한 비트가 하나 있습니다. SUID(Set User ID)가 켜진 실행 파일은, 실행하는 순간 그 파일 주인의 권한으로 돌아갑니다. root 소유 + SUID인 프로그램은 누가 실행해도 root의 힘으로 동작합니다.
이 장치는 필요해서 존재합니다 — 대표적으로 passwd(비밀번호 변경 도구)는 일반 사용자 대신 시스템 파일을 고쳐야 하므로 SUID입니다. 하지만 구멍 있는 SUID 프로그램은 일반 사용자를 관리자로 끌어올리는 사다리가 됩니다. 그래서 침투 정찰의 필수 질문이 "이 서버에 SUID 파일이 뭐가 있지?"입니다.
find / -perm /4000 -type f 2>/dev/null
-perm /4000이 "SUID 비트가 켜진 것"이라는 조건입니다. 오늘 내 컴퓨터에서 직접 돌려 봅니다.
2-3. 데이터 속의 한 줄 — grep 계열 도구들
6~10 구간의 나머지 문제들은 "찾기"가 아니라 "건지기"입니다. 수만 줄 파일에서 패턴 하나(grep), 중복투성이에서 유일한 줄(sort | uniq -u), 바이너리 덩어리에서 읽히는 문자열(strings), Base64로 꼬인 문자열 되돌리기(base64 -d).
공통점이 보이시나요? 전부 "양이 많을 때 신호만 남기는" 도구입니다. 로그 분석과 침해 조사의 일상이 바로 이 작업입니다.
3. 따라 하기
3-1. Level 6 → 7 — 서버 전체 조건 검색
목표: "서버 어딘가에 있는, 소유자 bandit7, 그룹 bandit6, 크기 33바이트인 파일."
입력 (서버 안에서, 출력 예시)
ssh bandit6@bandit.labs.overthewire.org -p 2220
find / -user bandit7 -group bandit6 -size 33c 2>/dev/null
읽는 법: /에서 시작하니 서버 전체를 뒤집니다. 조건 세 개가 AND로 겹쳐 수만 개 중 하나를 정확히 집어냅니다. 2>/dev/null 덕분에 화면은 깨끗합니다.
같은 조건 검색을 내 컴퓨터에서 재현해 봅시다. 33바이트 파일을 만들고 주인을 바꿔 둔 뒤 찾는 실험입니다 (2026-09-09 WSL 실측):
printf 'x%.0s' {1..33} > target33.txt
echo hello > other.txt
chown nobody:nogroup target33.txt
find . -user nobody -group nogroup -size 33c 2>/dev/null
출력 (2026-09-09 실측):
./target33.txt
조건 세 개가 겹쳐 other.txt는 걸러지고 target33.txt만 남았습니다. chown은 소유자를 바꾸는 명령으로, 로컬 실험 파일에만 사용하세요.
3-2. Level 7 → 8 — 거대 파일 속의 한 줄
목표: data.txt 속 "millionth"라는 단어 옆의 값.
입력 (서버 안에서, 출력 예시)
wc -l data.txt
grep millionth data.txt
내 컴퓨터에서 규모부터 확인하는 습관까지 재현한 결과입니다 (2026-09-09 WSL 실측 — 2만 줄짜리 파일을 만들고 마지막에 정답 줄을 심었습니다):
20001 data.txt
millionth R3alPassW0rdHere
읽는 법: wc -l은 줄 수를 세어 규모를 먼저 알려 주고, grep 패턴 파일은 패턴이 든 줄만 건집니다. "거대한 데이터에서 패턴 하나를 건지는 것"은 로그 분석 그 자체입니다.
3-3. Level 8 → 9 — 딱 한 번 등장한 줄
이번엔 "한 번만 등장하는 유일한 줄"이 답입니다.
입력 (서버 안에서, 출력 예시)
sort data.txt | uniq -u
로컬 재현 (2026-09-09 WSL 실측):
printf 'apple\nbanana\napple\ncherry\nbanana\nunique_line_xyz\napple\n' > data.txt
sort data.txt | uniq -u
cherry
unique_line_xyz
읽는 법: sort가 같은 줄끼리 모으면, uniq -u가 "딱 한 번 나온 줄"만 남깁니다. 파이프 앞뒤가 세트라는 점 — 정렬 없이 uniq를 쓰면 떨어져 있는 중복을 못 잡습니다.
3-4. Level 9 → 10 — 바이너리 속 문자열
이번 data.txt는 대부분 깨진 바이트인 바이너리 파일이고, 그 안에 =가 몇 개 붙은 문자열이 답입니다.
입력 (서버 안에서, 출력 예시)
strings data.txt | grep "=="
로컬 재현 (2026-09-09 WSL 실측 — 바이너리 속에 문자열을 심은 실험 파일):
printf '\xde\xad\xbe\xefReadablePart==secret_token==\x00\xffmore_binary\x01' > data.txt
strings data.txt | grep '=='
ReadablePart==secret_token==
읽는 법: strings는 바이너리에서 "사람이 읽을 수 있는 문자열 조각"만 건져 줍니다. 낯선 실행 파일을 받았을 때 제일 먼저 돌려 보는 분석 명령이기도 합니다.
3-5. Level 10 → 11 — Base64 되돌리기
이번 파일은 영문·숫자가 길게 나열된 Base64 문자열입니다.
입력 (서버 안에서, 출력 예시)
cat data.txt
base64 -d data.txt
로컬 재현 (2026-09-09 WSL 실측):
echo 'VGhlIHBhc3N3b3JkIGlzIGJhbmRpdF9yb2Nrcwo=' > b64.txt
base64 -d b64.txt
The password is bandit_rocks
읽는 법: Base64는 암호가 아니라 변환입니다 — 번역표가 공개되어 누구든 같은 명령으로 되돌립니다. 끝의 = 꼬리가 Base64를 알아보는 단서입니다. Base64로 숨긴 비밀은 숨겨진 것이 아니라, 이상한 글자로 적힌 것일 뿐입니다.
3-6. SUID 목록 뽑기 — 정찰의 표준 장면
입력 (2026-09-09 WSL 실측, Ubuntu 24.04):
find / -perm /4000 -type f 2>/dev/null
출력 (2026-09-09 실측, 일부):
/usr/bin/passwd
/usr/bin/sudo
/usr/bin/su
/usr/bin/mount
/usr/bin/umount
/usr/bin/chsh
/usr/bin/gpasswd
... (총 14개)
읽는 법: 전부 "특권이 필요한 정상 도구"들입니다. 문제는 이 목록에 있을 이유가 없는 것이 섞여 있을 때입니다. 공격자는 이 목록에서 약한 프로그램을 찾고, 수비자는 이 목록을 "정상 목록"과 대조합니다. 같은 명령, 두 시선입니다.
참고: WSL은 최소 구성이라 14개가 나왔지만, 일반 서버는 이보다 많을 수 있습니다. 개수보다 "목록을 뽑고 대조하는 절차"가 중요합니다.
3-7. 조건 설계 훈련 — 질문을 명령으로 번역하기
find 실력의 본체는 "자연어 질문 → 조건 조합" 번역입니다. 다섯 문제를 먼저 직접 짜 보세요. 정답은 5번 섹션에 있습니다.
- /var에서 최근 7일 안에 바뀐
.log파일 전부 - 내 홈 폴더에서 크기가 10MB를 넘는 파일
- /tmp에서 내 소유가 아닌 파일
- /etc에서 폴더가 아닌 것(파일만)
- 현재 폴더에서 실행 권한이 있는 파일
+10M의 +는 "초과"(반대는 -10M 미만), ~는 내 홈 폴더, $(whoami)는 명령 결과를 그 자리에 넣는 치환 문법입니다.
해보기 (2026-09-09 WSL 실측 확인): find . -type f -printf '%T+ %p\n' | sort | head -3은 수정 시각과 경로를 함께 찍어 "가장 오래된 파일"을 찾습니다. -printf로 출력 형식을 직접 만드는 법까지 익히면 find가 완전히 손에 익습니다.
4. 미션과 연습문제
미션 — find 조건 카드와 실전 세 질문
- Bandit 6→11 비밀번호 체인을 완성하고 각 레벨을 Step 96의 write-up 형식으로 기록합니다
- 내 컴퓨터에서
find / -perm /4000 -type f 2>/dev/null로 SUID 목록을 추출하고, 각 항목이 무엇인지 표로 정리합니다 (man이나 검색으로 용도 조사) - 위키에
find-조건카드.md를 만듭니다 — 조건 옵션 7개 이상을 예시 명령과 함께 - 다음 세 질문에 find 한 줄로 답합니다: ① 내 홈의 1MB 이상 파일 ② 오늘 수정된 파일 ③
.pem확장자(열쇠 파일) 전부
연습문제
문제 1. find / -user bandit7 -group bandit6 -size 33c 2>/dev/null에서 각 부분(시작 경로, 조건 셋, 꼬리표)의 역할을 설명해 보세요.
문제 2. sort data.txt | uniq -u에서 sort를 빼면 어떤 문제가 생기나요?
문제 3. strings는 무엇을 하는 명령이며, 어떤 상황에서 가장 먼저 꺼내는 도구인가요?
문제 4. Base64로 적힌 비밀번호를 발견했습니다. 이것이 "안전하게 보호된 비밀번호"가 아닌 이유를 한 문장으로 말해 보세요.
5. 모범 답안과 완료 기준
미션 모범 답안
조건 설계 훈련(3-7)의 정답:
find /var -name "*.log" -mtime -7 2>/dev/null
find ~ -type f -size +10M
find /tmp -type f ! -user $(whoami) 2>/dev/null
find /etc ! -type d
find . -type f -executable
실전 세 질문의 답: ① find ~ -type f -size +1M ② find ~ -type f -mtime -1 ③ find / -name "*.pem" 2>/dev/null.
검증하는 법: ① 조건 카드의 각 옵션에 "내가 직접 실행해 본 예시"가 붙어 있는가. ② SUID 표의 각 항목에 용도 한 줄이 적혀 있는가. ③ 세 질문의 명령을 실제로 실행해 결과를 눈으로 확인했는가. 다섯 문제 중 셋 이상을 스스로 맞혔다면 find를 "아는" 것을 넘어 "쓰는" 단계입니다.
연습문제 해답
문제 1 해답. /는 검색 시작점(서버 전체)이고, -user/-group/-size 33c는 AND로 겹치는 세 조건이며, 2>/dev/null은 권한 부족 에러 출력을 버리는 꼬리표입니다. 셋이 모여 "서버 전체에서 이 세 속성을 모두 만족하는 파일만 조용히 보여 줘"가 됩니다.
문제 2 해답. uniq는 인접한 줄끼리만 비교하므로, 정렬하지 않으면 떨어져 있는 같은 줄을 중복으로 못 잡습니다. sort | uniq는 세트입니다.
문제 3 해답. 바이너리 파일에서 사람이 읽을 수 있는 문자열 조각만 건지는 명령입니다. 정체 모를 실행 파일이나 덤프를 받았을 때 "일단 strings"가 분석의 첫 걸음입니다 (3-4절 실측에서 바이너리 속 ==secret_token==을 건진 것 참조).
문제 4 해답. 번역표가 공개된 변환이라 열쇠 없이 누구나 base64 -d로 되돌릴 수 있기 때문입니다. 변환과 암호화를 가르는 기준은 "열쇠 없이 되돌릴 수 있는가"입니다.
완료 기준 체크리스트
- [ ] find 조건을 3개 이상 조합해 원하는 파일만 정확히 뽑을 수 있다
- [ ]
2>/dev/null의 뜻(에러 출력 버리기)과 필요성을 설명할 수 있다 - [ ] SUID가 무엇이며 왜 감시 대상인지 설명할 수 있다
- [ ]
grep,sort | uniq -u,strings,base64 -d를 상황에 맞게 쓸 수 있다 - [ ] 자연어 질문을 find 한 줄로 번역할 수 있다
- [ ] 미션: 체인 완성, 조건 카드, SUID 표를 완성했다
6. 흔한 실수와 해결
벽 1. find 결과가 텅 비었다
증상: 분명 있을 텐데 아무것도 안 나옵니다.
원인: 조건이 하나라도 틀리면 AND라 전체가 빈 손입니다. -size 33c의 c 누락이 최다 원인입니다 (Step 96에서도 같은 벽을 만났습니다).
해결: 조건을 하나씩 떼어 보며 어느 조건이 0개를 만드는지 좁히세요. find 디버깅의 정석은 "조건 빼기"입니다.
벽 2. "Permission denied"가 화면을 지배한다
증상 (실측 계열 메시지):
find: '/root': Permission denied
find: '/proc/1234': Permission denied
... 수백 줄
원인: / 전체 검색의 숙명입니다 — 내 권한이 닿지 않는 폴더마다 에러가 납니다.
해결: 2>/dev/null 꼬리표를 붙이세요. 관심 폴더(/home, /tmp)부터 좁혀 시작하는 전략도 유효합니다.
벽 3. sort | uniq -u가 이상하게 많은 줄을 보여 준다
증상: 유일한 줄이 하나여야 하는데 여러 줄이 나옵니다.
원인: 데이터 끝의 개행·공백 차이로 "같아 보이는 줄"이 실제로는 다른 경우가 있습니다.
해결: sort data.txt | uniq -c | sort -n | head로 등장 횟수부터 보세요. 횟수가 보이면 상황이 읽힙니다.
벽 4. Bandit 서버에서 find가 한참 간다
증상: / 검색이 몇 분씩 걸립니다.
원인: 정상입니다 — 수만 개 파일을 훑는 중입니다.
해결: 기다리거나, 유력 후보(/etc, /var)부터 순서대로 좁혀 가세요. 정찰도 우선순위가 있는 게임입니다. 내 컴퓨터에서도 find /는 /mnt/c 같은 마운트까지 훑으면 매우 느려집니다 — 범위를 좁히는 것이 정답입니다 (2026-09-09 WSL 실측에서 전체 스캔이 1분을 넘긴 것 확인).
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 조건의 AND 조합 | find 조건은 겹칠수록 좁아진다 |
2>/dev/null |
에러 출력(통로 2번)을 버리는 구멍으로 |
| SUID | 실행 순간 파일 주인 권한으로 도는 비트 |
| 정찰(recon) | 공격 전 "무엇이 어디에 있는가"의 전수 조사 |
| 신호와 잡음 | grep·uniq·strings는 양 속에서 신호만 남기는 도구 |
오늘의 명령어
| 명령 | 하는 일 |
|---|---|
find 경로 -조건 ... |
조건 검색의 왕 |
find / -perm /4000 -type f 2>/dev/null |
SUID 파일 전수 목록 |
grep 패턴 파일 |
패턴이 든 줄만 건지기 |
sort 파일 | uniq -u |
딱 한 번 등장한 줄 |
strings 파일 |
바이너리 속 읽히는 문자열 |
base64 -d 파일 |
Base64 되돌리기 |
wc -l 파일 |
줄 수(규모) 확인 |
명령어보다 중요한 감각
오늘의 명령들은 전부 한 줄입니다. 그런데 그 한 줄이 "서버 전체에서 이상한 것"을 건집니다. 해킹 도구가 거창할 필요는 없습니다 — 질문이 정확하면 명령은 짧아집니다. 그리고 같은 명령의 두 시선을 기억하세요. SUID 목록을 뽑는 명령은 공격자의 사다리 찾기이자 수비자의 점검표입니다. 도구는 중립이고, 시선이 방향을 정합니다. find가 손에 익으면 서버는 더 이상 검은 상자가 아닙니다 — 조건을 거는 자에게 모든 파일은 목록이 됩니다.
전부 체크되면 Step 97 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.