대상: Laravel을 프로덕션에서 운영하는 모두. 여기에 공격 절차는 없습니다 — 이 문서는 하드닝을 위한 실무 레퍼런스입니다: 우선순위순 체크리스트, 위험한 기본값, 영역별 지침, 그리고 자기 점검. 프레임워크 전반의 그림은 프레임워크별 보안 입구를 참고하세요.
우선순위순 하드닝 체크리스트
이 표를 위에서부터 처리하세요. P0은 나머지의 전제, P1은 사고가 가장 자주 나오는 곳, P2는 지속적인 유지 관리입니다.
P0 ── 전제(먼저 한다)
프로덕션 디버그 off / 시크릿을 공개 표면 밖에 권한 600으로 / APP_KEY 관리
P1 ── 최대 사고 원인
인가(Policy/Gate) / Mass Assignment 제어 / 의존성 CVE / 프로덕션 캐시
P2 ── 지속적인 유지 관리
세션/CSRF/쿠키 / 업로드 검증 / HTTPS, 헤더, 속도 제한
| 우선순위 | 대책 | 구체적 내용(Laravel) |
|---|---|---|
| P0 | 프로덕션 디버그 비활성화 | APP_DEBUG=false / APP_ENV=production, config:cache로 고정. 에러 페이지에 내부 정보를 흘리지 않기 |
| P0 | 시크릿을 공개 표면 밖으로 | .env, 백업, 키를 public/ 밖에, 권한 600. storage/logs는 비공개 |
| P0 | APP_KEY 안전 관리 | 암호화·서명 쿠키·세션의 근간. 환경에서 주입, 유출 시 교체 |
| P1 | 명시적 인가 | Policy / Gate + authorize() / can 미들웨어, 소유자/권한으로 스코프 |
| P1 | Mass Assignment 제어 | $fillable 선언; $request->all() 통째 대입 회피, validated() 사용 |
| P1 | Composer CVE 모니터링 | composer audit / osv-scanner; 실행 중인 버전으로 판단, 빠르게 패치 |
| P1 | 프로덕션 캐시 | config:cache route:cache view:cache로 설정 신뢰성 + 속도 |
| P2 | 세션/쿠키 안전 | secure http_only same_site 설정; 로그인 시 세션 재생성 |
| P2 | 업로드 검증 | 타입/크기 검증, public/ 밖에 저장, 실행 권한 없음 |
| P2 | HTTPS/헤더/속도 제한 | HTTPS 강제, HSTS, 로그인/API에 throttle |
1. 시크릿과 APP_KEY (P0)
Laravel은 기본적으로 .env를 도큐먼트 루트 밖(프로젝트 루트)에 둡니다. 사고는 대부분 시크릿을 있어서는 안 될 곳에 두는 것에서 나옵니다.
.env, DB 덤프, 백업, 키 파일을public/에 절대 두지 마세요. 시크릿은 앱 루트 밖에 권한 600(소유자만)으로 두세요.storage/나storage/logs/를 노출하지 마세요(로그에는 시크릿이나 개인 정보가 들어갈 수 있습니다)..env를 리포지토리에 커밋하지 마세요.- **
APP_KEY**는 암호화, 서명 URL, 암호화된 쿠키, 세션의 근간입니다. 환경에서 주입하고 유출되면 즉시 교체하세요(이는 기존 암호화 데이터/세션을 무효화한다는 점에 유의).
일반 원칙은 공개 디렉터리에 시크릿을 두지 않기를, 실제 전면 노출 사례는 .env 전면 노출 사례를 참고하세요.
2. 프로덕션 설정: DEBUG, 환경, 캐시 (P0)
APP_DEBUG=false / APP_ENV=production
캐시로 설정 고정
php artisan config:cache(+ route:cache view:cache)는 설정을 확실히 반영시키고 앱을 빠르게 합니다. 주의: config:cache 이후 config/ 밖의 env()는 null을 반환하므로, 앱에서는 config('...')로 값을 참조하세요.프로덕션에 진단 도구를 노출하지 않기
3. 인가: Broken Access Control (P1 — 최대 원인)
가장 흔한 프로덕션 사고는 "인증은 됐지만 인가가 없다"입니다. 로그인할 수 있다고 해서 그 동작이 허용되는 것은 아닙니다.
흔히 하는(위험)
- 인가 없음 — "로그인 = 조회/수정 가능"
- route-model 바인딩이 타인의 ID를 가져옴
Model::create($request->all())가 모든 필드를 수용is_admin같은 권한 필드를 사용자 입력에서 대입
올바른
- Policy / Gate +
authorize()/can미들웨어, 매번 소유자/권한으로 스코프 - 조회도 소유자 스코프(예:
where('user_id', $me)) $request->validated()(FormRequest)로 입력 제한$fillable선언으로 Mass Assignment 차단
IDOR이란 무엇인가를 참고하세요. 핵심은 모든 조회/수정/삭제 경로에 소유권 검사를 두는 것입니다.
4. 인젝션과 출력
Laravel의 Eloquent/쿼리 빌더는 값을 플레이스홀더로 바인딩하고, Blade는 기본적으로 출력을 이스케이프합니다. 규칙은 그 안전장치를 스스로 끄지 않는 것입니다.
- SQL:
whereRaw/DB::raw에 사용자 입력을 문자열 연결로 섞지 마세요. 원시 SQL이 필요할 때도 바인딩을 쓰세요(→ SQL 인젝션이란 무엇인가). - XSS: Blade
{{ }}는 이스케이프하고,{!! !!}는 원시 출력입니다. 사용자 입력을{!! !!}에 넘기지 마세요. HTML을 내보내야 한다면 새니타이즈 후에만(→ XSS란 무엇인가). - 검증: 사용 전에 FormRequest /
validate()로 타입/범위/허용값을 검증하세요.
5. 세션, CSRF, 쿠키 (P2)
- CSRF: web 미들웨어의 CSRF 보호를 전역으로 비활성화하지 마세요. 폼에는
@csrf를, SPA에는 적절한 토큰 처리를 쓰세요(→ CSRF란 무엇인가). - 쿠키/세션:
config/session.php에secure(HTTPS),http_only,same_site를 설정하세요. 로그인 시 세션을 재생성해 고정(fixation)을 막으세요(Laravel의 인증은 재생성합니다). - 무차별 대입: 로그인에
throttle/ 로그인 시도 제한을 적용하세요.
6. 파일 업로드와 공개 파일 (P2)
- mime 타입, 확장자, 크기를 검증하고, 클라이언트가 제공한 파일명을 신뢰하지 마세요.
public/밖에(예:storage/) 실행 권한 없이 저장하세요. 공개가 필요한 것만 통제된 경로로 제공하세요.- 전달에도 인가를 두어, 순차적인 직접 링크로 타인의 파일을 가져갈 수 없게 하세요.
7. HTTPS, 보안 헤더, 속도 제한 (P2)
- HTTPS 강제(
URL::forceScheme('https')등) + HSTS. 로드 밸런서 뒤에서는 스킴이 올바르게 감지되도록TrustProxies를 쓰세요. - 보안 헤더(X-Content-Type-Options 등; CSP는 자신의 에셋 구성에 맞춰 설계). 본인 사이트는 보안 헤더 체커로 점검하세요.
- 속도 제한: 로그인, API, 비밀번호 재설정에
throttle을 적용하세요.
8. 의존성과 버전 (P1)
- Composer 의존성 CVE를
composer audit나 osv-scanner로 모니터링하고, 실행 중인 버전으로 판단하며, 빠르게 패치하세요(→ 의존성 CVE 모니터링 · 취약점 대응 실무). - Laravel과 PHP를 지원되는 버전으로 유지하세요. EOL 버전을 방치하지 마세요(수정되지 않은 취약점이 쌓입니다).
점검: 당신의 Laravel은 실제로 하드닝됐는가?
만드는 것으로 끝이 아닙니다 — 점검해야 비로소 끝입니다. 다음은 본인 사이트/환경에 대한 방어적 자기 점검입니다.
시크릿을 URL로 가져올 수 없다
/.env와 /storage/logs/laravel.log에 접근해 404를 반환하는지 확인하세요(가져와지면 즉시 수정하고 키를 교체).프로덕션에 디버그 노출 없음
인가가 유지된다
쿠키/세션과 의존성
composer audit가 클린한지 확인하세요.본 사이트의 관점: 견고한 기본값이 있어도 인가와 의존성은 당신의 책임
Laravel은 좋은 기본값을 많이 갖췄지만, 누가·무엇을·해도 되는가라는 인가와 의존성을 최신으로 유지하는 일은 앱·운영 고유이므로 어떤 프레임워크도 자동으로 지켜줄 수 없습니다. 본 사이트가 반복해서 봐온 사고도 정교한 공격보다 설정/운영 패턴입니다: "인증은 됐는데 소유권 검사가 없다", "프로덕션에 디버그가 열려 있다", "시크릿이 노출됐다". 그래서 중점은 위 표를 위에서부터 처리하고 기본을 꾸준히 지키는 것입니다. 모든 조회/수정을 소유자로 스코프하고, 의존성을 CVE로 모니터링하세요.
다음으로 읽기
- 입구: 프레임워크별 보안 · Next.js 보안
- 시크릿: 공개 디렉터리에 시크릿을 두지 않기 · 사례: .env 전면 노출 사례
- 인가 / 실무: IDOR이란 무엇인가 · 취약점 대응 실무 · 의존성 CVE 모니터링
- 용어집: SQL 인젝션 · XSS · CSRF
출처와 확인 범위
아래 1차 자료는 위의 설정·영향 범위·대응을 뒷받침하며 링크는 2026년 10월 23일 확인했습니다. 자료의 버전·구성 조건을 확인하세요. 점검 우선순위와 교훈은 이 사이트의 정리이며 글 전체의 재검증이나 안전 보증이 아닙니다.