01개요
MyBB는 PHP로 작성된 오픈소스 포럼 소프트웨어입니다. 관리자 컨트롤 패널(Admin Control Panel, ACP)의 설정(Settings) 모듈은 게시판 운영에 필요한 각종 옵션값을 mybb_settings 테이블에 저장하고, ACP의 "Change Settings" 페이지에서 이 값들을 입력폼으로 그려 보여줍니다.
각 설정은 optionscode라는 문자열 하나에 "타입"과 "추가 옵션"을 개행문자(\n)로 이어붙여 저장합니다(예: text, numeric, yesno 같은 타입). NVD 설명에 따르면 MyBB 1.2.0부터 php라는 특수 타입이 추가됐는데(1.2.0은 2006년 릴리스), 이 타입일 때는 개행 뒤에 오는 나머지 문자열 전체를 PHP 코드로 간주해 그대로 실행합니다 — 원래 플러그인이나 MyBB 자체의 내장 설정이 동적인 입력폼(예: 드롭다운 목록을 서버 상태에 따라 다르게 그리는 것)을 만들 때 쓰라고 넣어둔, ACP 화면을 통해 일반 관리자가 직접 만들 일은 없다고 전제된 내부용 기능입니다.
CVE-2022-24734는 이 전제가 실제로는 지켜지지 않았다는 사실에서 시작합니다 — ACP의 설정 추가/수정 폼은 "php" 타입을 사용자가 직접 만들지 못하게 막는 필터를 두고 있었지만, 이 필터가 화면을 그릴 때 쓰는 타입 판별 로직과 정확히 같은 기준으로 문자열을 정리(normalize)하지 않았습니다. 그 틈을 이용하면 "설정 관리" 권한을 가진 인증된 관리자가 임의 PHP 코드를 저장하고, ACP의 해당 설정 그룹 페이지를 열람하는 순간(자기 자신이 열람해도 됩니다) 그 코드가 서버에서 실행됩니다 — 즉 인증 후(post-auth) 원격코드실행이며, 비인증 공격자가 곧바로 서버를 장악할 수 있는 사전인증(pre-auth) 취약점은 아닙니다.
CVSS: 7.2 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H, NVD·GHSA 공통) · CWE-94(Improper Control of Generation of Code, 'Code Injection')
NVD 발행일 2022-03-09. 같은 취약점을 다루는 벤더 자체 GitHub Security Advisory GHSA-876v-gwgh-w57f, ZDI 자체 권고 ZDI-22-503이 함께 존재합니다(모두 같은 CVE-2022-24734를 가리키며 별도 변형 CVE로 쪼개지지 않았습니다). 최초 발견·신고자는 Cillian Collins(Trend Micro Zero Day Initiative 경유), 실제 패치 커밋 작성자는 MyBB 팀의 Tomasz Mlynski입니다 — 신고자와 패치 작성자가 다릅니다.
02영향받는 버전
| 대상 | 취약 버전 | 안전 버전 |
|---|---|---|
| MyBB(공식 배포) | 1.2.0 이상 1.8.29 이하 (NVD·GHSA 명시 범위 — php 설정 타입이 도입된 1.2.0부터 이 필터 로직이 그대로 이어져 왔습니다) | 1.8.30 이상 (패치 커밋 92012b9831b330714b9f9b4646a98784113489c1 포함) |
| 공식 배포 기준 저장소 HEAD (오늘 재확인) | 해당 없음 | 2026-09-19 기준 mybb/mybb 기본 브랜치(dev-1.9)에서 동일 검증 로직(ctype_alnum 전체검사)이 그대로 유지되고 있음을 직접 재확인 — 후속 회귀(regression) 없음 |
03배경 — 한 문자열에 "타입"과 "내용"을 이어붙인 설정 저장 방식
MyBB의 설정 관리 화면(관리자 메뉴 Configuration → Settings)에서 새 설정을 추가하거나 기존 설정을 수정하면, 화면에는 "Type"이라는 드롭다운(text·numeric·yesno·onoff 등)과 "Additional Options"라는 입력칸이 있습니다. 서버는 이 둘을 저장할 때 합쳐서 {type}\n{extra} 형태의 문자열 하나($options_code)로 만들어 mybb_settings.optionscode 컬럼에 넣습니다.
타입 목록에는 사용자가 드롭다운으로 고를 수 있는 값들 외에 php라는 값도 코드상 존재합니다. 이 값일 때 ACP가 "Change Settings" 페이지를 그릴 때는, 개행 뒤에 오는 부분(extra에 해당하는 부분)을 검증 없이 eval()로 실행해 그 결과를 입력폼의 HTML로 씁니다 — 즉 이 타입은 값 하나가 아니라 실행 가능한 PHP 코드 조각을 담습니다.
MyBB 개발진도 이 위험을 몰랐던 건 아닙니다 — 그래서 설정 추가/수정 화면의 서버 쪽 처리 코드(admin/modules/config/settings.php)에는 "사용자가 ACP 화면으로 직접 php 타입 설정을 만들지 못하게 막는" 필터가 이미 존재했습니다. 문제는 이 필터가 "화면을 그릴 때 타입을 판별하는 코드"와 완전히 같은 방식으로 문자열을 다듬지 않았다는 데 있습니다 — 다음 절에서 그 불일치를 짚습니다.
04취약점 발생 원인
이 취약점은 "php 타입은 ACP 화면으로 만들 수 없다"는 하나의 전제가, 서로 다른 세 지점에서 서로 다른 강도로 지켜지면서 성립합니다. 저장할 때 쓰는 필터(W1)와 화면을 그릴 때 쓰는 판별 로직(W2)이 다른 정규화 규칙을 쓴다는 것, 그리고 그 판별을 통과한 뒤에는 값 자체에 대한 검증이 애초에 없다는 것(W3) — 이 세 미흡점의 연계로 완성됩니다.
1"저장할 때는 개행만 지우고, 앞 3글자만 봤다"
설정을 추가(add)·수정(edit)할 때 서버는 type 값에서 개행문자만 제거한 뒤, 앞 3글자를 소문자로 바꿔 "php"와 같은지만 확인합니다 — 그 외의 공백·제어문자는 전혀 손대지 않습니다.
설정 추가 처리 코드는 사용자가 폼으로 보낸 type 값에 대해 딱 한 줄의 정리만 합니다 — str_replace("\n", "", ...)로 개행문자만 제거합니다. 그다음 substr($type, 0, 3)으로 앞 3글자를 잘라 소문자로 바꾼 값이 정확히 "php"인지만 검사하고, 맞으면 type을 빈 문자열로 만들어 이후 처리에서 걸러냅니다(빈 타입은 아래에서 error_invalid_type 오류로 막힙니다).
MyBB 오픈소스 실제 소스 — admin/modules/config/settings.php · 설정 추가(add) 처리 (패치 전, 태그 mybb_1829 = 패치 커밋 92012b9831b330714b9f9b4646a98784113489c1의 부모). 296~297행이 저장 시점 타입 필터입니다. 수정(edit) 처리 코드에도 499~500행에 동일한 로직이 그대로 반복됩니다.
이 검사는 "type이 정확히 개행 없는 "php..." 형태로 시작하는가"만 확인합니다. 만약 type 값의 맨 앞에 개행이 아닌 다른 공백류 문자(예: 스페이스, 탭, 캐리지리턴 등)가 하나 붙어 있다면, 앞 3글자는 "php"가 아니게 되어 이 검사를 그냥 통과해 버립니다 — 그런데 그 문자는 지워지지 않은 채 그대로 DB에 저장됩니다.
왜 이렇게 됐나이 필터는 "php로 시작하는 타입 문자열을 눈에 보이는 그대로 막겠다"는 목적에는 부합하지만, 그 문자열이 나중에 다른 코드에서 어떻게 다시 정리되는지는 고려하지 않았습니다. "개행만 지우면 충분하다"는 전제 자체가, 화면을 그리는 코드가 실제로 어떤 정리를 하는지와 맞춰보지 않은 채 세워졌습니다.
2"화면을 그릴 때는 trim()으로 앞뒤를 다 지운 뒤에야 비교했다"
ACP "Change Settings" 페이지가 설정을 나열하며 타입을 판별하는 코드는 trim()으로 앞뒤 공백·제어문자를 전부 지운 뒤에 "php"와 비교합니다 — W1이 통과시킨, 저장 시점엔 안 지워졌던 문자가 여기서는 지워집니다.
설정 목록을 그리는 코드는 각 설정의 optionscode를 개행 기준으로 나눈 뒤(explode("\n", ...)), 그 첫 조각을 trim()으로 다듬어 $type[0]에 넣습니다. PHP의 trim()은 스페이스·탭·개행·캐리지리턴·널바이트·수직탭까지 앞뒤에서 전부 제거합니다 — W1의 str_replace("\n", "", ...)보다 훨씬 넓은 범위입니다.
MyBB 오픈소스 실제 소스 — admin/modules/config/settings.php · "Change Settings" 페이지의 설정별 입력폼 생성 루프 (패치 전, 태그 mybb_1829). 1466~1467행이 화면 렌더링 시점의 타입 재판별입니다.
그 결과, W1에서 저장을 통과시킨 "php 앞에 공백류 문자가 붙은" 타입 값이 여기서는 그 문자가 지워져 정확히 "php"가 됩니다. 저장 시점엔 "php"가 아니라고 판정돼 필터를 빠져나갔던 값이, 화면을 그리는 시점엔 "php"로 재해석되는 것입니다 — 같은 문자열을 두 곳이 서로 다른 결론으로 판정합니다.
왜 이렇게 됐나trim()을 쓴 것 자체는 이상하지 않습니다 — 관리자가 드롭다운으로 "text"를 고른 값에 실수로 공백이 섞여 들어가는 것까지 다 걸러내려는, 오히려 관대한 설계입니다. 문제는 이 관대함이 저장 시점의 방어 로직과 같은 기준으로 맞춰지지 않았다는 것입니다 — 방어 코드와 소비 코드가 "정상적인 입력이 무엇인가"에 대해 서로 다른 정의를 쓰면, 그 사이 어딘가에 방어는 통과하지만 소비 쪽에서는 위험하게 해석되는 값이 반드시 남습니다.
3"php로 확정되면, 나머지는 검증 없이 그대로 실행했다"
타입이 "php"로 확정되는 순간, optionscode의 나머지 부분이 이스케이프나 화이트리스트 없이 eval()이 실행할 PHP 문자열 리터럴 안에 그대로 이어붙여집니다.
타입이 "php"로 판별되면, 코드는 optionscode에서 앞 3글자(원래 "php"가 차지하는 길이)를 잘라낸 나머지를 $setting_code = "..."; 형태의 PHP 코드 문자열을 조립해 eval()로 실행합니다. 이 조립 과정에 나머지 문자열에 대한 이스케이프 처리나 허용 문자 검사는 전혀 없습니다.
MyBB 오픈소스 실제 소스 — admin/modules/config/settings.php · 타입별 입력폼 생성 분기의 php 케이스 (패치 전, 태그 mybb_1829). 1540행이 검증 없는 eval() 실행 지점입니다.
즉 W1·W2가 막으려던 것은 "php 타입 자체를 사용자가 만들지 못하게"였을 뿐, php 타입으로 인식된 뒤의 extra 내용에 대한 방어선은 애초에 존재하지 않습니다 — "php 타입은 UI로 못 만든다"는 그 한 가지 전제가 이 함수 전체의 유일한 방어벽이었습니다. W1·W2 중 하나라도 그 전제를 지키지 못하면, 그 뒤에는 아무 검증도 남아 있지 않습니다.
왜 이렇게 됐나이 코드는 애초에 관리자 UI가 아니라 MyBB 자신의 내장 설정·플러그인이 만든, 신뢰된 문자열만 이 자리에 들어온다고 가정하고 짜였습니다. 그 가정이 지켜지는 한 이 코드는 위험하지 않습니다 — 문제는 그 가정을 지키는 책임이 오직 W1의 3글자 substr 검사 하나에만 있었다는 것이고, W1·W2의 불일치가 그 가정을 깨뜨렸습니다.
무게 중심은 W1과 W2 사이의 정규화 불일치입니다 — 저장 시점의 방어 로직(str_replace + substr 앞 3글자)과 소비 시점의 판별 로직(trim 후 전체 비교)이 "이 문자열에서 무엇을 제거해야 정상값인가"에 대해 서로 다른 기준을 썼습니다.
W3(php로 확정된 뒤 아무 검증 없이 eval)은 그 자체로는 새로운 결함이 아니라, 원래부터 "이 자리엔 신뢰된 값만 온다"는 전제 위에 세워진 내부용 기능입니다. W1·W2가 그 전제를 지켜주는 한 위험하지 않았고, 이번 패치도 W3(eval 자체)을 바꾸지 않고 W1을 강화해 전제를 되살리는 방식으로 고쳐졌습니다.
한 문장으로 묶으면 이렇습니다. 같은 문자열을 두고 '막는 쪽'과 '쓰는 쪽'이 서로 다른 정리 규칙을 쓰면, 막는 쪽은 통과시켰지만 쓰는 쪽은 위험하게 읽는 값이 반드시 존재합니다. 이 취약점에서 그 값은 "php" 앞에 공백류 문자 하나가 붙은 타입 문자열이었습니다.
05공격 과정
5.1 공격 과정 요약
- 공격자가 "Can manage settings?"(설정 관리) 권한을 가진 MyBB ACP 계정으로 로그인합니다 — 이 권한이 없으면 이 경로 자체가 열리지 않습니다.
- ACP의 설정 추가(또는 수정) 화면에 POST 요청을 보내면서, type 값에는 저장 시점 필터(W1)를 통과하지만 trim() 후에는 "php"가 되는 문자열을(개념적으로 "php" 앞에 공백류 문자 하나를 더한 형태), extra 값에는 실행시키고 싶은 PHP 코드를 담습니다.
- add()/edit() 처리 코드가 W1의 substr(0,3)=="php" 검사를 통과시켜, 오염된 type 문자열이 그대로 mybb_settings.optionscode에 저장됩니다.
- 공격자(또는 다른 관리자)가 ACP "Change Settings" 페이지에서 이 설정이 속한 그룹을 엽니다 — 설정을 저장한 사람과 화면을 여는 사람이 같은 세션일 필요는 없습니다.
- 설정 목록 렌더링 코드가 optionscode를 개행으로 나누고 trim()을 적용해(W2) 타입을 "php"로 재확정합니다.
- 타입이 "php"로 확정되면 optionscode의 나머지(extra) 부분이 이스케이프 없이 eval() 문자열에 그대로 삽입됩니다(W3) — extra에 담긴 PHP 코드가 그대로 실행됩니다.
- 이 시점에서 웹서버 프로세스(전형적으로 www-data) 권한으로 임의 PHP 코드가 실행됩니다 — 파일 시스템 접근, 다른 설정·DB 자격증명 열람, 웹셸 설치 등으로 이어질 수 있습니다.
5.2 상세 공격 과정
개념적으로 설명하면, 공격자는 type 필드에 "php"라는 세 글자 앞에 개행이 아닌 공백류·제어문자 하나를 붙여 보냅니다(예를 들어 스페이스 — 정확히 어떤 바이트가 되는지는 PHP trim()이 제거하는 문자 집합 안에서 여러 선택지가 있습니다). W1의 검사는 substr(0,3)만 보므로 이 값을 "php"로 인식하지 못해 통과시키지만, 그 문자는 지워지지 않은 채 DB에 그대로 들어갑니다.
extra 필드에는 실행시키려는 PHP 코드를 담습니다. 다만 이 코드가 그대로 실행되려면, 그 값이 eval("$setting_code = \"" . $extra . "\";")라는 이중따옴표로 감싼 PHP 문자열 리터럴 안에 삽입된다는 점을 고려해야 합니다 — extra를 곧바로 실행 가능한 PHP 코드로 만들려면, 먼저 이 문자열을 조기에 끝내고 이후 남는 \"; 꼬리를 주석 등으로 무력화하는, PHP의 eval-문자열 삽입에서 널리 알려진 일반적인 탈출 패턴이 필요합니다. 분석 — 저희는 이 탈출 패턴의 원리를 실제 eval() 코드를 직접 읽고 재구성했으며, 특정 바이트 시퀀스나 연구자의 실제 PoC 문자열을 인용하지 않습니다. 실행 가능한 값을 이 글에 싣지 않습니다(무해화).
설정이 DB에 저장된 뒤에는, ACP "Change Settings" 화면에서 그 설정이 속한 그룹을 여는 것만으로 코드가 실행됩니다 — 별도의 "저장" 버튼을 누를 필요 없이 그 그룹 페이지를 GET으로 열람하는 순간 렌더링 루프가 돌면서 eval()이 실행됩니다. 공격자 자신이 그 화면을 열어도 되므로, 실질적으로 "설정을 만드는 요청"과 "코드를 실행시키는 요청" 두 번의 HTTP 요청으로 끝나는 흐름입니다.
5.3 미흡점 ↔ 공격 흐름 매핑
| 미흡점(§4) | 발화 지점(§5.2) | 여는 프리미티브 | → 다음으로 잇는 것 |
|---|---|---|---|
| W1 — 저장시점 필터(개행제거+substr 앞3글자) | 설정 추가/수정 요청 처리(§8.2 1~2문단) | 저장시점 필터를 통과한, 공백류 문자가 섞인 type 문자열 | DB에 오염된 optionscode 그대로 저장(③) |
| W2 — 소비시점 trim() 후 재비교 | Change Settings 페이지 렌더링 루프(§8.2 3문단) | trim으로 정규화돼 "php" 타입으로 재확정 | php 분기 진입, eval 직전 문자열 조립 |
| W3 — php 확정 후 검증 없는 eval | eval() 문자열 조립·실행(§8.2 2~3문단) | 이스케이프 없이 삽입된 extra 내용이 PHP로 실행 | 웹서버 프로세스 권한 임의 코드 실행(최종 임팩트) |
06취약점 패치
왜§취약점 발생 원인의 W1 — 저장 시점 필터가 개행만 지우고 앞 3글자만 보던 자리 — 를 정확히 겨냥한 수정입니다. 커밋 제목 그대로 "ACP Settings management RCE"를 고치는 단일 목적의 변경입니다.
어떻게새 검증 계층을 추가한 게 아니라 필터 로직 자체를 교체했습니다. $mybb->get_input('type')으로 MyBB 표준 입력 헬퍼를 쓰고, ctype_alnum()으로 문자열 전체가 영숫자로만 이루어졌는지 확인해 하나라도 아니면(공백·제어문자·개행 등 무엇이든) 즉시 무효 처리합니다. 그다음에야 strtolower($type) == "php"로 문자열 전체가 정확히 "php"인지 비교합니다(기존의 앞 3글자만 보던 substr 비교가 아닙니다). ctype_alnum이 trim()이 지울 수 있는 모든 문자를 이미 걸러내므로, W2(소비 시점 trim)와 다시 어긋날 여지 자체가 사라집니다.
비고패치는 8줄이 안 되는 아주 작은 변경(각 처리 코드당 2줄 교체, 총 4줄)입니다 — 새 방어선을 세운 게 아니라 저장 시점 필터를 소비 시점 판별 로직과 같은 엄격도로 맞춘 것입니다. W3(eval 자체)은 이번 패치로 바뀌지 않았습니다 — "php 타입은 ACP UI로 만들 수 없다"는 원래 전제를 다시 확실히 지키는 방식으로 고쳤을 뿐, eval을 없애거나 안전하게 만들지는 않았습니다.
07대응방안
근본 해결은 MyBB 1.8.30 이상으로 업그레이드하는 것입니다(패치 커밋 92012b9831b330714b9f9b4646a98784113489c1 포함). 오래된 1.2.x~1.6.x 계열을 유지 중이라면 해당 브랜치용 공식 패치가 없으므로 1.8.30 이상 라인으로 마이그레이션을 검토해야 합니다.
- 즉시 업그레이드가 어렵다면, ACP "설정 관리(Can manage settings?)" 권한을 가진 관리자 계정 수를 최소화하고, 해당 권한을 가진 계정에는 반드시 강한 비밀번호와 2단계 인증(가능하다면 리버스 프록시 단에서의 추가 인증)을 적용해 애초에 이 경로에 도달할 수 있는 계정 자체를 줄이는 것이 가장 실질적인 차선입니다 — 이 취약점은 관리자 권한 탈취(피싱·자격증명 재사용·세션 하이재킹)와 결합해야 완성되는 사슬이기 때문입니다.
- 웹서버 설정에서
admin/modules/config/settings.php로의 접근을 별도 네트워크(사내망·VPN)로만 허용하거나, 웹서버 실행 계정의 쓰기 권한을 최소화해 eval() 실행 이후의 파일 시스템 쓰기(웹셸 설치 등) 확산을 제한하는 것도 보조적인 차단선이 됩니다. - 업그레이드 전까지 ACP 감사 로그(설정 추가/수정 이벤트)를 별도로 백업·모니터링해, 패치 적용 후에도 사고 발생 여부를 사후 확인할 수 있게 해둡니다.
- 탐지 관점. 짧은 시간 안에 ACP 설정 추가/수정 요청(module=config-settings&action=add 또는 edit) 직후 같은 설정 그룹의 Change Settings 페이지(action=change)를 곧바로 재방문하는 관리자 계정의 행위 패턴을 이상 신호로 봅니다. 웹 애플리케이션 방화벽(WAF)이나 리버스 프록시 로그에서 설정 추가/수정 요청 본문에 개행이 아닌 공백류·제어문자로 시작하면서 뒤에 "php"가 이어지는 type 파라미터, 또는 PHP 코드 조각으로 보이는 extra 파라미터가 있는지 확인하는 것도 (예방이 아닌 사후) 탐지 관점에서 유효합니다.
08왜 이게 반복되는가
이 취약점이 보여주는 패턴은 단순합니다 — 같은 값을 두고 '막는 코드'와 '쓰는 코드'가 서로 다른 정규화 규칙을 쓰면, 그 둘이 합의하지 못하는 값이 반드시 존재합니다. 이건 저희가 다른 CVE에서 반복적으로 본 것과 같은 계열입니다 — 리눅스 커널 nf_tables의 더블프리(CVE-2024-1086)에서는 판정값 하나에 '무엇을 할지'와 '부가정보'를 겹쳐 담는 인코딩에서, 그중 절반의 검증을 빠뜨린 코드와 그 절반을 신뢰하는 코드가 서로 다른 계층에 있었습니다. 여기서는 '저장 시점의 방어'와 '소비 시점의 판별'이 서로 다른 정규화 함수를 쓴다는 훨씬 단순한 형태로 같은 구조가 나타났습니다 — 방어 코드를 짤 때 "이 값이 나중에 정확히 어떻게 다시 읽히는가"까지 맞춰보지 않으면, 방어 자체는 논리적으로 멀쩡해 보여도 구멍이 남습니다.
패치완전성 관점에서 이 사건은 깔끔한 사례입니다 — 새 방어선을 추가하는 대신, 저장 시점 필터를 소비 시점 판별과 같은 엄격도(ctype_alnum 전체검사)로 맞춰 두 코드의 '정상값' 정의를 일치시켰습니다. 다만 W3(php 타입이 확정되면 검증 없이 eval)이라는 설계 자체는 그대로 남아 있다는 점도 정직하게 짚어야 합니다 — 이번 패치는 '그 위험한 기능에 일반 관리자 UI로는 도달할 수 없다'는 전제를 다시 세운 것이지, 그 기능 자체를 없애지는 않았습니다. 신뢰 전제 하나에 기대는 방어벽은, 그 전제로 가는 경로가 하나 더 생기는 순간 다시 흔들릴 수 있습니다.
이 한 틈은 고쳐졌지만, '막는 쪽과 쓰는 쪽이 같은 문자열을 다르게 정리한다'는 질문은 검증 로직을 여러 계층에 나눠 짜는 모든 코드베이스에서 또 나옵니다 — 그래서 저희는 이 커밋 하나가 아니라 이 질문을 남깁니다.
09결론
MyBB ACP 설정 관리 기능에서, 설정을 저장할 때 쓰는 타입 필터(개행 제거 + 앞 3글자 비교)와 화면을 그릴 때 쓰는 타입 판별(trim 후 전체 비교)이 서로 다른 정규화 규칙을 써서, 저장 시점엔 통과하지만 소비 시점엔 "php" 타입으로 재해석되는 값이 존재했습니다. 이 값으로 확정되면 설정값의 나머지가 이스케이프 없이 eval()에 그대로 실행됩니다. CVSS 7.2, CWE-94이며, "설정 관리" 권한을 가진 인증된 관리자만 트리거할 수 있는 post-auth RCE입니다. MyBB 1.8.30(커밋 92012b98)이 저장 시점 필터를 ctype_alnum 전체검사로 교체해 이 불일치를 없앴습니다 — 저희가 오늘 재확인한 결과 이 수정은 이후에도 유지되고 있습니다.
이 CVE의 표준판(요약본)은 아직 별도로 작성되지 않았습니다.
참고 자료
이 글의 코드 인용(admin/modules/config/settings.php의 296~304행·499~507행·1463~1470행·1533~1541행)은 mybb/mybb 저장소의 태그 mybb_1829(커밋 89ba6fd39fca4ede328f69deca9aba7b57f2c5d1)를 raw.githubusercontent.com에서 직접 받아 대조했습니다. 이 태그는 GitHub API로 확인한 결과 패치 커밋 92012b9831b330714b9f9b4646a98784113489c1의 부모 커밋과 정확히 일치합니다(즉 "패치 전" 상태 그 자체) — 우연히 비슷한 버전이 아니라 패치가 적용되기 직전의 코드와 바이트 단위로 같습니다. 패치 diff는 GitHub의 .patch 원문을 그대로 받아 실었고, 패치가 실제로 유지되고 있는지는 mybb/mybb 기본 브랜치(dev-1.9)의 오늘(2026-09-19) 시점 HEAD를 다시 받아 재확인했습니다. CVE 메타데이터(설명·CVSS 3.1 벡터·CWE·참고링크)는 NVD 공식 REST API(services.nvd.nist.gov)에서 직접 받은 값이며, 블로그나 2차 요약이 아니라 1차출처입니다. 다만 이 취약점을 최초 발견·신고한 연구자(Cillian Collins, Trend Micro Zero Day Initiative 경유)의 상세 기고문·PoC 원문은 게재처(Packet Storm)가 조회 시점에 접근을 막아 저희가 직접 대조하지 못했습니다 — 그래서 §공격 과정의 "이중따옴표 문자열을 조기 종료해 코드를 주입하는" 부분은 저희가 실제 eval() 코드를 직접 읽고 재구성한 일반적인 PHP eval-문자열 탈출 원리에 대한 저희 분석이지, 연구자의 실제 PoC 문자열을 인용한 것이 아닙니다(그 부분은 본문에 '분석'으로 표기). 저희는 이 취약점을 실제 MyBB 인스턴스에 설치해 랩 재현하지는 않았습니다(meta.reproduced=false) — 코드 대조만으로 결론 내린 부분과 실행 검증이 필요한 부분을 본문에서 구분합니다.
- NVD — CVE-2022-24734 상세 · CVSS 3.1 벡터·CWE-94·공식 설명, 이 글의 1차출처(NVD REST API로 직접 조회)
- MyBB 공식 GitHub Security Advisory GHSA-876v-gwgh-w57f · 벤더 자체 권고, 이 글이 재구성한 원 분석
- MyBB 오픈소스 저장소 — 패치 커밋 92012b98 · 실제 patch diff(직접 대조)
- MyBB 오픈소스 저장소 — 태그 mybb_1829 · 패치 커밋의 부모(패치 전 상태), 이 글의 코드 인용 출처
- Zero Day Initiative — ZDI-22-503 · 최초 신고자(Cillian Collins) 크레딧·공개 타임라인 근거
- MyBB 공식 블로그 — "MyBB 1.8.30 Released — Security Release" · 벤더 발표, 패치 버전 확인 근거
- infiltr8 Lab, 「한 정수 안에 두 가지 의미를 겹쳐 담은 대가」(Linux nf_tables 더블프리, CVE-2024-1086) — '막는 코드와 쓰는 코드의 정규화 불일치'라는 같은 계열 논평 연결