đš Cette Ă©dition est relativement longue, votre boĂźte mail risque de la tronquer. Je vous conseille de cliquer sur le titre ci-dessus pour lâouvrir dans votre navigateur web. âïž
Temps de lecture : 10 minutes
Hello les petits Biscuits !
Bienvenue sur la 27Úme édition de Ruby Biscuit.
Vous ĂȘtes maintenant 540 abonnĂ©s đ„ł
Maintenant Ruby biscuit, câest aussi votre meilleur alliĂ© pour recruter des devs Ruby !
Si vous nâavez pas encore rejoint le club, RDV sur https://recrutement.rubybiscuit.fr
Bonne lecture.
En finir avec les PDF infectés au js
En mai 2024, une faille majeure a été découverte dans la bibliothÚque PDF.js, utilisée par de trÚs nombreux iframes pour permettre la visualisation et la prévisualisation de fichiers PDF dans une page web. Cette faille permettait d'injecter du code javascript dans une FontMatrix qui n'était pas censée en accueillir et ensuite de s'assurer de son exécution lors de l'interprétation du fichier par un lecteur. Ce type de faille est une porte d'entrée pour des attaques de type XSS, bien qu'elle n'en permette pas une seule.
Le cross-site scripting (abrégé XSS) est un type de faille de sécurité des sites web permettant d'injecter du contenu dans une page, provoquant ainsi des actions sur les navigateurs web visitant la page. Il est par exemple possible de voler la session en récupérant les cookies.
Les CVE concernant l'exécution arbitraire de javascript via des fichiers PDF dans des pages web sont nombreuses, et il y a aussi des multitudes de formes d'exécution de javascript volontairement permises par le format PDF. Celles-ci sont généralement bloquées par le navigateur mais il y a des exceptions.
Aujourd'hui nous allons apprendre comment nous en débarrasser. AprÚs avoir lu cet article, vous saurez comment implémenter un sanitizer en ruby qui vous protÚge durablement de la CVE de mai 2024 et d'autres types d'injections au js. Vous serez également solidement armés pour réagir efficacement et rapidement à la prochaine CVE de ce style et capables de :
Comprendre sur quoi se base la CVE
Adapter votre sanitizer
Créer vos propres fichiers infectés pour le tester
I - Introduction, les actions javascripts et les fontmatrix
Entre la crĂ©ation du format PDF en 1992 oĂč seulement 12 types d'objets Ă©taient autorisĂ©s et sa derniĂšre mise Ă jour en 2009 qui en compte plus de 70, de nombreuses fonctionnalitĂ©s ont Ă©tĂ© ajoutĂ©es. Et avec elles beaucoup de vulnĂ©rabilitĂ©s.
Une partie non nĂ©gligeable de ces vulnĂ©rabilitĂ©s et dangers ont Ă©tĂ© introduits en mĂȘme temps que les scripts javascript.
La plupart de ces scripts ne seront pas malveillants : widgets, liens dynamiques, actions sympathiques et variées au clic d'un bouton ou dÚs l'ouverture d'un fichier : le javascript a été admis pour améliorer et enrichir l'expérience utilisateur.
D'autres le seront probablement, c'est le cas des PDF écrits pour contenir du javascript de sorte à exploiter la CVE de mai 2024.
Je vais vous montrer comment écrire un script ruby qui sanitise les fichiers PDF pour leur enlever les éléments javascripts légitimes ou illégitimes.
Mais avant il y a quelques pré-requis nécessaires :
Une compréhension globale du format PDF
Une connaissance des emplacements et des formes que le javascript peut occuper dans un PDF
Des fichiers PDF "infectés" pour tester nos scripts
Nous allons obtenir tout cela en créant ensemble et de toute piÚce un fichier PDF infecté au javascript (inoffensif bien sûr) !
II - Créons un fichier corrompu
Nous allons dans cette partie écrire à la main, de A à Z, un fichier PDF. Le javascript pouvant se trouver dans de trÚs nombreuses sections d'un PDF, je montrerai pour chaque section dans un premier temps la version saine et dépourvue de javascript, puis la version infectée.
Cependant, il est impossible de présenter l'ensemble des objets liés à des actions javascript en un seul article tant ceux-ci sont nombreux. La norme PDF 32000-1:2008 ou PDF 1.7 décrit de façon exhaustive ces objets si cela vous intéresse (page 422).
Pour chaque section, les fragments de code PDF en version saine présentés dans l'article, une fois assemblés, formeront un fichier PDF valide et non corrompu.
Si vous souhaitez crĂ©er vous mĂȘme votre PDF infectĂ©, il faudra adapter les offsets de la table des rĂ©fĂ©rences (je vous expliquerai tout ça en dĂ©tail le moment venu).
Speedrun
Si vous souhaitez speedrun la lecture de cet article, et n'en sortir qu'un script de sanitisation et des fichiers de payload pour le tester, vous pouvez sauter directement Ă la partie suivante oĂč vous trouverez les deux.
Je ne vous conseille cependant de ne pas faire cela, l'intĂ©rĂȘt de coder votre propre sanitizer Ă©tant de pouvoir l'adapter rapidement Ă toute nouvelle CVE permettant une exĂ©cution de javascript dans un pdf via des moyens dĂ©tournĂ©s. Cela peut ĂȘtre plus compliquĂ© sans une vague comprĂ©hension du format PDF et des objets javascript.
Le format général
Une façon de se représenter un fichier PDF serait de dire qu'il contient globalement 3 sections :
L'en-tĂȘte qui annonce le format et la version (trĂšs court)
Le corps qui abrite le contenu (ou charge utile) du PDF
La fin de fichier qui regroupe la table des références, le trailer et le marqueur de fin de fichier : des éléments utiles à la bonne interprétation du document mais n'ajoutant généralement pas de contenu à proprement parler.
Nous allons remplir ce guide progressivement dans cette partie.
En tĂȘte
Un PDF commence directement par une section d'en-tĂȘte. L'en tĂȘte prĂ©cise le format : PDF, la version : 1.3 et quelques caractĂšres binaires pour annoncer que le fichier sera encodĂ© en binaire.
Le fichier que nous allons écrire étant constitué de trÚs peu d'objets, il sera valide et lisible avec n'importe quelle version et par n'importe quel lecteur PDF (si vous souhaitez écrire la version contenant du JS à la main, utilisez une version récente comme la 1.8 ou au minimum postérieure à 1.2).
Corps
Le corps regroupe tout le contenu d'un PDF : c'est une suite d'objets indirects. Ces objets peuvent ĂȘtre de types variĂ©s. Cependant certains types d'objets sont nĂ©cessaires Ă l'Ă©laboration d'un PDF valide minimal.
Afin de comprendre le format du corps, quelques définitions s'imposent à ce sujet.
Le corps d'un fichier PDF est constitué d'une série d'objets indirects.
Les objets indirects sont composés d'un numéro d'objet (un identifiant), d'un numéro de génération (qui commence à 0 et s'incrémente si l'objet est dupliqué).
Puis obj [Contenu objet] endobj
1 0 obj
[CONTENT]
endobj
Un objet indirect peut ĂȘtre vu comme un contenant pour un ou plusieurs objet directs.
Les objets directs (ou objets) sont des structures de donnĂ©es basiques, qui peuvent souvent ĂȘtre directement traduites vers un type d'objet primitif en Ruby (tableaux, boolĂ©ens, dictionnaires, chaĂźne de caractĂšres, entiers, objet nul, ...).
La plupart des objets directs de ce document seront des dictionnaires.
Les dictionnaires sont des séquences de clés et valeurs entourés de << et >>. Chaque clés type sa valeur. Les clés sont toutes des names objects (au format /Name).
Les éléments simples que vous voyez à l'écran lorsque vous visualisez un PDF sont en fait constitués d'une multitudes d'objets qui sont imbriqués et/ou qui se référencent. Les dictionnaires par exemple sont souvent imbriqués à de nombreux niveaux.
Les objets indirects peuvent se référencer les uns les autres. Une référence est un type d'objet. Elle se compose des numéros d'objet et de génération de l'objet référencé suivis du caractÚre R.
Ainsi, un objet indirect défini de la façon suivante :
2 0 obj
[Contenu]
endobj
Pourra ĂȘtre rĂ©fĂ©rencĂ© (avant ou aprĂšs sa dĂ©finition dans le document) par : 2 0 R.
Ne pas confondre objet direct et indirect
Dans un fichier PDF, les objets peuvent ĂȘtre reprĂ©sentĂ©s de maniĂšre directe ou indirecte. Un objet direct est intĂ©grĂ© directement dans le document et est souvent trouvĂ© comme valeur d'une clĂ© dans un dictionnaire ou comme Ă©lĂ©ment dans un tableau. Il est accessible immĂ©diatement sans rĂ©fĂ©rence externe. En revanche, un objet indirect est rĂ©fĂ©rencĂ© par un identifiant unique (composĂ© d'un numĂ©ro d'objet et d'un numĂ©ro de gĂ©nĂ©ration), ce qui permet au lecteur PDF de retrouver sa valeur en consultant dâautres parties du fichier. Les objets indirects facilitent la rĂ©utilisation et l'organisation des donnĂ©es dans un PDF en permettant de pointer vers un objet unique depuis plusieurs endroits.
Passons Ă la pratique.
Le catalogue
Le premier objet indirect contenu dans le corps est ici le catalogue. C'est l'objet racine du document. C'est un dictionnaire qui référence l'objet liste des pages.
Il peut contenir d'autres types d'objets. Il peut notamment contenir des actions javascript légitimes ou non.
Les actions javascript
Une action javascript est en rĂ©alitĂ© une sĂ©rie d'objets et peut prendre de multiples formes. Ici, action javascript dĂ©signe les diffĂ©rents types d'objets qui rĂ©fĂ©rencent une exĂ©cution de javascript (cĂŽtĂ© navigateur) conforme au format PDF et Ă son contenu. Ils correspondent Ă des utilisations non dĂ©tournĂ©es de diffĂ©rents types d'objets. Ces objets peuvent ĂȘtre imbriquĂ©s.
Elles peuvent ĂȘtre contenues dans un dictionnaire de type /Action ou /OpenAction. La premiĂšre est gĂ©nĂ©ralement attachĂ©e Ă une interaction de l'utilisateur comme un clic, la seconde s'exĂ©cute dĂšs l'ouverture du document (pratique).
Ces objets peuvent aussi ĂȘtre dĂ©finis indĂ©pendamment, les deux premiers sont alors simplement des dictionnaires qui rĂ©fĂ©rencent les suivants. L'objet /JS est contenu dans un objet indirect et contient directement le code Ă exĂ©cuter.
Retour au catalogue
Le catalogue peut contenir des actions javascript.
Ou les référencer.
Liste des pages
La liste des pages est un dictionnaire qui liste les références des pages (ses enfants) dans un tableau. Ici le tableau contient une seule entrée puisque le PDF que l'on écrit contient une seule page.
Les tableaux sont ouverts et fermés par [ et ], les différentes entrées sont séparées par des espaces.
S'il y avait plusieurs pages, les références seraient séparées par un simple espace : [ 3 0 R 4 0 R ]...
Page 1
Chaque page définit dans un dictionnaire Page les ressources nécessaires à son affichage : une police. La page référence aussi son contenu : ici l'objet identifié par la référence 4 0 R.
On peut y trouver des scripts ou des références à des scripts
Les polices peuvent ĂȘtre entiĂšrement dĂ©finies dans le PDF ou utiliser celles installĂ©es sur les ordinateurs (dans le premier cas, cela pourrait causer des problĂšmes d'affichage selon le lecteur)
Le stream
Dans un fichier PDF, un stream est un type dâobjet utilisĂ© pour stocker des donnĂ©es volumineuses ou complexes, comme des images, du texte formatĂ© ou des informations graphiques. Il est dĂ©limitĂ© par les mots clĂ©s stream
et endstream
. Les streams permettent dâinclure des contenus plus longs ou compressĂ©s dans le fichier PDF, rendant ce type de donnĂ©es plus facile Ă gĂ©rer et Ă stocker de maniĂšre efficace.
Un stream commence généralement par une déclaration de ses propriétés dans un dictionnaire précédant le mot stream
. Ce dictionnaire contient des informations essentielles, comme la longueur du stream (en octets) et, le cas échéant, la méthode de compression utilisée (par exemple, FlateDecode pour une compression zlib/deflate).
Voici un exemple simplifiĂ© dâun objet stream dans un fichier PDF (ici, aucune compression n'a Ă©tĂ© appliquĂ©e) :
Cet objet stream contient simplement du texte formaté à afficher.
Le texte est inséré entre les tags BT (Begin Text) et ET (End Text).
La premiÚre lignée définit la police : F1 (définie plus tÎt) et la taille : 100 grùce au tag Tf (text font).
La deuxiÚme ligne indique les coordonnées grùce au tag de dessin Td (text draw).
La derniÚre affiche le texte grùce à l'opérateur Tj (show text).
Les FontMatrix
Une FontMatrix est une matrice de transformation associée aux polices de caractÚres. Elle permet d'appliquer des transformations géométriques comme la mise à l'échelle, la rotation, la translation ou le cisaillement aux glyphes (caractÚres) d'une police avant leur affichage. Dans une FontMatrix, six valeurs numériques définissent ces transformations, offrant un contrÎle précis sur la présentation des textes.
Dans un fichier PDF, les FontMatrix sont généralement des entrées dans un dictionnaire qui définit une police et un formatage.
La CVE-2024-4367
La faille dĂ©couverte en mai 2024 exploite une faiblesse dans la gestion des FontMatrix par la bibliothĂšque PDF.js, permettant lâinjection et l'exĂ©cution de code JavaScript malveillant.
Les valeurs contenues dans la FontMatrix étaient interprétées par PDF.js et évaluées pour afficher correctement la police. Si elles étaient remplacées par du code javascript, celui-ci était donc évalué.
Ce cas de figure sera traitĂ© de façon lĂ©gĂšrement diffĂ©rente par le sanitizer : contrairement aux autres objets Ă©voquĂ©s permettant des actions javascript, les FontMatrix n'ont en thĂ©orie, aucun rapport avec l'exĂ©cution de javascript. Elles peuvent donc ĂȘtre prĂ©sentes dans de nombreux PDF sans qu'il ne soit pertinent de les supprimer.
Au lieu de retirer toutes les FontMatrix, nous testerons qu'elles sont au format correct (6 chiffres). Si elles ne le sont pas (si elles contiennent des caractÚres non numériques), elles seront retirées.
Fin de fichier
Le reste d'un fichier PDF contient des objets qui sont utiles pour permettre la lecture du fichier.
La table des références
La table des références (ou xref table) dans un fichier PDF est une structure qui répertorie les positions de tous les objets indirects en indiquant leurs décalages en octets par rapport au début du fichier.
La table des références est annoncée par le mot xref et doit commencer par une ligne contenant deux nombres séparés par un espace, représentant le numéro d'objet du premier objet de cette sous-section et le nombre d'entrées dans la sous-section.
xref
0 5
Ici, la table des références contient les objets indirects de 0 à 4.
Chaque ligne de la table des références fait 20 octets et contient :
nnnnnnnnnn ggggg m eol
nnnnnnnnnn
: l'offset en octet sur 10 chiffres de l'objet à partir du début du fichierggggg
: le numéro de génération de l'objet sur 5 chiffres (à 65535 pour un objet libre)m
: un mot clé sur une lettre qui indique si l'objet est libre (f) ou utilisé (n)eol
: un marqueur de fin de ligne sur deux caractĂšres
La table des références permet au lecteur PDF de localiser rapidement chaque objet sans devoir analyser l'ensemble du fichier. Placée vers la fin du document, cette table est essentielle pour que le lecteur puisse interpréter le document correctement et efficacement.
La table commence par un objet nul. Cet objet commence à l'offset 0. Comme il n'est pas utilisé son numéro de génération est à 65535 par convention, et le mot clé est f.
Les objets suivants sont les différents objets définis plus tÎt, on ajoute pour chacun leur offset en octet depuis le début du fichier, leur numéro de génération, puis un n pour annoncé qu'ils sont utilisés.
Attention : Bien qu'elle s'appelle table des références, c'est techniquement une table de pointeurs.
Dans un PDF, une référence et un pointeur jouent des rÎles distincts pour organiser et structurer les données.
Une référence est utilisée pour relier les objets entre eux au sein du fichier. Par exemple, un objet peut contenir une référence vers un autre objet indirect (identifié par un numéro d'objet et de génération, suivi de "R"), indiquant que son contenu est à rechercher ailleurs dans le document.
Un pointeur, quant à lui, indique une position précise dans le fichier PDF. Il est souvent employé dans la table des références (ou xref table) et dans le trailer pour diriger le lecteur PDF vers le début de chaque objet indirect. Le pointeur aide le lecteur à retrouver rapidement les éléments sans avoir à parcourir tout le fichier.
Ainsi, la référence est une relation logique entre objets, tandis que le pointeur est une adresse précise dans le fichier.
Le trailer
Les PDF doivent ĂȘtre lus en partant de la fin, c'est notamment le cas parce que le trailer, derniĂšre section d'un fichier PDF, est le point d'entrĂ©e pour les lecteurs : il permet de trouver rapidement la table des rĂ©fĂ©rences et l'emplacement de certains objets spĂ©ciaux.
Le trailer est un dictionnaire qui contient au moins deux entrées indispensables :
Une paire clé valeur /Root qui référence le catalogue.
Une paire clé valeur /Size qui annonce la taille de la table des références.
Enfin, le trailer contient également un pointeur vers la table des référence : le point d'entrée pour le lecteur qui interprétera le fichier.
Le marqueur de fin de fichier
La derniĂšre ligne du fichier doit contenir uniquement le marqueur de fin de fichier, %%EOF.
Résumons
Et voilà ! Nous avons désormais construit un PDF infecté au js de toute piÚce. Mais ça fait beaucoup d'informations. Voici quelques schémas pour résumer les différents objets et les relations qui les lient.
Les références
Les pointeurs
D'autres objets divers
Si de nombreux types d'objets peuvent ĂȘtre le point d'entrĂ©e Ă l'exĂ©cution de javascript, la plupart auront besoin d'un objet /JS qui contient le code. Supprimer cet objet s'il est prĂ©sent permet donc de neutraliser de nombreux chemins d'exĂ©cution.
III - Maintenant, on nettoie tout ça
Notre PDF corrompu est prĂȘt Ă servir de payload pour tester l'algorithme de nettoyage que nous allons coder.
L'algorithme est plutĂŽt simple Ă rĂ©aliser : on fait la liste des types d'objets qui peuvent contenir du JS susceptible d'ĂȘtre exĂ©cutĂ© et on les "dĂ©sactive".
Donc, si on résume, deux cas de figure ont été abordés dans cet article :
Ceux qui sont normalement désactivés 99% du temps et qui sont conformes à ce qui est prévu par le format : ceux-ci reposent généralement sur un objet /JS. Supprimer la paire clé-valeur /JS - code
Les FontMatrix, dont on peut vérifier simplement qu'elles sont au format attendu et les supprimer si ce n'est pas le cas
HexaPDF
J'ai fait le choix de la gem HexaPDF pour coder mon sanitizer. Celle-ci est trÚs bien codée et trÚs utile pour les manipulations de PDF.
J'utilise pour l'exemple la gem Stringio pour gérer la sortie du document traité en mémoire plutÎt que d'écrire directement sur le disque. C'est un choix qui m'a permis de simplifier l'intégration de ce sanitizer à mon application Rails.
Je présente ici un squelette simple pour le sanitizer, comme un script ruby indépendant afin de présenter la logique. Je vous laisse décider des détails d'implémentation.
On commence par importer les dépendances :
require 'hexapdf'
require 'stringio'
Puis, on crée une classe qui servira de sanitizer, avec un peu de setup :
class Sanitizer
attr_reader :file_to_sanitize, :result
def initialize(file_to_sanitize)
@file_to_sanitize = file_to_sanitize
@result = { success: false, edited: false }
end
def call
open_pdf
sanitize_file
save_pdf
@result
end
def open_pdf
unless @file_to_sanitize && File.exist?(@file_to_sanitize) && File.extname(@file_to_sanitize).downcase == '.pdf'
print("File #{@file_to_sanitize} not found or not a PDF file\n")
exit(1)
end
@file = HexaPDF::Document.open(@file_to_sanitize)
end
Parcours du fichier
Il est ensuite possible de parcourir l'ensemble des objets contenus dans le PDF trĂšs simplement :
On vérifie si les objets rencontrés sont des dictionnaires, si c'est le cas, on appelle une fonction de nettoyage sur l'objet. HexaPDF gÚre de nombreux aspects de la logique de suppression : création d'un fichier en mémoire sans les objets supprimés, ajustement des offsets dans la table des références, etc. Ce qui permet de supprimer simplement des objets sans rentre le PDF invalide.
def sanitize_file
@file.each do |obj|
next unless obj.value.is_a?(Hash)
sanitize_object(obj)
end
end
La méthode sanitize_object(obj)
délÚgue ensuite la responsabilité d'analyser et nettoyer les objets dictionnaires rencontrés aux méthodes appropriées :
Les FontMatrix corrompues (
remove_font_matrix
)Les actions javascript, notamment l'objet /JS (
remove_js
)
On écrira une derniÚre fonction qui parcourt récursivement les éventuels dictionnaires imbriqués pour s'assurer de nettoyer l'ensemble du document.
def sanitize_object(obj)
remove_font_matrix(obj) if obj[:Type] == :Font && (obj.key?(:FontMatrix) && corrupt_font_matrix?(obj))
remove_js(obj) if obj.key?(:JS)
clean_nested_dictionary(obj) if obj.is_a?(HexaPDF::Dictionary)
end
Les actions javascript
def remove_js(obj)
print("Removing JS from object #{obj.oid}\n")
obj.delete(:JS)
@result[:edited] = true
end
Les FontMatrix
Une premiÚre méthode cherche la façon dont la FontMatrix est insérée dans le dictionnaire de police (celle ci peut varier) puis on vérifie que la matrice ne contient que des valeurs numériques.
def corrupt_font_matrix?(obj)
font_matrix = obj[:FontMatrix].respond_to?(:value) ? obj[:FontMatrix].value : obj[:FontMatrix]
font_matrix.any? { |n| !n.is_a?(Numeric) }
end
Si ce n'est pas le cas, on supprime complĂštement la matrice : puisqu'elle est corrompue, elle n'est pas utile.
def remove_font_matrix(obj)
print("Removing corrupt FontMatrix from object #{obj.oid}\n")
obj.delete(:FontMatrix)
@result[:edited] = true
end
Le cas des dictionnaires imbriqués
Afin de nettoyer le code javascript mĂȘme s'il est contenu dans une sĂ©rie de dictionnaires imbriquĂ©s, on Ă©crit simplement une mĂ©thode rĂ©cursive qui vĂ©rifie et nettoie les entrĂ©es d'un dictionnaires, et le contenu des entrĂ©es qui sont des tableaux.
def clean_nested_dictionary(dictionary)
return unless dictionary.is_a?(HexaPDF::Dictionary)
dictionary.each do |key, value|
if value.is_a?(HexaPDF::Dictionary)
sanitize_object(value)
clean_nested_dictionary(value)
end
next unless value.is_a?(Array)
value.each do |v|
next unless v.is_a?(HexaPDF::Dictionary)
sanitize_object(v)
clean_nested_dictionary(v)
end
end
end
Le nettoyage est terminé !
On enregistre le fichier PDF s'il a été modifié, et on met à jour le hash de résultat du sanitizer.
def save_pdf
return unless @result[:edited]
@io = StringIO.new
@file.write(@io, optimize: false, validate: false)
@io.rewind
@result[:output_data] = @io.string
@result[:success] = true
end
Je fais un petit main rapidement pour tester le sanitizer :
if __FILE__ == $0
if ARGV.empty?
puts 'Please provide the path to a PDF file to sanitize.'
exit
end
file_to_sanitize = ARGV[0]
sanitize = Sanitizer.new(file_to_sanitize)
result = sanitize.call
if result[:success]
File.open('sanitized_output.pdf', 'wb') { |f| f.write(result[:output_data]) }
puts "PDF sanitized successfully and saved as 'sanitized_output.pdf'."
else
puts 'PDF sanitization failed.'
end
end
Je lance ça sur un fichier PDF contenant des actions JS et une FontMatrix corrompue :
Et j'obtiens un fichier PDF qui ne contient plus aucun code javascript. Il existe des reliques, comme cet objet indirect Javascript :
9 0 obj
<<
/S/JavaScript
>>
endobj
Ce pendant, la section /JS avec le code associé à l'action JavaScript ont été supprimés, il n'y a donc plus aucun risque d'exécution de code.
Quelques remarques pour la fin
L'exemple que nous avons vu ici est un cas de PDF extrĂȘmement simple. En rĂ©alitĂ© un simple Hello World gĂ©nĂ©rĂ© par un gĂ©nĂ©rateur de PDF moyen serait bien plus lourd et constituĂ© de nombreux objets plus complexes.
Par exemple, nous avons fait appel dans notre document Ă la police Arial installĂ©e sur votre ordinateur, mais un Hello World en Arial gĂ©nĂ©rĂ© par google docs contiendrait l'intĂ©gralitĂ© de la police afin de s'assurer que le PDF soit visualisĂ© de façon exacte par n'importe quel ordinateur, mĂȘme s'il n'a pas cette police installĂ©e.
Le format PDF permet dâinclure de nombreuses formes d'actions JavaScript qui n'ont pu ĂȘtre prĂ©sentĂ©es en totalitĂ© dans cet article. Il est important de noter que ces actions sont destinĂ©es Ă ĂȘtre interprĂ©tĂ©es par des lecteurs PDF spĂ©cialisĂ©s (comme Adobe Acrobat).
Les navigateurs web ne permettent gĂ©nĂ©ralement pas cette exĂ©cution, et lâinterprĂ©tation est propre Ă chaque bibliothĂšque ou lecteur de PDF.
Liens utiles :
A propos de cet article :
Le format PDF :
Let's write a pdf file : vulgarisation du format et de la syntaxe
Norme 32000-1:2008 ou PDF 1.7 : explications détaillées sur le format PDF
Les exploitations de PDF :
PDF files payload for pentesting : github avec différents fichiers PDF contenant du JS
Portable Data exFiltration: XSS for PDFs : aller plus loin sur les attaques XSS et les PDF
â Ines