PDF nije samo papir. To je kontejner koji može nositi skripte koje se pokreću kada se datoteka otvori, linkove koji pokreću spoljne programe, linkove koji se obraćaju veb serverima, datoteke ugnežđene unutar datoteka i potpis koji tvrdi da se dokument nije promenio otkad je neko garantovao za njega. Kada datoteka stigne iz izvora koji ne kontrolišete, najbezbedniji prvi korak nije njeno renderovanje. To je čitanje onoga što datoteka kaže o sebi i pravljenje popisa svega što bi mogla da pokuša da uradi, kako bi čovek mogao da odluči da li joj je uopšte mesto u vašem radnom procesu.
Ovaj članak prolazi kroz statički prolaz revizije samo za čitanje preko te površine rizika koristeći PDFium komponentu za Delphi i Lazarus. Revizija nikada ne crta stranicu. Ona parsira strukturu dokumenta, popisuje delove datoteke koji nose ponašanje i piše običan izveštaj. To je razlika između traženja od stranca da isprazni džepove na vratima i verovanja mu samo zato što se nasmešio.
Šta revizija jeste, a šta nije
Budite jasni u vezi sa granicom. Pregled u izolovanom okruženju renderuje datoteku pod strogim ograničenjima kako bi korisnik mogao da je pogleda a da ona ne dodirne ostatak mašine. Revizija dolazi pre toga. To je inspekcija bez renderovanja čiji je jedini izlaz opis površine pretnje: koje skripte postoje, koje akcije su povezane sa linkovima, da li je datoteka potpisana i koliko strogo, i šta je priloženo. Pokrećete je kada dokument pređe granicu poverenja, pri prijemu iz e-pošte, obrasca za otpremanje ili partnerskog toka, pre nego što je bilo koja kasnija faza stvarno otvori.
Komponenta učitava dokument na isti način za reviziju kao i za bilo šta drugo. Pozicionirate ime datoteke i aktivirate je, što parsira podatke unakrsne reference i katalog dokumenta bez renderovanja ijedne stranice. Sve ispod čita iz tog učitanog, nerenderovanog stanja.
var
Pdf: TPdf;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'Incoming_Invoice.pdf';
Pdf.Active := True; // parses structure, renders nothing
// audit the loaded document here
finally
Pdf.Free;
end;
end;
JavaScript dokumenta u stablu imena
Prva stvar koju treba popisati jeste kod. PDF može da nosi JavaScript na nivou dokumenta: skripte koje nisu zakačene ni za jednu stranicu ili polje, već za sam dokument, sačuvane u stablu /Names pod unosom /JavaScript. Usklađeni čitač ih pokreće pri otvaranju. To je mehanizam koji stoji iza duge linije PDF zlonamernog softvera, jer omogućava datoteci da izvrši logiku onog trenutka kada korisnik dvaput klikne na nju, pre nego što pročita ijednu reč.
Revizor želi dve činjenice o svakoj takvoj skripti: da ona postoji i šta sadrži. Komponenta izlaže broj i omogućava vam da pročitate svaku akciju kao zapis koji sadrži ime skripte i njeno celo telo. Čitanje tela je važno. Skripta pod nazivom Doc.0 ne govori vam ništa, ali njen tekst može pozivati app.launchURL ili sastavljati tekstualni niz i slati ga negde gde ne bi trebalo. Izvlačenje izvornog koda kako bi recenzent mogao da ga pročita jeste cela poenta označavanja datoteke koja pokreće kod pri otvaranju.
var
I: Integer;
Action: TPdfJavaScriptAction;
begin
if Pdf.JavaScriptActionCount > 0 then
WriteLn('WARNING: document runs ', Pdf.JavaScriptActionCount,
' script(s) on open');
for I := 0 to Pdf.JavaScriptActionCount - 1 do
begin
Action := Pdf.JavaScriptAction[I];
WriteLn(' script "', Action.Name, '":');
WriteLn(Action.Script); // full body, for a human to read
end;
end;
Datoteka sa nula skripti dokumenta nije automatski bezbedna, jer postoje i skripte stranica i polja, ali datoteka sa skriptama dokumenta uvek zaslužuje drugi pogled. Sam broj prisutnih skripti je koristan filter, a telo skripte je ono što pretvara filter u procenu.
Akcije pokretanja i URI akcije
Sledeće ponašanje koje treba popisati živi na linkovima i napomenama. Dva tipa akcija su najvažnija za revizora. Akcija pokretanja pokreće spoljni program ili otvara lokalnu datoteku kada se link aktivira. URI akcija otvara veb lokaciju. Recenzent koji gleda sumnjiv dokument trebalo bi da vidi, bez kliktanja na bilo šta, da je dugme na trećoj stranici povezano za pokretanje cmd.exe ili za otvaranje URL adrese koja se ne poklapa sa brendom na stranici.
Komponenta klasifikuje linkove koje pronađe i izlaže tip akcije i ciljnu putanju za svaki, tako da revizija može izlistati svaku Launch i URI akciju sa njenim odredištem. Ovo je izveštavanje, a ne izvršavanje. Revizor čita akciju iz strukture i zapisuje je. Nikada je ne prati.
Kontrola čitača koja renderuje dokumente jeste mesto gde bi se praćenje akcije dogodilo, a njeno podrazumevano držanje je namerno oprezno. Kontrola TPdfView ima skup LinkOptions koji odlučuje koji tipovi linkova se automatski aktiviraju na klik. Podrazumevana vrednost je [loAutoGoto, loAutoOpenURI], što znači da se skokovi unutar dokumenta i veb URL-ovi mogu otvoriti, ali je loAutoLaunch odsutan, tako da se akcije pokretanja nikada ne pokreću automatski. Za radni tok revizije idete korak dalje i potpuno praznite skup, tako da se apsolutno ništa ne pokreće automatski dok još odlučujete da li da verujete datoteci.
// Audit posture for the viewer: nothing auto-runs, nothing auto-opens.
View.LinkOptions := [];
// The shipped default already withholds launch:
// default = [loAutoGoto, loAutoOpenURI]
// loAutoLaunch is NOT in the default set, so external programs
// are never started on a stray click out of the box.
Razlog za uskraćivanje pokretanja po podrazumevanoj vrednosti je jednostavan. Skok unutar dokumenta je bezopasan, a URL je vidljiv i može se otkazati, ali pokretanje proizvoljnog spoljnog programa jednim klikom je najopasnija stvar koju PDF link može da zahteva, pa je stoga isključeno osim ako se ne odlučite za to. Revizor se odriče čak i bezbednih ponašanja, jer je posao gledati, a ne delovati.
Nivo dozvole MDP digitalnog potpisa
Potpisi menjaju pitanje. Običan potpis svedoči o bajtovima u vreme potpisivanja. Sertifikacioni potpis, onaj kreiran sa pravilom za detekciju i sprečavanje modifikacije dokumenta, ide dalje: on deklariše šta se može legitimno promeniti nakon što je dokument sertifikovan, a usklađeni čitač upozorava ako je dodirnuto bilo šta izvan te dozvole. Čitanje tog nivoa dozvole govori revizoru da li je datoteka sertifikovana i, ako jeste, koliko je zaključana predviđena da bude.
MDP dozvola je ceo broj sa tri definisane vrednosti. Nivo 1 znači da promene uopšte nisu dozvoljene; svaka modifikacija narušava sertifikaciju. Nivo 2 dozvoljava popunjavanje obrazaca i potpisivanje, što je uobičajen slučaj za ugovor koji treba da se popuni i potpiše, ali ne i drugačije menja. Nivo 3 dodatno dozvoljava napomene pored popunjavanja obrazaca i potpisivanja. Poznavanje nivoa omogućava vašoj logici prihvata da razume nameru: dokument sertifikovan na nivou 1 koji uprkos tome sadrži polja obrazaca ili skripte protivreči samom sebi, i tu protivrečnost vredi označiti.
Komponenta čita broj potpisa i izlaže svaki kao zapis čije polje Permission nosi tu MDP vrednost, popunjenu direktno iz osnovnog poziva FPDFSignatureObj_GetDocMDPPermission. Dozvola nula znači da potpis nije sertifikacioni potpis, tako da nema zaključavanja na nivou dokumenta o kome bi se izveštavalo.
var
I: Integer;
Sig: TPdfSignature;
begin
if Pdf.SignatureCount = 0 then
WriteLn('document is not signed')
else
for I := 0 to Pdf.SignatureCount - 1 do
begin
Sig := Pdf.Signature[I];
case Sig.Permission of
1: WriteLn('certified: no changes allowed');
2: WriteLn('certified: form fill and signing allowed');
3: WriteLn('certified: form fill, signing and annotations allowed');
else
WriteLn('signed, but not a DocMDP certification');
end;
end;
end;
Revizija ovde ne proverava kriptografiju potpisa; verifikacija lanca sertifikata je zasebna briga. Ono što ona izveštava jeste deklarisana namera: ova datoteka kaže da je zaključana na ovom nivou. To je upravo kontekst koji je recenzentu potreban da proceni da li su kasnije promene, ili samo prisustvo aktivnog sadržaja, u skladu sa načinom na koji je autor zapečatio dokument.
Ostatak površine: ugrađene datoteke i XFA
Još dve stavke zaokružuju kompletan popis. Ugrađene datoteke su celi dokumenti koji se nose unutar PDF-a kao prilozi, i oni su klasično sredstvo isporuke, jer izveštaj bezazlenog izgleda može da isporuči izvršnu datoteku ili drugi zlonamerni PDF u svom stablu priloga. Komponenta izlaže broj priloga i ime svakog priloga, tako da revizija može izlistati šta sve putuje uz datoteku bez izvoženja ili otvaranja bilo čega od toga.
Prisustvo XFA je druga zastavica. XFA obrazac zamenjuje statički AcroForm XML-zasnovanom arhitekturom obrazaca koja donosi sopstveni model renderovanja i skriptovanja, veću i složeniju površinu od običnog obrasca. Ne morate da obrađujete XFA da biste primetili da je tu; njegov samo prisustvo je signal da datoteka nosi bogatiji interaktivni sloj koji vredi detaljnije pogledati. Komponenta ga prijavljuje kao jednu logičku vrednost.
var
I: Integer;
begin
if Pdf.XFA then
WriteLn('NOTE: document contains an XFA form layer');
if Pdf.AttachmentCount > 0 then
begin
WriteLn('embedded files: ', Pdf.AttachmentCount);
for I := 0 to Pdf.AttachmentCount - 1 do
WriteLn(' - ', Pdf.AttachmentName[I]);
end;
end;
Jedna rutina samo za čitanje koja piše izveštaj
Spojite delove i revizija je jedna procedura koja učitava dokument, popisuje njegove skripte i njihova tela, navodi njegove Launch i URI ciljeve, izveštava o MDP nivou potpisa, beleži priloge i XFA i upisuje nalaze u dnevnik. Ona ne renderuje ništa, pa je stoga jeftina i ne može se prevariti da prikaže neprijateljski sadržaj stranice. Izlaz je ravan zapis čitljiv čoveku na osnovu kojeg recenzent ili nizvodno pravilo mogu delovati.
Oblik koji dobro funkcioniše u praksi jeste sakupljanje svakog nalaza u red, dodavanje prefiksa za zaista rizične nalaze kako bi se sortirali na vrh reda za pregled, i čuvanje celine pored datoteke. Dokument bez skripti, bez akcija pokretanja, bez priloga, bez XFA i ili bez potpisa ili sa koherentnom sertifikacijom prolazi tiho. Dokument koji aktivira nekoliko zastavica odjednom je onaj koji osoba treba da vidi pre nego što ga bilo koja kasnija faza otvori. Revizija ne donosi odluku o poverenju umesto vas. Ona se stara da odluka bude informisana, a ne slepa.
Nakon što datoteka prođe reviziju i zaista morate da je pogledate, učinite to pod ograničenjem, a ne u podrazumevanom čitaču. Pristup u našem vodiču o izgradnji bezbednog PDF pregleda u Delphi-ju pokazuje kako sprečiti automatsko rukovanje linkovima i aktivnim sadržajem da deluju tokom kontrolisanog pregleda. Da biste ugradili ovaj popis u pun proces prijema sa alatima za recenzente, pogledajte članak o radnom okruženju za prijem i reviziju PDF-a. Oba se grade na istoj osnovi samo za čitanje i bez renderovanja i isporučuju se kao deo PDFium komponente za Delphi i C++Builder, zajedno sa API-jima za renderovanje, tekst, obrasce i potpise koji su pokriveni na drugim mestima na ovom blogu.