Pular para o conteúdo
getnextpdf.com

Enterprise edição

Content Disarm and Reconstruction — Referência Profunda

Esta página é a referência detalhada do módulo NextPDF\Enterprise\Security\Cdr. O módulo desarma um PDF não confiável e reconstrói um arquivo limpo a partir de seus objetos seguros. O pipeline é: análise, controle de admissão, detecção de ameaças, filtragem, limpeza de referências, reconstrução. A saída é uma projeção de segurança da entrada, nunca uma cópia probatória. Para orientação de fluxo de trabalho, leia primeiro a página de capacidade do CDR.

Esta capacidade é distribuída no NextPDF Enterprise (nextpdf/enterprise) e é ativada com um envelope de licença de nível Enterprise. Uma implantação sem esse direito não carrega as classes da capacidade. Compare edições e obtenha uma licença.

SímboloParâmetrosComportamento padrãoRetornaLança ou falha comNotas
CdrEngine::__constructnenhumConstrói o detector e o reconstrutor internosCdrEngineNada declaradoSem colaboradores injetáveis
CdrEngine::sanitizestring $pdfData, ?CdrPolicy $policy = nullExecuta o pipeline completo sob CdrPolicy::standard()CdrResultNão lança em entrada hostil; falhas de análise e de admissão retornam um resultado rejeitadoO resultado relata a rejeição de forma distinta da sanitização
CdrPolicy::__constructsete parâmetros nomeados opcionais, veja o blocoConjunto de remoção vazio; allowUriActions false; flattenIncrementalUpdates true; limites de 100000 objetos, 256 MiB decodificados, 10000 páginas, inflação de 1000.0CdrPolicyNada declaradofinal readonly; uma lista removeThreatTypes vazia não detecta nada
CdrPolicy::standardnenhumConjunto de ameaças legado; ações URI removidas; limites padrãoselfNada declaradoExclui os sete casos Strip* com perdas
CdrPolicy::paranoidnenhumConjunto de ameaças legado com limites mais rígidos: 50000 objetos, 128 MiB, 5000 páginas, inflação de 100.0selfNada declaradoExclui os sete casos Strip* com perdas
CdrPolicy::permissivenenhumRemove apenas JavaScript, LaunchAction, NamedJavaScript, SubmitForm, ImportData; preserva ações URIselfNada declaradoDestinado a fontes confiáveis
CdrPolicy::allThreatTypesnenhumRetorna todos os casos de ThreatType, incluindo os casos Strip* com perdaslist<ThreatType>Nada declaradoA adesão explícita à remoção máxima
CdrPolicy::legacyThreatTypesnenhumRetorna todos os casos exceto os sete casos Strip*list<ThreatType>Nada declaradoConjunto de remoção padrão para standard() e paranoid()
CdrPolicy::shouldRemoveThreatType $typeTeste de pertencimento em removeThreatTypesboolNada declaradoRetorna false para UriAction quando allowUriActions é true
ThreatDetector::detectPdfReader $reader, CdrPolicy $policyVarre cada objeto e o catálogo do trailer em busca dos tipos de ameaça da políticalist<DetectedThreat>Não lança; um objeto não analisável se torna uma ameaça UnparseableObjectA varredura do catálogo cobre a árvore /Names/JavaScript
CdrRebuilder::rebuildPdfReader $reader, list<int> $safeObjNums, list<int> $removedObjNums, CdrPolicy $policySerializa os objetos seguros em um arquivo %PDF-2.0 de revisão únicastringNada declarado; objetos que falham na releitura ou na validação de /Length são ignorados$policy está reservado para futuros ajustes de serialização
DetectedThreat::__constructThreatType $type, int $objectNumber, string $description, string $location = ''Objeto de valor imutável de descobertaDetectedThreatNada declaradoTodas as quatro propriedades são public readonly
ThreatTypeenum baseado em stringVinte casos: treze legados mais sete casos Strip* opcionaisn/an/aVeja o inventário de casos abaixo
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: string

Treze casos legados formam o conjunto de remoção padrão. Os casos Strip* têm perdas por design e nunca entram em uma política padrão.

CasoValor de apoioSuperfície de detecção
ThreatType::JavaScriptjavascriptchave /JS em qualquer objeto, ou uma ação /S /JavaScript
ThreatType::AdditionalActionsadditional-actionsdicionário /AA em qualquer objeto
ThreatType::OpenActionopen-actionchave /OpenAction em qualquer objeto
ThreatType::LaunchActionlaunch-actionação /S /Launch
ThreatType::RemoteGoToremote-gotoação /S /GoToR ou /S /GoToE
ThreatType::SubmitFormsubmit-formação /S /SubmitForm
ThreatType::ImportDataimport-dataação /S /ImportData
ThreatType::EmbeddedFilesembedded-filesárvore de nomes /EmbeddedFiles ou dicionário /EF
ThreatType::RichMediarich-media/Subtype /RichMedia
ThreatType::NamedJavaScriptnamed-javascriptárvore de nomes /Names/JavaScript do catálogo
ThreatType::UriActionuri-actionação /S /URI; suprimida quando allowUriActions é true
ThreatType::Xfaxfachave /XFA
ThreatType::UnparseableObjectunparseable-objectQualquer objeto ou catálogo que falha na análise
ThreatType::StripJavaScriptstrip-javascriptSuperconjunto opcional: chave /JS, /S /JavaScript ou /Subtype /JavaScript
ThreatType::StripEmbeddedFilesstrip-embedded-filesOpcional: /Type /EmbeddedFile, /Type /Filespec, /EmbeddedFiles ou /EF
ThreatType::StripFormFieldsstrip-form-fieldsOpcional: /Subtype /Widget, chave /FT ou chave /AcroForm
ThreatType::StripAnnotationsRichstrip-annotations-richSubtipos opcionais: Movie, Sound, FileAttachment, 3D, RichMedia, Screen
ThreatType::StripOcgNonDefaultstrip-ocg-non-defaultOpcional: /Type /OCG com uma chave /Usage ou /Visibility
ThreatType::StripDigitalSignaturesAtRebuildstrip-digital-signatures-at-rebuildOpcional: /Type /Sig, /FT /Sig, /DSS, /VRI ou /ByteRange
ThreatType::Strip3dAndRichMediastrip-3d-and-rich-mediaSubtipos opcionais: 3D, U3D, PRC, RMF, RichMedia, Sound, Movie

CdrEngine::sanitize executa seis fases ordenadas e nunca lança para entrada hostil.

  1. Análise. Uma falha de análise retorna um resultado com admitted false e um motivo de rejeição de erro de análise. A saída sanitizada fica vazia nesse caso.
  2. Controle de admissão. A contagem de objetos, o total agregado de bytes de fluxo decodificados, a razão de inflação por fluxo e a contagem de páginas são verificados em relação aos limites da política. Um documento acima do limite é rejeitado, não sanitizado. Rejeição e sanitização são relatadas de forma distinta.
  3. Detecção. ThreatDetector::detect varre cada objeto e o catálogo do trailer em busca dos tipos de ameaça da política. Objetos não analisáveis são registrados como descobertas ThreatType::UnparseableObject em vez de ignorados.
  4. Filtragem. Objetos que carregam descobertas são enfileirados para remoção. O catálogo do documento nunca é removido como objeto inteiro. Descobertas em nível de catálogo (OpenAction, AdditionalActions, NamedJavaScript) são remediadas por remoção de chaves.
  5. Limpeza de referências. Cada referência indireta a um objeto removido é substituída por null durante a serialização.
  6. Reconstrução. CdrRebuilder::rebuild emite um arquivo %PDF-2.0 de revisão única com objetos renumerados, uma tabela de referência cruzada clássica e um trailer novo. Os bytes de fluxo seguros são copiados de forma byte-idêntica. O catálogo reconstruído descarta /OpenAction, /AA e /Names; /AA é descartado de cada objeto.

O CdrResult retornado expõe os bytes reconstruídos, a lista de ameaças removidas, ambos os tamanhos em bytes, o sinalizador de admissão e o motivo de rejeição. Se a origem tinha um /Root resolvível e a saída reconstruída o perdeu, o motor rejeita a saída em vez de retornar um arquivo estruturalmente quebrado. Esta é uma garantia fail-closed: admitted true implica que a saída ainda carrega uma referência ao catálogo do documento.

Atualizações incrementais nunca sobrevivem: a reconstrução serializa exatamente uma revisão sob qualquer política, portanto revisões tardias no estilo shadow são achatadas por construção. Assinaturas digitais originais não podem permanecer válidas após uma reconstrução, porque os intervalos de bytes não correspondem mais à saída.

Linha vermelha de arquitetura. CDR é uma camada de projeção de segurança, não uma camada de preservação. A saída não deve ser usada para preservação de evidência legal, comparação de hash com o original ou cópias de arquivamento.

  • Uma política null resolve para CdrPolicy::standard(). Uma política construída com o removeThreatTypes vazio padrão não detecta nem remove nada.
  • allowUriActions definido como true suprime a remoção de UriAction mesmo quando o caso está presente em removeThreatTypes.
  • flattenIncrementalUpdates é declarativo nesta versão: a reconstrução emite uma única revisão sob qualquer política, incluindo permissive(), que define o sinalizador como false.
  • A verificação da razão de inflação trata um comprimento de fluxo bruto de zero como um, portanto um fluxo que infla a partir do nada ainda é limitado. Quando nenhuma forma decodificada é retida, o comprimento do fluxo bruto conta para o orçamento agregado.
  • A verificação de admissão por contagem de páginas é de melhor esforço: uma falha de leitura do catálogo ou da árvore de páginas não rejeita o documento por si só. Os orçamentos de contagem de objetos e de descompressão são sempre aplicados.
  • Um objeto cujo comprimento de fluxo bruto discorda de sua entrada inteira /Length é ignorado no momento da reconstrução (defesa contra poliglota). Uma referência a esse objeto ignorado retém seu número de objeto de origem e pode não resolver na saída. sanitize() recusa resultados detectavelmente quebrados (um /Root ausente), mas um chamador que aciona diretamente o CdrRebuilder::rebuild() de baixo nível deve revalidar a estrutura da saída e a integridade das referências por conta própria.
  • Quando o trailer de origem carrega /ID, o trailer reconstruído carrega um /ID aleatório recém-gerado, não o original. Outras entradas do trailer, incluindo /Info, não são transferidas; o trailer reconstruído mantém /Size, /Root quando resolvível e o /ID regenerado.
  • Bytes de nomes e chaves decodificados são reemitidos com escapes hexadecimais para delimitadores, espaços em branco e bytes não imprimíveis, para que nomes hostis não possam injetar sintaxe de dicionário na saída.
  • Valores de string sob chaves de dicionário fora do conjunto conhecido de valores nomeados são emitidos de forma conservadora como strings literais.
  • CdrPolicy::legacyThreatTypes() trata qualquer caso de enum futuro como removido por padrão, a menos que seja registrado como um caso Strip*, portanto novos casos com perdas não podem entrar silenciosamente em políticas padrão.
  • CDR não é um módulo criptográfico. Seu único uso de aleatoriedade é o /ID regenerado do trailer. A validação de assinatura está fora do escopo aqui; consulte a referência detalhada de assinatura.
AfirmaçãoPadrãoCláusula
Invocar uma ação ECMAScript faz um processador de PDF executar o script incorporado.ISO 32000-2§12.6.4.17
Scripts em nível de documento na árvore de nomes JavaScript são todos executados quando o documento abre.ISO 32000-2§12.6.4.17
O dicionário de nomes do catálogo pode conter uma árvore de nomes JavaScript de ações de script em nível de documento.ISO 32000-2§7.7.4 (Table 32)
Uma ação de inicialização inicia um aplicativo, ou abre ou imprime um documento.ISO 32000-2§12.6.4.6
Dicionários de ações adicionais /AA estendem os eventos de disparo em anotações, páginas, campos e no catálogo.ISO 32000-2§12.6.3
A entrada de arquivos não confiáveis deve limitar a presença, o volume e o conteúdo dos arquivos recebidos.OWASP ASVS 5.0§5.2
Os sistemas devem impedir a execução inadequada de arquivos enviados e detectar conteúdo perigoso.OWASP ASVS 5.0§5.3

Todas as cláusulas são parafraseadas; o NextPDF não reproduz texto normativo. O NextPDF não faz nenhuma alegação de certificação. O CDR remove as superfícies de conteúdo ativo enumeradas por ThreatType sob a política configurada; é uma capacidade, não um sanitizador certificado. O CDR não é um scanner antivírus e não detecta assinaturas de malware; ele complementa, e não satisfaz, controles como a varredura antivírus OWASP ASVS 5.4.3. Se um arquivo desarmado é aceitável para um determinado pipeline de entrada permanece a decisão de risco do operador.

  • O código-fonte do módulo carrega @since 1.9.0; esta referência documenta a superfície conforme distribuída no nextpdf/enterprise 3.1.0.
  • Tudo é executado em processo no seu host. Nenhum acesso à rede ocorre durante a sanitização.
  • CdrPolicy e DetectedThreat são final readonly; construa uma nova instância de política para alterar os limites.
  • CdrEngine constrói seu detector e reconstrutor internamente. ThreatDetector e CdrRebuilder permanecem diretamente utilizáveis para pipelines em etapas que fornecem seu próprio PdfReader.
  • O parâmetro $policy de CdrRebuilder::rebuild está atualmente reservado; o código-fonte o documenta como mantido para compatibilidade de local de chamada e futuros ajustes de serialização por política.
  • A saída é reproduzível estruturalmente, não bit a bit: o /ID regenerado difere em cada execução quando a origem carregava um.
  • O tipo de resultado CdrResult (valor de retorno de sanitize()) é coberto comportamentalmente acima; seus campos são public readonly, com hadThreats() e threatCount() como conveniências.

Esta página documenta apenas o comportamento observável externamente e a superfície de API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tíquetes estão fora do escopo.