폐쇄망 현장 — 방산·국방 도메인 · 반입 매체 검역 · 실습
반입 매체를 풀기 전에 검역하기
목표
반입 매체의 압축 파일을 풀기 전에 목록만 읽어 규모·위험 항목·압축비·형식 불일치를 판정하는 검역기를 만들고, 추출 필터로 항목마다 걸러 격리 디렉터리에 푼 뒤 근거 해시를 붙인 반입 판정서를 씁니다.
왜 중요한가
폐쇄망에 들어오는 것은 대부분 사람이 들고 온 매체이고, 그 안에는 압축 파일 하나가 들어 있습니다. 안을 보려고 푸는 그 한 줄이 이미 파일 시스템을 건드리는 행위입니다. 절대 경로, 상위 경로 탈출, 밖을 가리키는 링크, 특수 파일, 압축 폭탄은 전부 푸는 순간에 효과가 납니다.
tar 헤더에는 이름·크기·권한·항목 종류·링크 대상이 적혀 있어서, 풀지 않고도 이 다섯 가지를 전부 볼 수 있습니다. 그래서 순서를 바꿉니다. 먼저 읽고, 판정하고, 조건을 걸어 풉니다.
판정서에는 근거가 붙어야 합니다. 어떤 아카이브의 어떤 해시를 어떤 보고서로 읽었고 그 보고서에서 어떤 사유가 나왔는지가 이어져야, 협력사가 무엇을 고쳐야 하는지 알고 심사자는 같은 판정을 다시 낼 수 있습니다.
채점기는 여러분의 문구를 믿지 않습니다. 아카이브를 직접 열어 나와야 하는 값을 스스로 계산하고, 실행 계약대로 여러분의 검역기를 다시 돌려 그 출력까지 대조합니다.
단계
1. 생성 스크립트로 매체 두 개를 만들고 접수 대장 /root/media/intake.tsv 에 일련번호·수령 시각·제출자 역할·바깥 해시·크기를 적습니다.
2. /root/media/inspect.py 를 만들어 MEDIA-2609-017 을 풀지 않고 목록만 읽어 항목 수·총 해제 크기·최대 항목을 /root/media/report/MEDIA-2609-017.json 에 적습니다.
3. inspect.py 에 danger 분류를 넣습니다. absolute·traversal·escaping_link·special·exec_bit 다섯 칸을 두고 해당 없는 칸도 빈 목록으로 남깁니다.
4. inspect.py 에 ratio 와 ratio_verdict 를 넣습니다. 총 해제 크기를 압축 파일 크기로 나눈 값이 100 을 넘으면 bomb 입니다.
5. inspect.py 에 mismatch 를 넣습니다. 확장자가 말하는 형식과 앞머리 바이트가 말하는 형식이 다른 항목을 name·declared·actual 로 적습니다.
6. inspect.py 에 --extract-to 를 넣어 data 필터로 항목마다 판정하고, /root/media/quarantine/MEDIA-2609-017 에 풀고 extracted 와 rejected 를 보고서에 적습니다.
7. /root/media/decide.py 로 보고서를 반입 판정서 /root/media/report/verdict-MEDIA-2609-017.json 으로 옮깁니다. media·archive_sha256·report_sha256·decision·reasons·accepted_entries·rejected_entries 를 적습니다.
8. 같은 검역기와 같은 판정 규칙을 MEDIA-2609-018 에 돌려 /root/media/report/MEDIA-2609-018.json 과 /root/media/report/verdict-MEDIA-2609-018.json 을 만들고, 두 매체를 나란히 놓은 /root/media/report/compare.tsv 를 씁니다.
참고
- 실행 계약:
python3 /root/media/inspect.py --archive <매체> --out <보고서> [--extract-to <디렉터리>]. 판정 규칙은python3 /root/media/decide.py --report <보고서> --out <판정서>입니다. 채점기가 이 계약대로 직접 다시 돌립니다. - 매체는
/root/media/in/MEDIA-2609-017.tar.gz와/root/media/in/MEDIA-2609-018.tar.gz, 격리 디렉터리는/root/media/quarantine/<일련번호>입니다. - 판정 규칙(이 실습의 가정): absolute·traversal·escaping_link·special·bomb 중 하나라도 있으면 reject, 사유가 exec_bit 이나 mismatch 뿐이면 quarantine, 아무것도 없으면 accept 입니다. reasons 는 사유 이름을 정렬한 목록입니다.
- 목록은
tar -tvf, 파이썬은tarfile.open(...).getmembers()로 읽습니다. 항목별 판정은tarfile.data_filter(member, dest)가 냅니다. - 앞머리 바이트는
od -An -tx1 -N8이나 파이썬으로 봅니다. NUL 이 섞인 항목이 있어grep·head로는 제대로 못 봅니다. - 흔한 실수:
extractall()에 필터만 걸어 첫 거절에서 멈추기, 보고서를 다시 만들고 판정서의 해시는 그대로 두기, danger 의 빈 칸을 아예 빼 버리기. - 이 실습은 폐쇄망이라
zip·unzip·xz·gpg가 없습니다.tar와gzip만 씁니다.
단계 8개
- 매체를 열기 전에 접수 대장부터
- 풀지 않고 목록만 읽어 규모 재기
- 위험 항목을 다섯 갈래로 나누기
- 압축비로 폭탄 가리기
- 확장자와 실제 형식 맞춰 보기
- 추출 필터로 항목마다 걸러 풀기
- 근거 해시를 붙인 반입 판정서 쓰기
- 두 번째 매체로 판정이 갈리는지 보기