LMS 파일 업로드 보안 설계 — 과제·자료실이 웹셸 통로가 되지 않게 만드는 7가지 기술
LMS의 과제 제출·자료실·프로필 업로드는 웹셸이 가장 많이 들어오는 입구입니다. 확장자 검사만으로는 왜 부족한지, 저장소 분리·실행 차단·서명 주소·콘텐츠 형식 검증 등 WEBHEADS가 적용한 7가지 설계를 기술적으로 설명합니다.
한 줄 요약: 업로드 보안의 핵심은 '나쁜 파일을 찾아내는 것'보다 '어떤 파일이 올라와도 실행되지 않는 구조'를 만드는 것입니다. WEBHEADS(웹헤즈) LMS는 업로드 파일을 웹 서버와 분리된 저장소에 두고, 실행 권한이 없는 상태로만 내려주는 방식을 기본으로 합니다.
확장자 검사만으로 부족한 이유: 많은 레거시 LMS가 .php, .jsp, .asp 같은 확장자를 막는 차단 목록 방식으로 업로드를 검사합니다. 하지만 .pHp처럼 대소문자를 섞거나, .php5, .phtml, .phar처럼 덜 알려진 확장자를 쓰거나, shell.php%00.jpg처럼 널 바이트를 끼우거나, .htaccess 파일을 먼저 올려 jpg를 PHP로 실행하게 만드는 우회 기법이 오래전부터 알려져 있습니다. 차단 목록은 공격자가 새 우회법을 찾을 때마다 뚫립니다.
WEBHEADS가 적용한 7가지 설계: ① 저장소 분리 — 업로드 파일은 애플리케이션 서버가 아닌 객체 저장소에 저장되어, 웹 서버 디스크에 파일이 남지 않습니다. ② 실행 불가 저장소 — 객체 저장소는 파일을 해석하거나 실행하는 기능이 없어 .htaccess 같은 설정 파일도 의미가 없습니다. ③ 무작위 파일 이름 — 원래 이름은 DB에만 보관하고, 실제 저장 경로는 추측할 수 없는 값으로 바꿉니다. ④ 허용 목록 검사 — 과목별로 허용할 형식(PDF, 한글, 오피스, 이미지, 영상)만 받는 방식이며, 확장자와 함께 파일 형식 정보도 확인합니다.
⑤ 서명 주소 다운로드 — 비공개 자료는 로그인한 수강생에게만, 짧은 시간 동안 유효한 주소로 내려줍니다. 주소를 다른 사람에게 넘겨도 시간이 지나면 열리지 않습니다. ⑥ 다운로드 응답 헤더 — 첨부 파일은 Content-Disposition: attachment와 X-Content-Type-Options: nosniff로 내려보내 브라우저가 파일을 웹 페이지처럼 해석하지 않게 합니다. ⑦ 권한 정책 — 저장소 접근도 PostgreSQL과 같은 행 단위 정책을 따르기 때문에, 강사는 자기 과목 자료만, 수강생은 자기 과제만 볼 수 있습니다.
운영 단계에서 챙기는 것: 설계가 좋아도 운영이 느슨하면 소용이 없습니다. WEBHEADS는 업로드 용량 상한을 과목별로 두고, 비정상적으로 많은 업로드나 같은 IP의 반복 실패를 기록해 관리자 화면에서 확인할 수 있게 했습니다. 또 그누보드·워드프레스 계열 취약 주소를 찾는 자동 접속은 차단 목록으로 관리하며, 차단 횟수와 마지막 차단 시각을 관리자가 바로 볼 수 있습니다.
보안 담당자 검토 포인트: 업로드 기능을 평가할 때는 '어떤 확장자를 막나요?'보다 아래 세 가지를 먼저 물어보시길 권합니다. ① 업로드 파일이 저장되는 곳에서 스크립트가 실행될 수 있는가 ② 저장 경로를 외부에서 추측할 수 있는가 ③ 다른 사용자의 파일을 주소만 바꿔서 받을 수 있는가(IDOR). 세 질문에 모두 '아니오'라고 답할 수 있어야 웹셸과 자료 유출 위험을 함께 낮출 수 있습니다.
자주 묻는 질문 — 백신 검사를 하면 충분하지 않나요? 백신 검사는 알려진 악성 파일을 거르는 데 도움이 되지만, 한 줄짜리 웹셸이나 새로 변형된 코드는 놓칠 수 있습니다. 그래서 검사는 보조 수단으로 두고, '실행되지 않는 구조'를 1차 방어선으로 삼는 것이 안전합니다. 자세한 기준은 보안 센터 페이지에서 확인하실 수 있습니다.
관련 글
주식회사 웹헤즈 · 대표전화 02-540-4337 · 도입 문의