
CVE-2026-77818 - Yordam Kütüphane Otomasyon Sistemi - 세 개의 서로 다른 지점에서의 반사형 HTML 삽입, 폼 액션 탈취 및 자격 증명 도용 (CWE-79)
CVE-2026-77818 · CVSS 3.1 6.1 (중간) · 사이버 보안청 · 게시일 2026-09-04 · TR-26-1011
상태: 취약점은 v22.2 버전에서 해결되었습니다. 영향을 받는 설치본은 v22.2 이상으로 업그레이드해야 합니다.
Yordam 도서관 자동화 시스템은 터키의 대학, 공공 및 기관 도서관에서 널리 사용되는 상용 도서관 자동화 및 온라인 목록(OPAC) 소프트웨어입니다. 설치는 온프레미스 방식이며, 각 고객 기관에서 별도의 사본이 실행됩니다.
제품의 v22.1 버전에는 서로 독립적인 세 개의 개별 지점에서 반사형 HTML 주입이 존재합니다. 세 가지 모두 인증이 필요 없으며, 세 가지 모두 단일 링크로 트리거됩니다.
| # | 지점 | 근본 원인 |
|---|
| 1 | 로그인 페이지, devam 매개변수 | 이스케이프가 전혀 적용되지 않음 |
| 2 | 숨은 양식 필드 value 속성 | 이스케이프 후 두 번째 URL 디코딩 |
| 3 | 숨은 양식 필드 name 속성 | 이스케이프가 값에만 적용되고 이름에는 적용되지 않음 |
세 가지는 동일한 제품의 동일한 버전에 있고 동일한 취약점 클래스에 속하므로 단일 공지로 통합되어 단일 CVE ID로 게시되었습니다. 영향 측면에서 가장 심각한 것은 1번 지점입니다.
devam 매개변수가장 중요한 것입니다. 주입 지점은 인증 양식 자체의 HTML 태그에 직접 있습니다.
devam 매개변수는 사용자가 로그인 후 돌아갈 주소를 전달하며 hex로 인코딩되어 옵니다 — 2f796f7264616d2f 값은 /yordam/을 의미합니다. 애플리케이션은 이 값을 hex에서 디코딩하여 로그인 양식의 시작 태그에 기록합니다. 그 사이에 이스케이프 처리가 전혀 없습니다:
<form class='girisForm collapse show ikiAdimliGiris' method='post'
action='inc/islem.fm.inc.php'
data-url='<HEX 디코딩된 사용자 입력>'
autocomplete="off">
출력에서 <, > 및 따옴표 문자가 원시 상태로 나타납니다. Payload를 유지하는 유일한 것은 data-url 속성이 작은따옴표로 감싸져 있다는 것입니다. 입력 안에 작은따옴표를 넣으면 그것도 끝납니다: 속성이 닫히고, <form> 태그가 닫히며, 공격자가 작성한 HTML이 페이지의 인증 양식을 대체합니다.
양식 action이 탈취됩니다. 여기서 가짜 양식이 그려지는 것이 아닙니다 — 애플리케이션 자체의 양식을 비워 둔 채 닫고, 그 직후 동일한 CSS 클래스를 가진 새 <form>이 열립니다. 페이지의 사용자 이름, 비밀번호 및 인증 코드 필드는 모두 애플리케이션의 원본 HTML이므로 이 새 양식 안에 남아 있습니다. 사용자는 실제 양식을 보고, 실제 양식을 작성합니다; 입력한 정보는 공격자의 서버로 전송됩니다. 시각적으로 구별할 수 있는 차이는 전혀 없습니다.
중요한 점: 주입은 임의의 페이지가 아니라 사용자가 이미 비밀번호를 입력할 것으로 예상되는 페이지에서 발생합니다. 일반적인 반사형 주입에서는 공격자가 피해자를 설득해야 합니다; 여기서는 설득 작업을 애플리케이션 자체 인터페이스가 수행합니다.
value 속성 — 이중 URL 디코딩검색 페이지에서 GET 매개변수의 값이 숨은 양식 필드에 기록됩니다. 이 지점에서는 이스케이프가 적용됩니다 — 하지만 잘못된 순서로.
동일한 q 값이 단일 응답 내에서 세 가지 다른 컨텍스트에서 사용되며, 각각 다른 디코딩 깊이를 가집니다:
| 컨텍스트 | 디코딩 | 상태 |
|---|---|---|
<script> 블록의 JS 문자열 | 1회 | 안전 |
기본 검색 상자 <input value="…"> | 1회 | 안전 |
숨은 양식 필드 <input type='hidden' value="…"> | 2회 | 취약 |
처리 순서는 다음과 같습니다:
클라이언트 입력 : %2522
↓ $_GET 파싱
PHP 변수 : %22
↓ 입력 필터 → 악성 콘텐츠를 보지 못함, 따옴표 없음
↓ htmlspecialchars → 이스케이프할 문자가 없음, 변경 없음
↓ urldecode → %22 디코딩됨
페이지에 출력 : " ← 원시 따옴표, 속성에서 이탈
입력 필터와 이스케이프는 첫 번째 디코딩 계층에서 작동하는 반면, 출력은 두 번째 계층에서 공급됩니다. 동일한 payload의 단일 및 이중 인코딩 버전을 비교하면 차이가 명확하게 보입니다:
| 전송 | 응답 | 숨은 필드 출력 |
|---|---|---|
q=foo%22… (단일 인코딩) | 302 Found | value="foo"…" — 필터가 포착 |
q=foo%2522… (이중 인코딩) | 200 OK | value="foo"><…>" — 원시 HTML |
취약점은 q 매개변수에만 국한되지 않습니다. 숨은 필드를 생성하는 블록은 요청의 모든 GET 매개변수를 순회합니다; tip 및 alan에서도 별도로 검증되었습니다.
name 속성 — 매개변수 이름에서의 주입동일한 블록이 각 GET 매개변수에 대해 다음 구조를 생성합니다:
<input type='hidden' name="<매개변수 이름>" value="<매개변수 값>"/>
이스케이프는 value 쪽에만 적용됩니다. name 쪽에는 전혀 적용되지 않습니다. 이 지점에서는 이중 인코딩도 필요하지 않습니다 — 단일 인코딩으로 충분합니다, 왜냐하면 우회해야 할 이스케이프가 이미 없기 때문입니다.
조작된 매개변수 이름이 name 속성에 원시 상태로 직접 기록되며 속성에서 이탈할 수 있습니다. 매개변수 이름은 공격자의 통제 하에 있으므로 애플리케이션이 인식하는 매개변수일 필요도 없습니다.
이 세 지점 중 2번과 3번은 동일한 코드 블록에서 발생하며, 이 블록은 여섯 개의 서로 다른 양식에서 반복됩니다: dilForm, adetForm, siralaForm, tkForm, ekForm, tmForm. 즉, 단일 요청에서 주입이 여섯 번 발생합니다.
블록이 동적이라는 것은 두 요청의 출력을 비교하여 검증되었습니다:
요청 A: ?p=1&dil=0&alan=&tip=basit&gorunum=liste&q=…
출력 A: name="p" · name="alan" · name="tip" · name="gorunum" · name="q"
요청 B: ?p=2&dil=0&devam=…
출력 B: name="p" · name="devam"
생성된 필드는 고정된 목록이 아니라 요청의 매개변수에서 직접 파생됩니다. 따라서 name 및 value 속성 모두에 기록되는 콘텐츠는 공격자의 통제 하에 있습니다.
공격자에게 필요한 것은 피해자가 열어볼 링크 하나뿐입니다. 로그인할 필요도, 계정이 있을 필요도 없습니다.
action 대상이 공격자에게 전환됩니다. 검증됨.영향을 받는 플랫폼은 도서관 회원의 자격 증명과 개인 데이터를 보유하고 있으므로, 탈취된 계정을 통해 회원 기록에 접근할 수 있습니다.
애플리케이션은 CSP를 사용하며 script-src 및 object-src는 nonce 기반입니다; 즉, 기존의 스크립트 기반 XSS는 이 페이지에서 작동하지 않습니다. 언뜻 보기에 이는 발견 사항을 "단순한 콘텐츠 변조" 수준으로 낮추는 것처럼 보입니다.
정책 전체는 다음과 같습니다:
Content-Security-Policy: script-src 'nonce-...'; object-src 'nonce-...'; frame-ancestors 'self'
form-action이 없습니다. default-src도 없습니다 — 따라서 정의되지 않은 지시문에 대해 폴백할 기본값도 없습니다. 결과: 양식이 공격자의 서버로 POST를 보내는 것은 브라우저에 의해 어떤 방식으로도 차단되지 않습니다.
자격 증명을 탈취하기 위해 JavaScript를 실행할 필요가 없습니다. 일반 HTML이면 충분하며, CSP도 일반 HTML을 차단하지 않습니다.
1차
관련
CVE 레코드에서 1차 취약점은 CWE-79로 분류됩니다. 근본 원인 수준에서는 CWE-116이 더 설명적입니다: 세 지점 모두의 원인은 출력 이스케이프가 전혀 적용되지 않거나 잘못된 순서로 적용되기 때문입니다.
이 제품에서는 스크립트가 실행되지 않는다는 점을 언급해야 합니다 — 제품 자체가 보내는 nonce 기반 script-src 정책이 이를 허용하지 않으며 nonce 값은 cross-origin에서 읽을 수 없습니다. 실제로 발생하는 영향은 스크립트 실행이 아니라 HTML 주입 및 로그인 양식 탈취입니다. CAPEC-148(콘텐츠 스푸핑) 매핑도 이러한 이유로 이루어졌습니다.
CWE-174는 특히 2번 지점에 적용됩니다 — 이스케이프 후 동일한 데이터가 두 번째로 디코딩되는 경우.
중간 — CVSS 3.1 기본 점수 6.1 (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
공격자는 어떤 권한도 필요하지 않습니다; 피해자가 준비된 링크를 열어야 하므로 사용자 상호작용은 필수입니다. Scope는 주입된 콘텐츠가 브라우저의 보안 컨텍스트에서 처리되므로 Changed로 설정되었습니다.
세 지점 모두 동일한 점수에 해당합니다. 영향 측면에서 가장 심각한 것은 1번 지점입니다: 주입이 인증 양식 자체의 태그에서 직접 발생하므로 양식 action 대상의 탈취와 자격 증명 도용이 가능합니다.
Yordam 도서관 자동화 시스템
영향 : v22.1 및 이전
해결 : v22.2
검증은 v22.1에서 수행되었습니다. 취약점은 기관별 구성 오류가 아니라 제품의 공통 인터페이스 구성 요소에서 발생합니다; 동일한 버전 계열의 모든 설치본에 영향을 미칩니다. 이전 버전의 상태는 제조업체가 평가해야 합니다.
설치가 온프레미스이므로 제조업체가 수정 사항을 게시했더라도 업데이트를 적용하지 않은 설치본은 계속 영향을 받습니다.
| # | 엔드포인트 | 출력 지점 |
|---|---|---|
| 1 | GET /yordam/?p=2&dil=<n>&devam=<hex> | 로그인 양식의 data-url 속성 |
| 2 | GET /yordam/?p=1&…&<parametre>=<payload> | 숨은 양식 필드의 value 속성 |
| 3 | GET /yordam/?p=1&…&<payload>=1 | 숨은 양식 필드의 name 속성 |
2번과 3번 지점은 동일한 숨은 필드 생성 블록에서 발생합니다; 블록은 dilForm, adetForm, siralaForm, tkForm, ekForm 및 tmForm 양식에서 반복됩니다.
취약점은 제조업체에 의해 해결되었습니다. 애플리케이션을 v22.2 이상 버전으로 업그레이드해야 합니다.
| CVE ID | CVE-2026-77818 |
| 할당자 (CNA) | TR-CERT (USOM) — 터키 공화국 사이버 보안청 |
| 상태 | PUBLISHED |
| 예약 | 2026-08-21 |
| 게시 | 2026-09-04 |
| 보안 공지 | TR-26-1011 |
| CVE 레코드 제목 | Reflected HTML Injection via Form Hijacking in Yordam Informatics's Library Automation System |
| CAPEC | CAPEC-148 — 콘텐츠 스푸핑 |
제조업체: Yordam Bilgi Teknolojileri Danışmanlık Eğitim ve Elektronik Sistemler Sanayi ve Ticaret A.Ş.
Alkım Coşkun – Netlore Security
| 날짜 | 이벤트 |
|---|---|
| 2026-08-20 | 취약점 발견 및 검증 |
| 2026-08-21 | 사이버 보안청에 신고; CVE ID 예약 |
| 2026-09-04 | CVE-2026-77818 게시, 보안 공지 TR-26-1011 발표 |