
DX Security — Authentication Bypass 방어 v1.0.0 안내서
PHP 5.6+ · IIS / Apache / Nginx 완전 호환 코어 수정 없음 — 훅으로만 동작
목차
- Authentication Bypass란 무엇인가
- DXCMS 코어의 현재 방어 수준
- 이 플러그인의 역할
- 설치 방법
- 방어층 상세 설명
- 보안 로그 읽는 법
- 보안 강점 요약
- 개발자 API 가이드
1. Authentication Bypass란 무엇인가
공격자가 정상적인 인증 절차를 우회하여 보호된 자원에 접근하거나, 허용된 것보다 높은 권한을 획득하는 공격입니다.
공격 예시:
로그인 없이 /admin/members/ 직접 URL 접근
정지된 계정이 세션을 유지하며 계속 사용
로그인 브루트포스 공격
일반 회원이 관리자 기능 접근
POST 파라미터에 is_admin=1 주입
2. DXCMS 코어의 현재 방어 수준
코어가 이미 잘 하는 것
| 항목 | 방어 방식 | 평가 |
|---|---|---|
| 관리자 URL 인증 | Dispatcher::isAdmin() → 로그인 리다이렉트 | ✅ |
| DX_CMS 상수 체크 | 모든 API 파일에 exit | ✅ |
| 세션 토큰 검증 | makeToken() + hash_equals | ✅ |
| CSRF 체크 | dx_csrf_check() | ✅ |
| Remember Me | hash_equals + DB 검증 | ✅ |
코어가 하지 않는 것
| 항목 | 위험도 |
|---|---|
| 로그인 브루트포스 Rate Limit | 높음 |
| 인증 실패 감사 로그 | 높음 |
| 세션 생성 이후 정지된 계정 재검증 | 중간 |
| 관리자 접근 감사 로그 | 중간 |
| HTTP Method 우회 탐지 | 중간 |
| Parameter Pollution 탐지 | 중간 |
| 인증 오류 시 Fail Closed | 높음 |
3. 이 플러그인의 역할
코어의 인증 로직을 수정하거나 교체하지 않습니다. 코어가 하지 않는 로깅, 모니터링, 추가 방어를 훅으로 보강합니다.
4. 설치 방법
(DXCMS 루트)/
└── plugins/
└── dx-security-authn/
├── manifest.php
└── plugin.php
관리자 → 플러그인 → dx-security-authn → 활성화
5. 방어층 상세 설명
AN1. 로그인 브루트포스 Rate Limit
같은 IP에서 반복 로그인 실패를 차단합니다.
정책:
600초(10분) 안에 10회 실패
→ Rate Limit 발동
→ HTTP 429 응답
→ AUTH:LOGIN_RATE_LIMITED 로그 기록
코어 Secure::rateLimit() 재사용 — 별도 저장소 불필요
AN2. 인증 감사 로그
모든 인증 관련 이벤트를 data/security.log에 기록합니다.
| 이벤트 타입 | 의미 |
|---|---|
AUTH:LOGIN_FAILED |
로그인 실패 |
AUTH:LOGIN_RATE_LIMITED |
Rate Limit 초과 |
AUTH:LOGIN_SUCCESS |
로그인 성공 |
AUTH:LOGOUT |
로그아웃 |
AUTH:ADMIN_ANONYMOUS_ACCESS |
비로그인 상태로 관리자 URL 접근 시도 |
AUTH:ADMIN_UNAUTHORIZED_ACCESS |
일반 회원이 관리자 URL 접근 시도 |
AUTH:ADMIN_ACCESS |
관리자 정상 접근 |
AUTH:ADMIN_ACTION |
관리자 작업 실행 |
AUTH:SUSPENDED_ACCESS_BLOCKED |
정지 계정 접근 차단 |
AUTH:WITHDRAWN_ACCESS_BLOCKED |
탈퇴 계정 접근 차단 |
AUTH:UNUSUAL_METHOD |
비정상 HTTP Method 탐지 |
AUTH:GET_STATE_CHANGE |
GET으로 상태 변경 시도 탐지 |
AUTH:PARAM_POLLUTION |
Parameter Pollution 탐지 |
AUTH:DANGEROUS_PARAM |
위험 파라미터 탐지 |
AUTH:JSON_DANGEROUS_PARAM |
JSON 위험 파라미터 탐지 |
AUTH:AUTH_EXCEPTION_FAIL_CLOSED |
인증 예외 — Fail Closed |
AUTH:ACCESS_DENIED_NOT_LOGGED_IN |
플러그인 엔드포인트 — 미로그인 |
AUTH:ACCESS_DENIED_NOT_ADMIN |
플러그인 엔드포인트 — 비관리자 |
AN3. 정지/탈퇴 계정 재검증
코어의 loadSession()은 세션 로드 시점에 1회만 계정 상태를 확인합니다. 세션 생성 이후에 계정이 정지되면 코어가 이를 감지하지 못합니다. 이 플러그인은 매 요청마다 계정 상태를 재확인합니다.
흐름:
요청
→ 로그인 여부 확인
→ Auth 세션의 user 정보 읽기 (추가 DB 쿼리 없음)
→ status/blocked/deleted_at 필드 확인
→ 정지 → 강제 로그아웃 + 403
→ 탈퇴 → 강제 로그아웃 + 403
→ 정상 → 계속
중요: DB를 직접 조회하지 않습니다. Auth 세션에 이미 로드된 user 정보를 읽으므로 추가 성능 부담이 없습니다.
AN4. 관리자 접근 감사 로그
코어 Dispatcher가 이미 미인증 관리자 접근을 차단하고 로그인으로 리다이렉트합니다. 이 플러그인은 그 위에 감사 로그를 추가합니다. 차단 로직을 수정하지 않습니다.
비로그인 → /admin/ 접근 → ADMIN_ANONYMOUS_ACCESS 로그
일반 회원 → /admin/ 접근 → ADMIN_UNAUTHORIZED_ACCESS 로그
관리자 → /admin/ 접근 → ADMIN_ACCESS 로그
AN5. HTTP Method 우회 탐지
비정상 HTTP Method로 상태 변경 작업 시도를 탐지합니다.
WAF: 탐지·로그만 수행 — 요청 차단 없음
탐지 패턴:
HEAD/OPTIONS/TRACE/TRACK → /admin/ 또는 /api/ 경로 → 로그
GET → /admin/*delete*, /admin/*remove* 등 → 로그
차단하지 않는 이유:
OPTIONS — CORS preflight (정상 브라우저 동작)
HEAD — 일부 모니터링 도구 (정상)
차단하면 정상 기능이 깨질 수 있음
코어가 이미 CSRF 토큰으로 상태 변경 작업을 보호함
AN6. Parameter Pollution 탐지
인증 상태를 바꾸려는 위험 파라미터 주입을 탐지합니다.
감시 대상 파라미터:
is_admin, role, level, admin, permission, auth
탐지:
Query String 중복: ?is_admin=0&is_admin=1
POST body 주입: is_admin=1
JSON body 주입: {"is_admin": true}
모두 탐지·로그만 수행
코어는 요청 파라미터가 아닌 DB 세션 데이터에서 권한을 읽으므로 이 파라미터들은 실제로 효과가 없습니다. 탐지 목적은 공격 시도 모니터링입니다.
AN7. Fail Closed
인증 예외 발생 시 허용이 아닌 거부로 처리합니다.
잘못된 방식 (Fail Open):
try {
$user = authenticate();
} catch (Exception $e) {
// 접근 허용 ← 위험
}
이 플러그인 (Fail Closed):
dx_auth_exception 훅 발동
→ 강제 로그아웃
→ HTTP 403
→ AUTH:AUTH_EXCEPTION_FAIL_CLOSED 로그
→ exit
6. 보안 로그 읽는 법
형식
[날짜 시각][AUTH:타입][IP:주소][UA:에이전트][UID:사용자ID][METHOD URI] 메시지
예시
# 로그인 실패
[2026-09-03 09:00:01][AUTH:LOGIN_FAILED][IP:45.33.x.x][...][UID:0][POST /api/login]
login_id=admin reason=WRONG_PASSWORD
# Rate Limit 초과
[2026-09-03 09:00:15][AUTH:LOGIN_RATE_LIMITED][IP:45.33.x.x][...][UID:0][POST /api/login]
login_id=admin
# 일반 회원이 관리자 페이지 접근 시도
[2026-09-03 14:22:10][AUTH:ADMIN_UNAUTHORIZED_ACCESS][IP:58.29.x.x][...][UID:42][GET /admin/members/]
user_id=42 uri=/admin/members/
# 정지 계정 차단
[2026-09-03 16:45:03][AUTH:SUSPENDED_ACCESS_BLOCKED][IP:121.131.x.x][...][UID:99][GET /board/free]
user_id=99
# Parameter Pollution 탐지
[2026-09-03 20:11:44][AUTH:PARAM_POLLUTION][IP:103.21.x.x][...][UID:0][POST /api/member]
param=is_admin count=2 uri=/api/member
7. 보안 강점 요약
| 공격 | 결과 | 방어 레이어 |
|---|---|---|
| 로그인 브루트포스 | 10회 실패 후 차단 | AN1 |
| 비로그인 관리자 URL 접근 | 코어 차단 + 로그 | 코어 + AN4 |
| 일반 회원 관리자 URL 접근 | 코어 차단 + 로그 | 코어 + AN4 |
| 세션 생성 후 계정 정지 | 강제 로그아웃 + 403 | AN3 |
| 탈퇴 계정 세션 접근 | 강제 로그아웃 + 403 | AN3 |
| is_admin=1 POST 주입 | 효과 없음 (코어 DB 기반) + 로그 | 코어 + AN6 |
| HEAD/OPTIONS on admin | 로그 기록 | AN5 |
| GET으로 삭제 엔드포인트 접근 | 로그 기록 | AN5 |
| 인증 예외 발생 | Fail Closed (403) | AN7 |
8. 개발자 API 가이드
플러그인 엔드포인트에서 로그인 확인
// 로그인 필요
if (!dx_authn_check_login(false, 'my_plugin')) {
http_response_code(401);
exit(json_encode(array('success' => false, 'message' => '로그인이 필요합니다.')));
}
// 관리자 필요
if (!dx_authn_check_login(true, 'my_plugin_admin')) {
http_response_code(403);
exit(json_encode(array('success' => false, 'message' => '관리자만 사용할 수 있습니다.')));
}
플러그인에서 인증 감사 로그 기록
// 인증 이벤트 직접 기록
dx_authn_log('MY_PLUGIN_AUTH_DENIED', 'resource=invoice user_id=' . $userId);
DX Security — Authentication Bypass 방어 v1.0.0 — DesignOneX https://designonex.com
라이선스
디자인원엑스 라이선스 참고
https://designonex.com/notice/view/1787577858493247