Enterprise 에디션
콘텐츠 무해화 및 재구성 — 심층 참조
한눈에 보기
섹션 제목: “한눈에 보기”이 페이지는 NextPDF\Enterprise\Security\Cdr 모듈의 심층 레퍼런스입니다. 이 모듈은 신뢰할 수 없는 PDF를 무해화하고 그 안전한 객체들로부터 깨끗한 파일을 재구성합니다. 파이프라인은 파싱, 승인 제어, 위협 탐지, 필터링, 참조 스크러빙, 재구성입니다. 출력은 입력의 보안 투영이며, 결코 증거용 사본이 아닙니다. 워크플로 지침은 먼저 CDR 기능 페이지를 읽으십시오.
제공 및 라이선스
섹션 제목: “제공 및 라이선스”이 기능은 NextPDF Enterprise (nextpdf/enterprise)에 포함되어 제공되며 Enterprise 티어 라이선스 엔벨로프로 활성화됩니다. 해당 자격이 없는 배포에서는 이 기능의 클래스가 로드되지 않습니다. 에디션을 비교하고 라이선스를 받으십시오.
공개 API 표면
섹션 제목: “공개 API 표면”| 심볼 | 매개변수 | 기본 동작 | 반환 | 예외 또는 실패 조건 | 비고 |
|---|---|---|---|---|---|
CdrEngine::__construct | 없음 | 내부 detector와 rebuilder를 구성 | CdrEngine | 선언된 것 없음 | 주입 가능한 협력자 없음 |
CdrEngine::sanitize | string $pdfData, ?CdrPolicy $policy = null | CdrPolicy::standard() 하에 전체 파이프라인을 실행 | CdrResult | 적대적 입력에도 예외를 던지지 않음; 파싱 및 승인 실패는 거부된 결과를 반환 | 결과는 거부를 무해화와 구별하여 보고함 |
CdrPolicy::__construct | 선택적 명명 매개변수 7개, 펜스 참조 | 빈 제거 집합; allowUriActions false; flattenIncrementalUpdates true; 한도는 객체 100000개, 디코딩 256 MiB, 페이지 10000개, 팽창률 1000.0 | CdrPolicy | 선언된 것 없음 | final readonly; 빈 removeThreatTypes 목록은 아무것도 탐지하지 않음 |
CdrPolicy::standard | 없음 | 레거시 위협 집합; URI 액션 제거; 기본 한도 | self | 선언된 것 없음 | 손실을 일으키는 7개의 Strip* 케이스를 제외함 |
CdrPolicy::paranoid | 없음 | 더 엄격한 한도의 레거시 위협 집합: 객체 50000개, 128 MiB, 페이지 5000개, 팽창률 100.0 | self | 선언된 것 없음 | 손실을 일으키는 7개의 Strip* 케이스를 제외함 |
CdrPolicy::permissive | 없음 | JavaScript, LaunchAction, NamedJavaScript, SubmitForm, ImportData만 제거; URI 액션은 보존 | self | 선언된 것 없음 | 신뢰할 수 있는 소스용 |
CdrPolicy::allThreatTypes | 없음 | 손실을 일으키는 Strip* 케이스를 포함해 모든 ThreatType 케이스를 반환 | list<ThreatType> | 선언된 것 없음 | 명시적 최대 스트립 옵트인 |
CdrPolicy::legacyThreatTypes | 없음 | 7개의 Strip* 케이스를 제외한 모든 케이스를 반환 | list<ThreatType> | 선언된 것 없음 | standard()와 paranoid()의 기본 제거 집합 |
CdrPolicy::shouldRemove | ThreatType $type | removeThreatTypes에 대한 멤버십 테스트 | bool | 선언된 것 없음 | allowUriActions가 true일 때 UriAction에 대해 false를 반환 |
ThreatDetector::detect | PdfReader $reader, CdrPolicy $policy | 정책의 위협 유형에 대해 모든 객체와 트레일러 카탈로그를 스캔 | list<DetectedThreat> | 예외를 던지지 않음; 파싱 불가능한 객체는 UnparseableObject 위협이 됨 | 카탈로그 스캔은 /Names/JavaScript 트리를 포함함 |
CdrRebuilder::rebuild | PdfReader $reader, list<int> $safeObjNums, list<int> $removedObjNums, CdrPolicy $policy | 안전한 객체들을 단일 리비전 %PDF-2.0 파일로 직렬화 | string | 선언된 것 없음; 재읽기 또는 /Length 검증에 실패한 객체는 건너뜀 | $policy는 향후 직렬화 조정을 위해 예약됨 |
DetectedThreat::__construct | ThreatType $type, int $objectNumber, string $description, string $location = '' | 불변 발견 값 객체 | DetectedThreat | 선언된 것 없음 | 네 개의 프로퍼티 모두 public readonly |
ThreatType | 문자열 백드 열거형 | 20개 케이스: 레거시 13개와 옵트인 Strip* 케이스 7개 | 해당 없음 | 해당 없음 | 아래 케이스 목록 참조 |
진입점 시그니처
섹션 제목: “진입점 시그니처”final class CdrEngine{ public function __construct()
public function sanitize(string $pdfData, ?CdrPolicy $policy = null): CdrResult}final readonly class CdrPolicy{ public function __construct( public array $removeThreatTypes = [], public bool $allowUriActions = false, public bool $flattenIncrementalUpdates = true, public int $maxObjects = 100_000, public int $maxDecodedStreamBytes = 268_435_456, public int $maxPageCount = 10_000, public float $maxInflationRatio = 1000.0, )
public static function standard(): self
public static function paranoid(): self
public static function permissive(): self
public static function allThreatTypes(): array
public static function legacyThreatTypes(): array
public function shouldRemove(ThreatType $type): bool}final class ThreatDetector{ public function detect(PdfReader $reader, CdrPolicy $policy): array}final class CdrRebuilder{ public function rebuild(PdfReader $reader, array $safeObjNums, array $removedObjNums, CdrPolicy $policy): string}final readonly class DetectedThreat{ public function __construct( public ThreatType $type, public int $objectNumber, public string $description, public string $location = '', )}enum ThreatType: stringThreatType 케이스 목록
섹션 제목: “ThreatType 케이스 목록”레거시 케이스 13개가 기본 제거 집합을 이룹니다. Strip* 케이스는 설계상 손실을 일으키며 기본 정책에는 결코 들어가지 않습니다.
| 케이스 | 백킹 값 | 탐지 표면 |
|---|---|---|
ThreatType::JavaScript | javascript | 임의의 객체상 /JS 키, 또는 /S /JavaScript 액션 |
ThreatType::AdditionalActions | additional-actions | 임의의 객체상 /AA 딕셔너리 |
ThreatType::OpenAction | open-action | 임의의 객체상 /OpenAction 키 |
ThreatType::LaunchAction | launch-action | /S /Launch 액션 |
ThreatType::RemoteGoTo | remote-goto | /S /GoToR 또는 /S /GoToE 액션 |
ThreatType::SubmitForm | submit-form | /S /SubmitForm 액션 |
ThreatType::ImportData | import-data | /S /ImportData 액션 |
ThreatType::EmbeddedFiles | embedded-files | /EmbeddedFiles 이름 트리 또는 /EF 딕셔너리 |
ThreatType::RichMedia | rich-media | /Subtype /RichMedia |
ThreatType::NamedJavaScript | named-javascript | 카탈로그 /Names/JavaScript 이름 트리 |
ThreatType::UriAction | uri-action | /S /URI 액션; allowUriActions가 true일 때 억제됨 |
ThreatType::Xfa | xfa | /XFA 키 |
ThreatType::UnparseableObject | unparseable-object | 파싱에 실패하는 임의의 객체 또는 카탈로그 |
ThreatType::StripJavaScript | strip-javascript | 옵트인 상위 집합: /JS 키, /S /JavaScript, 또는 /Subtype /JavaScript |
ThreatType::StripEmbeddedFiles | strip-embedded-files | 옵트인: /Type /EmbeddedFile, /Type /Filespec, /EmbeddedFiles, 또는 /EF |
ThreatType::StripFormFields | strip-form-fields | 옵트인: /Subtype /Widget, /FT 키, 또는 /AcroForm 키 |
ThreatType::StripAnnotationsRich | strip-annotations-rich | 옵트인 서브타입: Movie, Sound, FileAttachment, 3D, RichMedia, Screen |
ThreatType::StripOcgNonDefault | strip-ocg-non-default | 옵트인: /Usage 또는 /Visibility 키를 가진 /Type /OCG |
ThreatType::StripDigitalSignaturesAtRebuild | strip-digital-signatures-at-rebuild | 옵트인: /Type /Sig, /FT /Sig, /DSS, /VRI, 또는 /ByteRange |
ThreatType::Strip3dAndRichMedia | strip-3d-and-rich-media | 옵트인 서브타입: 3D, U3D, PRC, RMF, RichMedia, Sound, Movie |
동작 계약
섹션 제목: “동작 계약”CdrEngine::sanitize는 순서가 정해진 6개 단계를 실행하며 적대적 입력에 대해 결코 예외를 던지지 않습니다.
- 파싱. 파싱 실패는
admitted가 false이고 파싱 오류 거부 사유를 담은 결과를 반환합니다. 그 경우 무해화된 출력은 비어 있습니다. - 승인 제어. 객체 수, 집계된 디코딩 스트림 바이트, 스트림별 팽창률, 페이지 수가 정책 한도에 대해 검사됩니다. 한도를 초과하는 문서는 무해화되지 않고 거부됩니다. 거부와 무해화는 구별되어 보고됩니다.
- 탐지.
ThreatDetector::detect는 정책의 위협 유형에 대해 모든 객체와 트레일러 카탈로그를 스캔합니다. 파싱 불가능한 객체는 건너뛰지 않고ThreatType::UnparseableObject발견으로 기록됩니다. - 필터링. 발견을 담은 객체는 제거 대기열에 들어갑니다. 문서 카탈로그는 결코 전체 객체로 제거되지 않습니다. 카탈로그 수준의 발견(
OpenAction,AdditionalActions,NamedJavaScript)은 대신 키 스트리핑으로 교정됩니다. - 참조 스크러빙. 제거된 객체에 대한 모든 간접 참조는 직렬화 중에
null로 대체됩니다. - 재구성.
CdrRebuilder::rebuild는 번호가 다시 매겨진 객체, 고전적 교차 참조 테이블, 그리고 새로운 트레일러를 갖춘 단일 리비전%PDF-2.0파일을 생성합니다. 안전한 스트림 바이트는 바이트 단위로 동일하게 복사됩니다. 재구성된 카탈로그는/OpenAction,/AA,/Names를 제거하며;/AA는 모든 객체에서 제거됩니다.
반환된 CdrResult는 재구성된 바이트, 제거된 위협 목록, 두 바이트 크기, 승인 플래그, 그리고 거부 사유를 노출합니다. 소스에 해석 가능한 /Root가 있었는데 재구성된 출력이 그것을 잃었다면, 엔진은 구조적으로 손상된 파일을 반환하는 대신 출력을 거부합니다. 이것은 페일 클로즈드 보장입니다: admitted가 true이면 출력이 여전히 문서 카탈로그 참조를 담고 있음을 의미합니다.
증분 업데이트는 결코 살아남지 못합니다: 재구성은 모든 정책 하에서 정확히 하나의 리비전을 직렬화하므로, 섀도 스타일의 늦은 리비전은 구성상 평탄화됩니다. 원본 디지털 서명은 바이트 범위가 더 이상 출력과 일치하지 않으므로 재구성을 거쳐 유효하게 유지될 수 없습니다.
아키텍처 레드라인. CDR은 보안 투영 계층이지 보존 계층이 아닙니다. 출력은 법적 증거 보존, 원본과의 해시 비교, 또는 아카이브 사본에 사용되어서는 안 됩니다.
엣지 케이스 및 실패 모드
섹션 제목: “엣지 케이스 및 실패 모드”null정책은CdrPolicy::standard()로 해석됩니다. 기본의 빈removeThreatTypes로 구성된 정책은 아무것도 탐지하거나 제거하지 않습니다.allowUriActions를true로 설정하면 케이스가removeThreatTypes에 존재하더라도UriAction제거를 억제합니다.flattenIncrementalUpdates는 이 릴리스에서 선언적입니다: 재구성은 플래그를false로 설정하는permissive()를 포함해 모든 정책 하에서 단일 리비전을 생성합니다.- 팽창률 검사는 원시 스트림 길이 0을 1로 취급하므로, 무에서 팽창하는 스트림도 여전히 제한됩니다. 디코딩된 형태가 유지되지 않으면, 원시 스트림 길이가 집계 예산에 산입됩니다.
- 페이지 수 승인 검사는 최선 노력 방식입니다: 카탈로그나 페이지 트리 읽기 실패가 그 자체로 문서를 거부하지는 않습니다. 객체 수와 압축 해제 예산은 항상 강제됩니다.
- 원시 스트림 길이가 정수
/Length항목과 불일치하는 객체는 재구성 시점에 건너뛰어집니다(폴리글롯 방어). 그렇게 건너뛴 객체에 대한 참조는 소스 객체 번호를 유지하며 출력에서 해석되지 않을 수 있습니다.sanitize()는 탐지 가능하게 손상된 결과(누락된/Root)를 거부하지만, 저수준CdrRebuilder::rebuild()를 직접 구동하는 호출자는 출력 구조와 참조 무결성을 스스로 재검증해야 합니다. - 소스 트레일러가
/ID를 담고 있으면, 재구성된 트레일러는 원본이 아니라 새로 생성된 임의의/ID를 담습니다./Info를 포함한 다른 트레일러 항목은 이월되지 않으며; 재구성된 트레일러는/Size, 해석 가능할 때의/Root, 그리고 재생성된/ID를 담습니다. - 디코딩된 이름 및 키 바이트는 구분자, 공백, 인쇄 불가능한 바이트에 대해 16진수 이스케이프로 다시 방출되므로, 적대적 이름이 출력에 딕셔너리 구문을 주입할 수 없습니다.
- 알려진 이름 값 집합 밖의 딕셔너리 키 아래의 문자열 값은 보수적으로 리터럴 문자열로 방출됩니다.
CdrPolicy::legacyThreatTypes()는 미래의 어떤 열거형 케이스든Strip*케이스로 등록되지 않는 한 기본 제거 대상으로 취급하므로, 새로운 손실 케이스가 기본 정책에 조용히 들어갈 수 없습니다.- CDR은 암호 모듈이 아닙니다. 그것의 유일한 무작위성 사용은 재생성된 트레일러
/ID입니다. 서명 검증은 여기서 범위 밖입니다; 서명 심층 레퍼런스를 참조하십시오.
적합성
섹션 제목: “적합성”| 주장 | 표준 | 절 |
|---|---|---|
| ECMAScript 액션을 호출하면 PDF 프로세서가 내장된 스크립트를 실행하게 됩니다. | ISO 32000-2 | §12.6.4.17 |
JavaScript 이름 트리의 문서 수준 스크립트는 문서가 열릴 때 모두 실행됩니다. | ISO 32000-2 | §12.6.4.17 |
카탈로그 이름 딕셔너리는 문서 수준 스크립트 액션의 JavaScript 이름 트리를 담을 수 있습니다. | ISO 32000-2 | §7.7.4 (Table 32) |
| 실행 액션은 애플리케이션을 실행하거나, 문서를 열거나 인쇄합니다. | ISO 32000-2 | §12.6.4.6 |
/AA 추가 액션 딕셔너리는 주석, 페이지, 필드, 그리고 카탈로그의 트리거 이벤트를 확장합니다. | ISO 32000-2 | §12.6.3 |
| 신뢰할 수 없는 파일 수집은 들어오는 파일의 존재, 볼륨, 콘텐츠를 제한해야 합니다. | OWASP ASVS 5.0 | §5.2 |
| 시스템은 업로드된 파일의 부적절한 실행을 방지하고 위험한 콘텐츠를 탐지해야 합니다. | OWASP ASVS 5.0 | §5.3 |
모든 절은 의역되었으며; NextPDF는 규범적 텍스트를 재현하지 않습니다. NextPDF는 어떠한 인증 주장도 하지 않습니다. CDR은 구성된 정책 하에 ThreatType으로 열거된 능동 콘텐츠 표면을 제거합니다; 이것은 하나의 기능이며 인증된 무해화 도구가 아닙니다. CDR은 안티바이러스 스캐너가 아니며 멀웨어 시그니처를 탐지하지 않습니다; 그것은 OWASP ASVS 5.4.3 안티바이러스 스캔과 같은 통제를 보완하며 충족하지는 않습니다. 무해화된 파일이 주어진 수집 파이프라인에 수용 가능한지 여부는 운영자의 위험 결정으로 남습니다.
개발 노트
섹션 제목: “개발 노트”- 모듈 소스는
@since 1.9.0을 담고 있습니다; 이 레퍼런스는nextpdf/enterprise3.1.0으로 출하된 표면을 문서화합니다. - 모든 것은 여러분의 호스트에서 인프로세스로 실행됩니다. 무해화 중에 네트워크 접근은 발생하지 않습니다.
CdrPolicy와DetectedThreat는final readonly입니다; 한도를 변경하려면 새 정책 인스턴스를 구성하십시오.CdrEngine은 자신의 detector와 rebuilder를 내부적으로 구성합니다.ThreatDetector와CdrRebuilder는 자체PdfReader를 공급하는 단계별 파이프라인을 위해 직접 사용 가능하게 유지됩니다.CdrRebuilder::rebuild의$policy매개변수는 현재 예약되어 있습니다; 소스는 그것을 호출부 호환성과 향후 정책별 직렬화 조정을 위해 유지된 것으로 문서화합니다.- 출력은 구조적으로 재현 가능하지만, 비트 단위로 재현 가능하지는 않습니다: 재생성된
/ID는 소스가 그것을 담고 있었을 때 매 실행마다 다릅니다. - 결과 유형
CdrResult(sanitize()의 반환값)는 위에서 동작 측면으로 다루어집니다; 그것의 필드는public readonly이며, 편의를 위한hadThreats()와threatCount()를 갖습니다.
함께 보기
섹션 제목: “함께 보기”- 콘텐츠 무해화 및 재구성 (CDR) — 워크플로 및 정책 지침이 담긴 기능 페이지.
- 보안 — 심층 레퍼런스
- 검증 — 심층 레퍼런스
- 포렌식 — 심층 레퍼런스
발행 경계
섹션 제목: “발행 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만을 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 테이블, 런북 파일명, 그리고 티켓 접두사는 범위 밖입니다.