
DX Security — Hook Abuse 방어 v1.0.0 안내서
PHP 5.6+ · IIS / Apache / Nginx 완전 호환 코어 HookManager 수정 없음 — 래핑 방식으로 동작
목차
- Hook Abuse란 무엇인가
- DXCMS 코어 HookManager 분석
- PHP 환경의 현실적인 한계
- 이 플러그인의 역할
- 설치 방법
- 방어층 상세 설명
- 보안 로그 읽는 법
- 보안 강점 요약
- 개발자 API 가이드
1. Hook Abuse란 무엇인가
Plugin 또는 공격자가 Hook을 악용하여 인증·인가·보안 검증을 우회하거나 실행 흐름을 조작하는 공격입니다.
공격 시나리오:
① Security Hook 제거:
dx_remove_hook('dx_before_login', ...)
→ 로그인 브루트포스 Rate Limit 제거 → 무제한 로그인 시도
② Priority 조작:
dx_add_hook('dx_before_login', $evil, -999)
→ 보안 플러그인보다 먼저 실행 → 보안 검사 우회
③ Hook 재귀 공격:
Hook A 실행 → Hook B 호출 → Hook A 호출 → ...
→ 무한 재귀 → 스택 오버플로 → 서버 다운
④ Hook DoS:
하나의 요청에서 수천 개 Hook 실행 → 서버 자원 고갈
2. DXCMS 코어 HookManager 분석
코어 구현
class HookManager
{
private $hooks = array(); // Hook 배열
private $executed = array(); // 실행된 Hook 목록
public function add($name, $callback, $priority = 10)
{
// 권한 검사 없음 — 누구나 어떤 Hook이든 등록 가능
$this->hooks[$name][] = array('callback' => $callback, 'priority' => $priority);
usort($this->hooks[$name], ...); // Priority 오름차순 정렬
}
public function remove($name, $callback = null)
{
// 권한 검사 없음 — 누구나 어떤 Hook이든 제거 가능
unset($this->hooks[$name]);
}
}
코어 평가
| 항목 | 코어 | 평가 |
|---|---|---|
| Hook 추가/실행/필터 | 단순 배열 기반 | ✅ |
| Priority 정렬 | usort 오름차순 | ✅ |
| executed 추적 | $executed[] 배열 |
✅ |
| Hook 등록 권한 | 없음 | ❌ |
| Security Hook 보호 | 없음 | ❌ |
| Priority 범위 제한 | 없음 (음수 포함) | ❌ |
| 재귀 방어 | 없음 | ❌ |
| 실행 횟수 제한 | 없음 | ❌ |
| Hook 감사 로그 | 없음 | ❌ |
3. PHP 환경의 현실적인 한계
dx_add_hook / dx_remove_hook은 전역 함수입니다. PHP에서 전역 함수를 재정의할 수 없으므로 완전한 Hook 등록 권한 제어는 불가능합니다.
이 플러그인의 접근:
직접 차단 불가:
dx_remove_hook()를 가로챌 수 없음
대안:
① Protected Hook 상태 지속 모니터링
② Hook 실행 후 카운트 변화 탐지
③ Priority 이상값 Reflection으로 탐지
④ 감사 로그로 사후 분석 지원
4. 이 플러그인의 역할
코어 HookManager를 수정하지 않고 탐지·로그·경고 방식으로 Hook Abuse를 방어합니다.
5. 설치 방법
(DXCMS 루트)/
└── plugins/
└── dx-security-hook/
├── manifest.php
└── plugin.php
관리자 → 플러그인 → dx-security-hook → 활성화
6. 방어층 상세 설명
HK1. Hook 등록 감사
Hook 전체 상태를 주기적으로 기록합니다.
관리자 플러그인 페이지(/admin/plugins) 진입 시:
전체 Hook 수 기록
보호 Hook 상태 확인
→ HOOK_AUDIT 로그
HK2. Security Hook 보호 — 제거 탐지
보호 대상 Hook 목록을 관리하고 제거 시도를 탐지합니다.
보호 Hook 목록 (17개):
dx_extend_top dx_before_login
dx_after_login dx_before_register
dx_login_failed dx_before_post_write
dx_before_comment_write dx_before_upload
dx_before_og_fetch dx_before_password_reset
dx_before_email_verify dx_before_webhook
dx_auth_exception dx_authz_exception
dx_rate_limit_exceeded dx_before_csrf_check
dx_admin_top
탐지 방식:
첫 실행 시 보호 Hook 카운트 저장
이후 요청마다 카운트 비교
→ 감소 시 PROTECTED_HOOK_REMOVED 로그
HK3. Priority 범위 제한 + 이상 탐지
정책:
일반 Plugin: Priority 1~100
Security 플러그인: 1~20 (우선 실행)
탐지:
0 이하 Priority → PRIORITY_UNDERFLOW 로그 + 최솟값 조정
100 초과 Priority → PRIORITY_OVERFLOW 로그 + 최댓값 조정
999 이상 극단값 → EXTREME_PRIORITY 로그
보호 Hook에 0 이하 Priority → PRIORITY_ABUSE 로그
Reflection으로 내부 hooks 배열 스캔:
Security Hook에 비정상 낮은 Priority(0 이하) 탐지
→ SECURITY_HOOK_LOW_PRIORITY 로그
HK4. Hook 재귀 방어
재귀 깊이 제한: 5 (DX_HOOK_MAX_DEPTH)
간접 탐지:
executed 배열 길이 모니터링
→ 비정상 급증 시 HOOK_INVOCATION_LIMIT 로그
HK5. Hook DoS 방어
요청당 최대 Hook 실행 횟수: 500 (DX_HOOK_MAX_INVOCATIONS)
탐지:
HookManager::getExecuted() 길이 확인
→ 500 초과 시 HOOK_INVOCATION_LIMIT 로그
HK6. Hook 호출자 추적
debug_backtrace로 Hook을 등록한 Plugin을 추적합니다.
추적 결과:
plugin:{plugin_id} → 특정 Plugin에서 등록
core → Core에서 등록
Priority 위반 시 caller 정보 포함:
PRIORITY_ABUSE hook=dx_extend_top priority=-999 caller=plugin:evil-plugin
HK7. Hook 감사 로그
Hook 관련 모든 이벤트를 data/security.log에 기록합니다.
7. 보안 로그 읽는 법
이벤트 타입
| 타입 | 의미 |
|---|---|
HK:PROTECTED_HOOK_REMOVED |
보호 Hook 카운트 감소 탐지 |
HK:PROTECTED_HOOK_EMPTY |
보호 Hook에 콜백 없음 |
HK:PRIORITY_ABUSE |
보호 Hook에 비정상 Priority |
HK:PRIORITY_UNDERFLOW |
Priority 최솟값 미만 |
HK:PRIORITY_OVERFLOW |
Priority 최댓값 초과 |
HK:EXTREME_PRIORITY |
극단적 Priority 값 |
HK:SECURITY_HOOK_LOW_PRIORITY |
Security Hook에 낮은 Priority |
HK:HOOK_INVOCATION_LIMIT |
요청당 Hook 실행 횟수 초과 |
HK:HOOK_AUDIT |
Hook 전체 상태 감사 |
HK:PLUGIN_HOOK_STATE |
Plugin 활성화/비활성화 시 Hook 상태 |
로그 예시
# 보호 Hook 제거 탐지
[2026-09-03 09:00:01][HK:PROTECTED_HOOK_REMOVED][IP:45.33.x.x][...][UID:1][URI:/admin/plugins]
hook=dx_before_login expected=2 current=1
# Priority 악용 탐지
[2026-09-03 14:22:10][HK:PRIORITY_ABUSE][IP:121.131.x.x][...][UID:1][URI:-]
hook=dx_extend_top priority=-999 caller=plugin:evil-plugin
# Hook DoS 탐지
[2026-09-03 16:45:03][HK:HOOK_INVOCATION_LIMIT][IP:58.29.x.x][...][UID:0][URI:/board/free]
count=523 limit=500
# 관리자 페이지 Hook 감사
[2026-09-03 20:11:44][HK:HOOK_AUDIT][IP:121.131.x.x][...][UID:1][URI:/admin/plugins]
total_hooks=42 protected_count=17
8. 보안 강점 요약
| 위협 | 결과 | 방어 레이어 |
|---|---|---|
| Security Hook 제거 | 탐지 로그 | HK2 |
| Priority -999로 보안 우회 시도 | Priority 조정 + 로그 | HK3 |
| Hook 재귀 공격 | 간접 탐지 로그 | HK4 |
| Hook DoS | 횟수 제한 탐지 로그 | HK5 |
| Plugin 활성화/비활성화 시 Hook 변화 | 상태 기록 | HK7 |
| 극단적 Priority 값 | EXTREME_PRIORITY 로그 | HK3 |
| 정상 Hook 동작 | 영향 없음 | ✅ |
9. 개발자 API 가이드
자신의 Hook을 보호 목록에 등록
// Security 플러그인에서 자신의 핵심 Hook을 보호 목록에 추가
dx_hook_add_protected('dx_before_my_critical_action');
// 이후 이 Hook의 카운트가 줄어들면 PROTECTED_HOOK_REMOVED 로그
특정 Hook이 보호 대상인지 확인
if (dx_hook_is_protected('dx_before_login')) {
// 이 Hook은 보호 대상 — 제거 금지
}
Hook 실행 체인 확인
// 현재 요청에서 실행된 Hook 목록
$chain = dx_hook_get_chain();
// ['dx_extend_top', 'dx_before_login', ...]
Hook 감사 로그 직접 기록
dx_hook_log('MY_HOOK_SECURITY_EVENT',
'hook=dx_my_hook caller=my-plugin action=register');
DX Security — Hook Abuse 방어 v1.0.0 — DesignOneX https://designonex.com
라이선스
디자인원엑스 라이선스 참고
https://designonex.com/notice/view/1787577858493247