PDF yra ne tik popierius. Tai konteineris, kuris gali nešti scenarijus, paleidžiamus atidarius failą, nuorodas, paleidžiančias išorines programas, nuorodas, pasiekiančias žiniatinklio serverius, failus, įdėtus kituose failuose, ir parašą, tvirtinantį, kad dokumentas nepasikeitė nuo to laiko, kai kas nors už jį laidavo. Kai failas atkeliauja iš šaltinio, kurio nekontroliuojate, saugiausias pirmasis žingsnis yra ne jo atvaizdavimas. Tai yra to, ką failas sako apie save, perskaitymas ir viso to, ką jis galėtų bandyti daryti, aprašo sudarymas, kad žmogus galėtų nuspręsti, ar jis išvis priklauso jūsų darbo eigai
Šiame straipsnyje apžvelgiamas statinis, tik skaitomas audito praėjimas per šį rizikos paviršių, naudojant PDFium komponentą, skirtą Delphi ir Lazarus. Audito metu puslapis niekada nepiešiamas. Jis analizuoja dokumento struktūrą, išvardija failo dalis, nešančias elgseną, ir rašo paprastą ataskaitą. Tai skirtumas tarp prašymo nepažįstamajam ištuštinti kišenes prie durų ir pasitikėjimo juo, nes jis nusišypsojo
Kas yra auditas ir kas jis nėra
Izoliuota (angl. sandboxed) peržiūra atvaizdoja failą taikant griežtus apribojimus, kad vartotojas galėtų į jį žiūrėti failui neliečiant likusios mašinos dalies. Auditas atliekamas prieš tai. Tai atvaizdavimo neturinti patikra, kurios vienintelė išvestis yra grėsmės paviršiaus aprašymas: kokie scenarijai egzistuoja, kokie veiksmai yra prijungti prie nuorodų, ar failas pasirašytas ir kaip griežtai, ir kas yra pridėta. Jūs paleidžiate jį, kai dokumentas peržengia pasitikėjimo ribą – gaunant jį iš el. pašto, įkėlimo formos ar partnerių srauto, prieš bet kuriam vėlesniam etapui atidarant jį iš tikrųjų
Komponentas įkelia dokumentą auditui taip pat, kaip ir bet kam kitam. Nustatote failo pavadinimą ir jį suaktyvinate, kas išanalizuoja kryžminių nuorodų duomenis ir dokumento katalogą neatvaizduojant nė vieno puslapio. Viskas, kas nurodyta žemiau, skaitoma iš šios įkeltos, neatvaizduotos būsenos
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;
Dokumento JavaScript vardų medyje
Pirmiausia reikia išvardyti kodą. PDF gali nešti dokumento lygio JavaScript – scenarijus, kurie yra priskirti ne puslapiui ar laukui, o pačiam dokumentui, saugomi /Names medyje po /JavaScript įrašu. Suderinama peržiūros programa juos paleidžia atidarymo metu. Tai yra mechanizmas, stovintis už ilgos PDF kenkėjiškų programų eilės, nes jis leidžia failui vykdyti logiką tą akimirką, kai vartotojas jį dukart spusteli, dar prieš jam perskaitant bent vieną žodį
Auditorius nori dviejų faktų apie kiekvieną tokį scenarijų: kad jis egzistuoja ir ką jis turi. Komponentas atskleidžia skaičių ir leidžia perskaityti kiekvieną veiksmą kaip įrašą, saugantį scenarijaus pavadinimą ir jo pilną kūną. Kūno skaitymas yra svarbus. Scenarijus, pavadintas Doc.0, nieko nepasako, tačiau jo tekstas gali iškviesti app.launchURL arba surinkti eilutę ir perduoti ją ten, kur ji neturėtų patekti. Šaltinio ištraukimas, kad recenzentas galėtų jį perskaityti, yra visa esmė žymint failą, kuris paleidžia kodą atidarymo metu
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;
Failas su nuliu dokumento scenarijų nėra automatiškai saugus, nes puslapio ir lauko scenarijai taip pat egzistuoja, tačiau failas su dokumento scenarijais visada vertas antro žvilgsnio. Vien tik buvimo skaičius yra naudingas barjeras, o kūnas yra tai, kas paverčia barjerą sprendimu
Paleidimo ir URI veiksmai
Kita elgsena, kurią reikia inventorizuoti, gyvena nuorodose ir anotacijose. Auditoriams labiausiai rūpi du veiksmų tipai. Paleidimo (angl. Launch) veiksmas paleidžia išorinę programą arba atidaro vietinį failą, kai nuoroda yra suaktyvinama. URI veiksmas atidaro žiniatinklio tikslą. Recenzentas, žiūrėdamas į įtartiną dokumentą, turėtų matyti (nieko nespustelėdamas), kad mygtukas trečiame puslapyje yra prijungtas paleisti cmd.exe arba atidaryti URL, kuris nesutampa su prekės ženklu puslapyje
Komponentas klasifikuoja randamas nuorodas ir atskleidžia kiekvienos veiksmo tipą bei tikslinį kelią, todėl audito ataskaitoje galima išvardyti kiekvieną Launch ir URI veiksmą su jo tikslu. Tai yra pranešimas, o ne vykdymas. Auditorius perskaito veiksmą iš struktūros ir jį užrašo. Jis niekada jo neseka
Peržiūros valdymo programos elgsena
// 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.
Peržiūros valdiklis, kuris atvaizduoja dokumentus, yra ta vieta, kur vyktų veiksmo sekimas, ir jo numatytoji pozicija yra sąmoningai atsargi. TPdfView valdiklis turi LinkOptions rinkinį, kuris nusprendžia, kurie nuorodų tipai suveikia automatiškai spustelėjus. Jo numatytasis nustatymas yra [loAutoGoto, loAutoOpenURI], kas reiškia, kad vidiniai dokumento peršokimai ir žiniatinklio URL gali atsidaryti, tačiau loAutoLaunch nėra, todėl paleidimo veiksmai niekada neveikia automatiškai. Audito darbo eigai einate toliau ir visiškai išvalote rinkinį, todėl niekas automatiškai nesuveikia, kol dar sprendžiate, ar pasitikėti failu
Paleidimo atsisakymo numatytuoju nustatymu motyvas paprastas. Peršokimas dokumente yra nekenksmingas, o URL yra matomas ir atšaukiamas, tačiau bet kokios išorinės programos paleidimas iš spustelėjimo yra pavojingiausias dalykas, kurio gali prašyti PDF nuoroda, todėl jis yra išjungtas, nebent pasirinksite jį įjungti. Auditorius atsisako net ir saugaus elgesio, nes darbas yra žiūrėti, o ne veikti
Skaitmeninio parašo MDP teisių lygis
Parašai pakeičia klausimą. Paprastas parašas liudija apie baitus pasirašymo metu. Sertifikavimo parašas, sukurtas su dokumento pakeitimo aptikimo ir prevencijos (angl. modification detection and prevention arba MDP) taisykle, eina toliau: jis deklaruoja, kas gali teisėtai pasikeisti po to, kai dokumentas buvo sertifikuotas, o suderinama peržiūros programa įspėja, jei buvo paliesta kas nors už to leidimo ribų. Šio teisių lygio perskaitymas praneša auditoriui, ar failas sertifikuotas ir, jei taip, kaip stipriai jis turėtų būti užrakintas
MDP teisės yra sveikasis skaičius su trimis apibrėžtomis reikšmėmis. Lygis 1 reiškia, kad jokie pakeitimai apskritai neleidžiami; bet koks modifikavimas sulaužo sertifikavimą. Lygis 2 leidžia pildyti formas ir pasirašyti – įprastas atvejis sutarčiai, kuri turi būti užpildyta ir pasirašyta, bet kitaip nekeičiama. Lygis 3 papildomai leidžia anotacijas ant formų pildymo ir pasirašymo viršaus. Žinant lygį, jūsų intake logika gali mąstyti apie ketinimus: dokumentas, sertifikuotas 1 lygiu, kuris vis dėlto neša formos laukus ar scenarijus, prieštarauja pats sau, ir šį prieštaravimą verta pažymėti
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;
Komponentas nuskaito parašų skaičių ir atskleidžia kiekvieną kaip įrašą, kurio Permission laukas neša tą MDP reikšmę, gautą tiesiogiai iš pagrindinio FPDFSignatureObj_GetDocMDPPermission iškvietimo. Teisių reikšmė nulis reiškia, kad parašas nėra sertifikavimo (DocMDP) parašas, todėl nėra jokio dokumento lygio užrakinimo, apie kurį reikėtų pranešti
Auditas čia netikrina parašo kriptografinio teisingumo; sertifikatų grandinės tikrinimas yra atskiras rūpestis. Tai, apie ką jis praneša, yra deklaruotas ketinimas: šis failas sako, kad buvo užrakintas šiuo lygiu. Tai būtent tas kontekstas, kurio reikia recenzentui, kad nuspręstų, ar vėlesni pakeitimai arba pats aktyvaus turinio buvimas suderinami su tuo, kaip autorius užplombavo dokumentą
Likusis paviršius: įterpti failai ir XFA
Dar du elementai užbaigia pilną aprašą. Įterpti failai yra sveiki dokumentai, nešami PDF viduje kaip priedai, ir jie yra klasikinė pristatymo priemonė, nes nekaltai atrodanti ataskaita gali gabenti vykdomąjį failą arba antrą kenkėjišką PDF savo priedų medyje. Komponentas atskleidžia priedų skaičių ir kiekvieno priedo pavadinimą, todėl auditas gali išvardyti, kas važiuoja kartu, neišgaunant ir neatidarant nieko iš to
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;
XFA buvimas yra kita vėliavėlė. XFA forma pakeičia statinę AcroForm XML pagrindu sukurta formų architektūra, kuri atneša savo atvaizdavimo ir scenarijų modelį – didesnį ir sudėtingesnį paviršių nei paprasta forma. Jums nereikia apdoroti XFA, kad pastebėtumėte, jog ji ten yra; vien jos buvimas yra signalas, kad failas neša turtingesnį interaktyvų sluoksnį, vertą atidesnio žvilgsnio. Komponentas praneša apie tai kaip apie vieną loginę (angl. boolean) reikšmę
Viena tik skaitoma rutina, kuri rašo ataskaitą
Sujunkite dalis ir auditas taps viena procedūra, kuri įkelia dokumentą, išvardija jo scenarijus ir jų kūnus, išvardija Launch ir URI tikslus, praneša apie parašo MDP lygį, pažymi priedus bei XFA ir įrašo radinius į žurnalą. Ji nieko neatvaizduoja, todėl yra pigi ir negali būti apgauta rodant priešišką puslapio turinį. Išvestis yra plokščias, žmogui skaitomas įrašas, kurį recenzentas arba tolimesnė taisyklė gali veikti
Forma, kuri gerai veikia praktikoje, yra surinkti kiekvieną radinį kaip eilutę, pažymėti tikrai rizikingus priešdėliu, kad jie būtų surūšiuoti į peržiūros eilės viršų, ir išsaugoti visą failą šalia originalo. Dokumentas be scenarijų, be paleidimo veiksmų, be priedų, be XFA ir be parašo arba su nuosekliu sertifikavimu praeina tyliai. Dokumentas, kuris vienu metu užkabina kelias vėliavėles, yra tas, kurį žmogus turėtų pamatyti prieš bet kuriam vėlesniam etapui jį atidarant. Auditas nepriima sprendimo dėl pasitikėjimo už jus. Jis užtikrina, kad sprendimas būtų priimtas informuotai, o ne aklai