V gradnjah komponente PDFium Component pred v3.126.2 je TPdf.AnalyzeSignatureRevisions lahko pravo urejanje vsebine strani ocenil kot dovoljeno spremembo anotacije pod DocMDP P=3, ker je njegov graf vlog revizij povratno referenco /P podpisnega widgeta na njegovo stran obravnaval kot lastništvo. Od v3.126.2 komponenta PDFium Component loči navigacijske povezave od povezav lastniške vsebine, tako da vsebina strani ostane vsebina strani. Hroščje poročilo za tem popravkom je na papirju videti neškodljivo. Certificirana pogodba dovoljuje anotacije, nasprotna stranka doda en inkrementalni shranjevalni korak, analizator pa pove, da je vsaka poznejša sprememba dovoljena. Potem nekdo primerja izrisane strani in znesek plačila na strani 2 je drugačen
Ta članek je nadaljevanje s pogledom napadalca na pregled analize sprememb revizij po podpisu, zato izpušča osnove ponovne izgradnje revizij in ocenjevanja DocMDP ter gre naravnost k grafu objektov: kako je bilo lastništvo modelirano, zakaj smer povezave odloča varnostno sodbo, kaj se je spremenilo v v3.126.2 in kako preveriti lastno sprejemno logiko
Zakaj je urejanje strani pod DocMDP P=3 šlo skozi kot sprememba anotacije?
Urejanje strani je šlo skozi, ker je stari graf vlog sledil vsaki posredni referenci v slovarju, kot da objekt, na katerega se sklicuje, pripada tistemu, ki se sklicuje, podpisni widget pa kaže nazaj na svojo stran. Slovar anotacije nosi /P, posredno referenco na objekt strani, na katerem stoji (ISO 32000-1 §12.5.2). Ta vnos je navigacijski namig. Widget ne lasti strani; stran lasti widget prek svoje tabele /Annots
Analizator vsakemu objektu dodeli množico bitov vlog, preden oceni poznejše spremembe: stran, anotacija, obrazec in validacijsko gradivo. Korenski objekti dobijo svojo vlogo iz svojega slovarja, vloga pa se nato razleze na vse, na kar se sklicujejo. V stari propagaciji je veriga tekla takole:
- Podpisni widget je
/Subtype /Widgets/FT /Sig, zato dobi vlogo anotacije - Widgetov
/Ppotisne vlogo anotacije na slovar strani, ki vlogo strani že ima - Stran potisne obe vlogi v
/Contents,/Resourcesin prek/Parentnavzgor v drevo Pages ter čez na vsako sestrsko stran - Slovar toka vsebine, kot je
<< /Length 812 >>, nima/Type, zato je razvrščevalnik padel nazaj na bite vlog in preveril vlogo anotacije pred vlogo strani
Spremenjeni tok vsebine je zato izšel kot prckAnnotation. Pod ISO 32000-1 §12.8.2.2 DocMDP P=3 dovoljuje spremembe anotacij, zato je bila odločitev prdAllowed in poročilo se je zvilo v prasAllowed. Isti zapis pod P=2 je bil zavrnjen, a samo po naključju: P=2 prepove spremembe anotacij, zato je bil napačno označeni tok zavrnjen iz napačnega razloga. Fiksirana propagacijska zanka s štirimi prehodi je dodala še drugo slabost. Obremenka, dosežena skozi posredno tabelo ali skozi dolgo verigo, katere številke objektov tečejo nazaj, morda sploh ne dobi nobene vloge
Zakaj mora validator podpisov vprašati, kdo lasti objekt?
Validator podpisov se mora vprašati, kdo lasti objekt, ker inkrementalne posodobitve PDF (ISO 32000-1 §7.5.6) komur koli dovolijo pripeti revizijo, ki redefinira obstoječo številko objekta, redefinirano telo pa ne naznani, kaj je. Podpis se še vedno preveri, ker pokriva samo bajte svoje revizije. Vsaka obramba pred manipulacijo po podpisu je zato odvisna od preslikave vsakega spremenjenega objekta na strukturo, ki ga uporablja, in od vprašanja, ali je podpisnik dovolil, da se ta struktura spremeni
Nekaj objavljenih razredov napadov ravno tam dela. Napadi z inkrementalnim shranjevanjem pripnejo revizijo, ki zamenja vsebino strani, in se zanašajo na to, da preverjevalnik preverja samo podpisani bajtni razpon. Senčni napadi posadijo skrito vsebino pred podpisom in jo aktivirajo pozneje z majhno, neškodljivo vidno spremembo. Napadi na certificirane dokumente zlorabijo to, da P=2 in P=3 izrecno dovoljujeta nekatere poznejše spremembe, prepovedano spremembo paoblečeta v dovoljeno. Preverjevalnik, ki razvršča objekte po oznakah, kot je /Type /Annot, ali po kateri koli referenčni poti, ki jih po naključju doseže, je izpostavljen tretjemu razredu: napadalec potrebuje samo eno dovoljeno strukturo, ki doseže prepovedano
Zato vprašanje ni, kateri objekti so se spremenili, ampak kdo jih lasti. Tok vsebine, dosežen iz strani prek /Contents, je vsebina strani, kar koli že kaže nanj. Anotacija, ki kaže nazaj na stran prek /P, pove, kje anotacija živi, ne pa kaj lasti
Kako komponenta PDFium Component v3.126.2 modelira lastništvo?
Komponenta PDFium Component v3.126.2 obravnava povratne reference kot navigacijo, jih drži izven propagacije vlog in odloča, kateri ključi štejejo kot navigacija, iz strukturne vloge slovarja, ki jih nosi, ne iz samega imena ključa. Tabela povzame navigacijske ključe, ki lastništva več ne nosijo
| Lastniški slovar | Ključi, obravnavani kot navigacija | Sklic na specifikacijo |
|---|---|---|
| Stran ali vozlišče Pages | /Parent, /Kids, /Annots | ISO 32000-1 §7.7.3 |
| Anotacija ali widget | /P | ISO 32000-1 §12.5.2 |
| Slovar widgeta ali polja | /Parent | ISO 32000-1 §12.7.3 |
Filtriranje po imenu ključa globalno bi ustvarilo novo luknjo. Vira pisave ali XObject se lahko upravičeno imenuje /P, /Parent ali /Annots, slovar /Resources, ki bi iz propagacije odvrgel svoj vnos /P, pa bi napadalcu dovolil skriti objekt XObject, v lasti strani, za nedolžnim imenom vira. V v3.126.2 navigacijski filter velja samo, kadar je lastniški slovar dejansko stran, vozlišče Pages, anotacija, widget ali polje. Če ena od teh slovarjev nosi podvojen navigacijski ključ, na primer dva vnosa /P v widgetu, analizator ne ugane, katero kopijo bi uporabil pregledovalnik; gradnja vlog spodleti in podpis postane Indeterminate
Še nekaj pravil zapre preostale poti ponovnega označevanja:
- Vozlišča Pages so koreni vloge strani po lastni pravici, zato viri, podedovani iz drevesa Pages (ISO 32000-1 §7.7.3.4), vstopijo v kontekst strani skozi pravo lastništvo, ne skozi sprehod po
/Parentiz otroške strani - Vloga anotacije ali obrazca, ki prispe na katalog, vozlišče Pages, stran, anotacijo ali slovar polja, se tam ustavi, ker ti strukturni objekti ustanovijo svoje vloge in prihajajoča vloga obremenke jih ne sme preglasiti
- Vloga strani je med razvrščanjem avtoritativna: objekt v lasti strani je
prckPageContent, tudi če ga poznejša revizija prepiše s ponarejenim/FT, oznako/Type /Annotali ga deli s tokom videza - Form XObject, uporabljen samo kot videz polja ali anotacije, obdrži svojo kategorijo obrazca ali anotacije, zato navadna ponovna izdelava videza po izpolnitvi obrazca ostane ocenjena pod običajnimi pravili dovoljenj
- Widget brez lastnega
/FTrazreši podedovano vrsto polja skozi verigo/Parent, nerazrešljiva veriga pa spodleti gradnjo vlog namesto da bi privzela anotacijo - Biti vlog iz vsake poznejše revizije se združijo v vloge pokrite revizije, tako da poznejša posodobitev ne more izbrisati zgodnejšega razmerja lastništva strani tako, da tok najprej odcepi in ga nato uredi
Fiksna točka namesto fiksnega števila prehodov
Dosegljivost vlog v v3.126.2 teče kot delovna vrsta, ki se ponavlja, dokler noben objekt ne dobi novega bita vloge, kar je prava fiksna točka, ne glede na globino verige ali številčenje objektov. Posredne tabele, kot je tabela /Contents, shranjena kot lasten objekt, so prav tako prehojene. Vsak objekt lahko dobi največ štiri različne bite vlog, zato je vrsta omejena na štiri vnose na številko objekta; preseganje tega proračuna sproži prrResourceLimitExceeded. Referenca na prosti objekt, neujemanje generacije ali polomljena glava objekta sprožita prrMalformedRevisionChain, obremenka znotraj stisnjenega toka objektov pa prrCompressedObjectUnresolved. Vsak od teh spodletelih primerov se konča s prasIndeterminate, nikoli z dovoljeno sodbo, kadar pa spodletitev zgodi med gradnjo vlog pokrite revizije, podpis sploh ne poroča o Changes
Naslednja rutina našteje urejanja vsebine strani, ki preživijo to analizo. Sprememba prckPageContent se nikoli ne oceni prdAllowed: DocMDP P=1, 2 ali 3 jo naredi prdDisallowed, podpis brez DocMDP pa jo oceni prdSuspicious
uses
SysUtils, TypInfo, PDFium, FPdfPades;
procedure ListPageContentEdits(const FileName: string);
const
ShadowTag: array[Boolean] of string = (' (unreferenced shadow)', '');
var
Pdf: TPdf;
Report: TPadesRevisionAnalysisReport;
Sig: TPadesSignatureRevisionAnalysis;
Change: TPadesRevisionObjectChange;
i, j: Integer;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := FileName;
Pdf.Active := True;
Report := Pdf.AnalyzeSignatureRevisions; // zapis, ničesar za sprostiti
for i := 0 to High(Report.Signatures) do
begin
Sig := Report.Signatures[i];
if not (prrPageContentChanged in Sig.Risks) then
Continue;
Writeln(Format('Signature %d (DocMDP P=%d): page content changed',
[Sig.SignatureIndex, Sig.DocMdpPermission]));
for j := 0 to High(Sig.Changes) do
begin
Change := Sig.Changes[j];
if Change.Kind <> prckPageContent then
Continue;
Writeln(Format(' revision %d object %d %d R %s%s',
[Change.RevisionIndex, Change.ObjectNumber, Change.Generation,
GetEnumName(TypeInfo(TPadesRevisionDecision), Ord(Change.Decision)),
ShadowTag[Change.IsAuthoritative]]));
end;
end;
finally
Pdf.Free;
end;
end;
Kaj se zgodi, kadar FieldMDP in anotacija delita en objekt?
Kadar /V polja in /Contents anotacije kažeta na isti posredni objekt, v3.126.2 obdrži zaklep FieldMDP v veljavi, tudi če je sprememba razvrščena kot urejanje anotacije. Scenarij se da ročno izdelati: podpisnik zaklene polje Total s FieldMDP (ISO 32000-1 §12.8.2.4), napadalec pa naredi, da se /Contents besedilne anotacije sklicuje na isti niz objektov, ki drži vrednost polja. Pod P=3 je urejanje anotacije dovoljeno, zato je prepis tega deljenega niza pred popravkom spremenil zaklenjeno vrednost polja z dovoljeno sodbo
Objekt zdaj nosi tako vlogo anotacije kot obrazca, odločitev anotacije pa ponovno preveri stran obrazca, kadar koli ima podpis transformacijo FieldMDP:
- Pod P=2 je sprememba anotacije čisto zavrnjena, točno kot prej
- S FieldMDP
Allje zaklenjeno vsako polje, zato je deljena spremembaprdDisallowed - S FieldMDP
IncludealiExcludeanalizator deljenega skalarnega podatka ne more slediti nazaj do enega imena polja, zato je odločitevprdIndeterminatenamesto ugibanja - Brez FieldMDP velja pravilo anotacije P=3 in sprememba ostane dovoljena
Ena podrobnost poročanja je pomembna za pregrado v kodi. Deljeni primer se poroča kot Kind = prckAnnotation z Decision = prdIndeterminate, prrFieldMdpUnresolved pa se v množico tveganj doda samo za spremembe, razvrščene kot polja obrazcev. Pregrada, ki išče prrFieldMdpUnresolved in ignorira Status, ta primer spregleda popolnoma
Kako naj koda v Delphiju ob analizi revizij spodleti zaprto?
Koda v Delphiju naj sprejme podpisan dokument samo, kadar je stanje analize prasNoLaterChanges ali prasAllowed in ni nobenega strukturnega tveganja, prasIndeterminate in prasSuspicious pa naj obravnava kot nezaupanja vredna, ne kot opozorili za dnevnik in prehod. Nedoločeno pomeni, da analizator ni mogel dokazati, da so bile poznejše revizije dovoljene; za napadalca je vnos, ki zanesljivo izda Nedoločeno, enako koristen kot tisti, ki izda Dovoljeno, če ga vaša koda spusti skozi. Globalni AnalyzePadesSignatureRevisions sprejme vsak TStream in ga bere od položaja 0, kar ustreza ročajevalnikom nalaganj, ki dokumenta ne potrebujejo izrisovati
uses
Classes, SysUtils, TypInfo, FPdfPades;
const
// Podvojeni definicije se zapišejo brez znižanja Status
BlockingRisks: TPadesRevisionRisks = [prrMalformedRevisionChain,
prrDuplicateObjectDefinition, prrUnreferencedObjectDefinition,
prrSignatureObjectRedefined, prrCompressedObjectUnresolved,
prrResourceLimitExceeded];
function SignedRevisionsAcceptable(const FileName: string;
out Reason: string): Boolean;
var
Source: TFileStream;
Report: TPadesRevisionAnalysisReport;
begin
Result := False;
Reason := '';
Source := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Report := AnalyzePadesSignatureRevisions(Source);
finally
Source.Free;
end;
if Report.SignatureCount = 0 then
begin
Reason := 'no signature anchors the analysis';
Exit;
end;
if Report.Risks * BlockingRisks <> [] then
begin
Reason := 'structural risk in the revision chain';
Exit;
end;
case Report.Status of
prasNoLaterChanges, prasAllowed:
Result := True;
else
// prasIndeterminate in prasSuspicious sta zavrnitvi, ne opozorili
Reason := 'revision status ' +
GetEnumName(TypeInfo(TPadesRevisionAnalysisStatus), Ord(Report.Status));
end;
end;
Dve meji sta vredni jasne izjave. TPadesRevisionAnalysisReport ne pove nič o celovitosti CMS ali zaupanju v certifikat, zato ta pregrada stoji ob kriptografski in zaupnostni validaciji, ne namesto njiju. In pravi graf lastništva ne naredi P=3 varnega za vsak delovni tok. P=3 res dovoljuje anotacije, anotacija z motnim videzom pa lahko pokrije podpisano besedilo, ne da bi se dotaknila enega samega toka vsebine. Če so vaši certificirani dokumenti pogodbe in ne pregledne kopije, bodisi certificirajte s P=2 bodisi dovoljene spremembe anotacij usmerite človeku, kot v tem pomožniku:
function AllowedAnnotationEditsUnderP3(
const Report: TPadesRevisionAnalysisReport): Integer;
var
i, j: Integer;
begin
Result := 0;
for i := 0 to High(Report.Signatures) do
if Report.Signatures[i].DocMdpPermission = 3 then
for j := 0 to High(Report.Signatures[i].Changes) do
if (Report.Signatures[i].Changes[j].Kind = prckAnnotation) and
(Report.Signatures[i].Changes[j].Decision = prdAllowed) then
Inc(Result);
end;
Kontrolni seznam za revizijo podpisnih revizij
Ta seznam uporabite, da preverite, ali je bila vaša veriga preverjanja izpostavljena in ali zdaj spodleti zaprto:
- Gradnje komponente PDFium Component pred v3.126.2 so lahko poročale
prasAllowedza urejanja vsebine strani v dokumentih DocMDP P=3; ponovno poženiteTPdf.AnalyzeSignatureRevisionsnad certificiranimi datotekami P=3, sprejetimi s strani starejših gradnji - Ponovno preverite dokumente P=3 z zaklepi FieldMDP, kjer se vrednost polja in anotacija morda delita posredni objekt
- Sprejmite samo
prasNoLaterChangesinprasAllowed;prasIndeterminateinprasSuspiciousobravnavajte kot nezaupanja vredni - Preizkusite
Report.Riskskot tudiReport.Status, kerprrDuplicateObjectDefinitionstanja sam po sebi ne spremeni - Prazne tabele
Changesne berite kot čistega rezultata, kadar je stanje podpisa Nedoločeno; spodletela gradnja vlog ne poroča o nobeni spremembi - Ne zanašajte se samo na
prrFieldMdpUnresolved, da ujamete težave FieldMDP, saj deljeni primer anotacije pride na površje samo skozi odločitev in stanje - Odločite, ali dovoljene spremembe anotacij pod P=3 potrebujejo človeški pregled v vašem delovnem toku
- Analizirajte izvirne bajte datoteke; dokument, prepisan s
SaveAs, verige revizij več ne vsebuje
Analiza revizij je ena plast preverjanja podpisa. Spara jo z pregledom digitalnih podpisov PDF in ravni PAdES za slovar in osnovno raven ter z širšim revidiranjem varnostnih tveganj PDF za JavaScript, akcije zagona in vgrajene datoteke. TPdf.AnalyzeSignatureRevisions, AnalyzePadesSignatureRevisions in graf vlog, ki pozna lastništvo, opisan tukaj, prihajajo v komponenti PDFium Component za Delphi, C++Builder in Lazarus