Ce qui pourrait être un moyen de récupérer une liste de tous les caractères d'une classe de caractères donnée (comme blank
, alpha
, digit
...) dans la configuration locale.
Par exemple,
LC_ALL=en_GB.UTF-8 that-command blank
idéalement, sur mon système Debian, afficherait quelque chose comme:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
e1 9a 80 U+1680 OGHAM SPACE MARK
e1 a0 8e U+180E MONGOLIAN VOWEL SEPARATOR
e2 80 80 U+2000 EN QUAD
e2 80 81 U+2001 EM QUAD
e2 80 82 U+2002 EN SPACE
e2 80 83 U+2003 EM SPACE
e2 80 84 U+2004 THREE-PER-EM SPACE
e2 80 85 U+2005 FOUR-PER-EM SPACE
e2 80 86 U+2006 SIX-PER-EM SPACE
e2 80 88 U+2008 PUNCTUATION SPACE
e2 80 89 U+2009 THIN SPACE
e2 80 8a U+200A HAIR SPACE
e2 81 9f U+205F MEDIUM MATHEMATICAL SPACE
e3 80 80 U+3000 IDEOGRAPHIC SPACE
Et dans les paramètres régionaux C pourrait afficher quelque chose comme:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Autrement dit, la représentation du caractère dans les paramètres régionaux en termes de tableaux d'octets (comme UTF-8 dans le premier exemple et octet unique dans le second), le point de code de caractère Unicode équivalent et une description.
Le contexte
(modifier) Maintenant que la vulnérabilité a été corrigée et divulguée depuis longtemps, je peux ajouter un peu de contexte.
J'ai posé cette question au moment où j'enquêtais CVE 2014-0475 . glibc
avait un bug en ce qu'il permettait à l'utilisateur d'utiliser des paramètres régionaux comme LC_ALL=../../../../tmp/evil-locale
ceux-ci sont résolus par rapport au chemin de recherche standard des paramètres régionaux du système et permettait ainsi d'utiliser n'importe quel fichier comme définition de paramètres régionaux.
Je pourrais créer un environnement local voyous par exemple avec un seul octet par jeu de caractères où la plupart des caractères sauf s
, h
et quelques autres étaient considérés comme des blancs et qui seraient bash
exécutés sh
lors de l'analyse d'un /etc/bash.bashrc
fichier Debian typique (et qui pourrait être utilisé pour obtenir un accès shell sur un git
le serveur d'hébergement par exemple fourni bash
est utilisé comme shell de connexion de l' git
utilisateur du serveur et que le ssh
serveur accepte LC_*
/ LANG
variables et que l'attaquant peut télécharger des fichiers sur le serveur).
Maintenant, si jamais je trouvais une LC_CTYPE
(définition locale compilée) dans /tmp/evil
, comment pourrais-je savoir que c'était une voyou et de quelle manière.
Mon objectif est donc de décompiler ces définitions de paramètres régionaux et, dans le cas contraire, de savoir au moins quel caractère (ainsi que leur codage) se trouvent dans une classe de caractères donnée.
Donc, avec cela à l'esprit:
- Les solutions qui regardent les fichiers source pour les paramètres régionaux (les définitions de paramètres régionaux comme celles de
/usr/share/i18n/locale
Debian) ne sont d'aucune utilité dans mon cas. - Les propriétés des caractères Unicode ne sont pas pertinentes. Je me soucie seulement de ce que dit la locale. Sur un système Debian, même entre deux locales du système UTF-8, et encore moins des locales escrocs, la liste des caractères d'une classe peut être différente.
- Des outils comme
recode
,python
ouperl
qui effectuent la conversion d'octet / multi-octet vers / à partir de caractères ne peuvent pas être utilisés car ils peuvent (et en pratique le font) effectuer la conversion d'une manière différente de la locale.
la source
/usr/share/i18n/locales/i18n
... qui bien sûr provient en grande partie de la base de données de caractères Unicode. Bien sûr, ce serait bien d'avoir une commandelocale
(au moins celui de GNU) récupère la plupart des informations stockées dans de nombreuses catégories, les choses ne sont pas les plus importantes dans LC_CTYPE et LC_COLLATE. Je me demande s'il y a une API cachée pour récupérer ces informations ou décompiler les informations locales.recode
etuconv
peut vous donner ce que vous dites que vous recherchez. Peut-être même justeluit
etod
je suppose ...perl
du tout, je pense.LC_CTYPE
avecod -A n -t c <LC_CTYPE | tsort
probablement que vous l'avez déjà essayé, mais je n'en avais jamais entendu parler auparavant et je lisaisinfo
et cela m'a rappelé cela - et cela semble fonctionner. Il y en a aussiptx
mais je pense que c'est moins pertinent. Quoi qu'il en soit, si vous ne l'avez pas essayé et décidez de le faire - avertissement juste - cela nécessite un peu de patience. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Réponses:
SOLUTION FINALE POSSIBLE
J'ai donc pris toutes les informations ci-dessous et trouvé ceci:
REMARQUE :
J'utilise
od
comme filtre final ci-dessus de préférence et parce que je sais que je ne travaillerai pas avec des caractères multi-octets, qu'il ne gérera pas correctement.recode u2..dump
va à la fois générer une sortie plus semblable à celle spécifiée dans la question et gérer correctement les caractères larges.PRODUCTION
API DU PROGRAMMATEUR
Comme je le démontre ci-dessous,
recode
vous fournira votre carte de personnage complète. Selon son manuel, il le fait d'abord en fonction de la valeur actuelle de laDEFAULT_CHARSET
variable d'environnement, ou, à défaut, il fonctionne exactement comme vous le spécifiez:Il convient également de noter
recode
qu'il s'agit d'une API :#include <recode.h>
Pour une comparaison de chaînes conviviale à l'échelle internationale Les normes
POSIX
etC
définissent lastrcoll()
fonction:Voici un exemple distinct de son utilisation:
En ce qui concerne les
POSIX
classes de personnages, vous avez déjà noté que vous avez utilisé l'C
API pour les trouver. Pour les caractères et les classes Unicode, vous pouvez utiliser le jeu de caractèresrecode's
dump-with-names pour obtenir la sortie souhaitée. De son manuel à nouveau :En utilisant une syntaxe similaire à celle ci-dessus combinée avec son jeu de données de test inclus, je peux obtenir ma propre carte de caractères avec:
PRODUCTION
Mais pour les personnages communs,
recode
n'est apparemment pas nécessaire. Cela devrait vous donner des caractères nommés pour tout dans un jeu de caractères de 128 octets:PRODUCTION
Bien sûr, seuls 128 octets sont représentés, mais c'est parce que mes paramètres régionaux, utf-8 charmaps ou non, utilisent le jeu de caractères ASCII et rien de plus. C'est tout ce que je reçois. Si je l'exécutais sans le
luit
filtrer,od
je le retournerais et imprimerais à nouveau la même carte jusqu'à\0400.
Il existe cependant deux problèmes majeurs avec la méthode ci-dessus. Il y a d'abord l'ordre de classement du système - pour les paramètres régionaux non ASCII, les valeurs de morsure pour les jeux de caractères ne sont pas simplement in
seq
uence, ce qui, comme je pense, est probablement au cœur du problème que vous essayez de résoudre.Eh bien, la
tr's man
page GNU indique qu'elle étendra les[:upper:]
[:lower:]
classes dans l'ordre - mais ce n'est pas beaucoup.J'imagine qu'une solution lourde pourrait être implémentée avec
sort
mais ce serait un outil plutôt lourd pour une API de programmation backend.recode
fera cette chose correctement, mais vous ne sembliez pas trop amoureux du programme l'autre jour. Peut-être que les modifications d'aujourd'hui apporteront une lumière plus amicale ou non.GNU propose également la
gettext
bibliothèque de fonctions, et il semble pouvoir résoudre ce problème au moins pour leLC_MESSAGES
contexte:Vous pouvez également utiliser des catégories de caractères Unicode natives , qui sont indépendantes de la langue et renoncer complètement aux classes POSIX, ou peut-être faire appel aux premières pour vous fournir suffisamment d'informations pour définir les dernières.
Le même site Web qui a fourni les informations ci - dessus discute aussi
Tcl
propre d » Posix compatibles avec la norme mise en œuvre de regex qui pourrait être encore une autre façon d'atteindre votre objectif.Enfin, parmi les solutions, je proposerai que vous puissiez interroger le
LC_COLLATE
fichier lui-même pour la table de caractères système complète et en ordre . Cela peut ne pas sembler facile à faire, mais j'ai obtenu un certain succès avec ce qui suit après l'avoir compilélocaledef
comme illustré ci-dessous:Il est, certes, actuellement imparfait, mais j'espère que cela démontre au moins la possibilité.
AU PREMIER BLUSH
Cela ne ressemblait vraiment pas à beaucoup, mais j'ai commencé à remarquer des
copy
commandes dans la liste. Le fichier ci-dessus semblecopy
dans "en_US" par exemple, et un autre très gros qu'il semble qu'ils partagent tous dans une certaine mesure estiso_14651_t1_common
.C'est assez gros:
Voici l'intro de
/usr/share/i18n/locales/POSIX
:...
Vous pouvez le faire
grep
bien sûr, mais vous pourriez simplement:Au lieu. Vous obtiendriez quelque chose comme ceci:
... ET PLUS
Il existe également un
luit
terminal depty
traduction UTF-8 , je suppose, qui sert d'intermédiaire pour les XTerms sans prise en charge UTF-8. Il gère de nombreux commutateurs, tels que la consignation de tous les octets convertis dans un fichier ou-c
comme un simple|pipe
filtre.Je n'ai jamais réalisé qu'il y avait tant de choses à cela - les paramètres régionaux et les cartes de personnages et tout cela. C'est apparemment un gros problème mais je suppose que tout se passe dans les coulisses. Il existe - au moins sur mon système - quelques centaines de
man 3
résultats liés aux recherches liées aux paramètres régionaux.Et il y a aussi:
Cela durera très longtemps.
Les
Xlib
fonctions gèrent cela tout le temps - fontluit
partie de ce package.Les
Tcl_uni...
fonctions pourraient également s'avérer utiles.juste un peu d'
<tab>
achèvement et deman
recherches et j'ai beaucoup appris sur ce sujet.Avec
localedef
- vous pouvez compiler lelocales
dans votreI18N
répertoire. La sortie est géniale et pas extraordinairement utile - pas ducharmaps
tout - mais vous pouvez obtenir le format brut comme vous l'avez spécifié ci-dessus comme je l'ai fait:Ensuite, avec
od
vous pouvez le lire - octets et chaînes:Bien qu'il soit loin de gagner un concours de beauté, c'est une sortie utilisable. Et
od
est aussi configurable que vous le souhaitez, bien sûr.Je suppose que j'ai également oublié ces derniers:
Je les ai probablement oubliés parce que je ne pouvais pas les faire travailler. Je n'utilise jamais
Perl
et je ne sais pas comment charger un module correctement je suppose. Mais lesman
pages sont plutôt jolies. En tout cas, quelque chose me dit que vous trouverez qu'il est au moins un peu moins difficile d'appeler un module Perl que moi. Et, encore une fois, ils étaient déjà sur mon ordinateur - et je n'utilise même jamais Perl. Il y a aussi notamment quelquesI18N
- uns que j'ai fait avec mélancolie en sachant très bien que je ne les ferais pas travailler non plus.la source
i18n
) qui peuvent ou non avoir été utilisés pour générer les paramètres régionaux que j'utilise actuellement. Les informations sur les paramètres régionaux proviennent probablement de/usr/lib/locale/locale-archive
ou/some/dir/LC_CTYPE
, et c'est la partie pertinente à mes paramètres régionaux qui est stockée dans les fichiers que je recherche.LC_STUFF
de l'archive aveclocaledef
- il le fait aussi. Je peux aussi faire une démonstration, je suppose. Vous pouvez également voir cela et à peu près tout le reste avecstrings
ouod
ou tout le reste. Je l'ai fait de toute façon. Mais au fait - cecharmaps
sont les paramètres régionaux que vous utilisez actuellement - et enlocaledef
feront également rapport. C'est aussi ce quirecode
fait aussi.od,
recode
,uconv
et le reste. Mais c'était mon erreur - ce n'est paslocaledef
cela qui l'extrait, c'estrecode
cette volonté. Vous devez vérifierinfo recode
- et en plus de larecode
commande de table que je montre, il y a à peu près la même chose - et cela traitera les choses de la même manière, je pense. Il ne fait pas que tirer votre charset de l'air. En tout cas, j'avais de grands espoirs pour cesperl
modules - en avez-vous essayé?iswblank(3)
toutes les valeurs de caractères possibles.Sur les systèmes GNU, FreeBSD ou Solaris au moins, cette approche par force brute fonctionne:
Alors que par C / POSIX,
wchar_t
est un type opaque qui n'a aucune relation avec Unicode et est uniquement garanti pour couvrir tous les caractères pris en charge par les paramètres régionaux du système, dans la pratique, dans la plupart des systèmes qui prennent en charge Unicode, les valeurs correspondent aux points de code Unicode et les définitions de paramètres régionaux sont elles-mêmes basées sur Unicode.Unicode est censé être un sur-ensemble de tous les jeux de caractères connus, donc boucler sur tous les points de code valides en Unicode (0 à 0xD7FF et 0xE000 à 0x10FFFF) devrait répertorier au moins tous les caractères pris en charge par un jeu de caractères donné.
Ici, nous utilisons l'API standard locale du système pour vérifier ceux qui sont d'un type donné et pour les convertir dans leur forme encodée dans l'encodage des paramètres régionaux. Nous utilisons
perl
et soncharnames
module uniquement pour obtenir le nom d'un point de code Unicode donné.Sur les paramètres régionaux qui utilisent des codages avec état comme ISO-2022-JP, nous nous assurons que la forme codée est affichée à partir d'un état initial par défaut.
Je n'ai pas trouvé de système qui avait installé des paramètres régionaux avec un codage de caractères avec état, mais au moins sur les systèmes GNU, il est possible d'en générer pour que des paramètres régionaux malveillants puissent être créés (et au moins les outils GNU ne fonctionnent pas correctement dans ces locales). Par exemple, avec un environnement local personnalisé qui utilise ISO-2022-JP avec un
ja_JP
environnement local normal , j'obtiens:Comparer avec:
Dans ISO-2022-JP, la
1B 24 42
séquence (\e$B
) passe de ASCII à un état où les caractères sont exprimés en 2 octets (7 bits) (ici 21 21 pour cet ESPACE IDÉOGRAPHIQUE). En EUCJP, ce sont les mêmes octets, mais la commutation d'état se fait en inversant le 8ème bit (A1 = 21 | 0x80
), ce qui le rend plus sans état.Cela signifie que dans ces encodages avec état, il existe plusieurs façons d'écrire un caractère donné (par exemple en insérant plusieurs de ces séquences de commutation d'état ), et la séquence illustrée par ce code ci-dessus n'est qu'une d'entre elles (la canonique à partir d'une initiale État par défaut).
Alors que pour un environnement local normal, les caractères ne peuvent pas être en dehors de 0..0xD7FF, 0xE000..0x10FFFF, pour un environnement local voyous , n'importe quel caractère de la plage prise en charge par wchar_t peut l'être. Par exemple, je pourrais créer un environnement local où les caractères U + DCBA ou U + 12345678 (ou seraient des caractères s'ils étaient autorisés) sont vides . C'est pourquoi vous voudriez compiler ce code avec
-D SUPPORT_ROGUE_LOCALES
pour les couvrir, bien que cela signifie que cela prend beaucoup plus de temps pour analyser toute la liste.Je ne pouvais pas utiliser la solution de @ mikeserv car elle
recode
utilise ses propres conversions, n'est plus maintenue et ne prend en charge que les caractères Unicode jusqu'à 0xFFFF, et GNUtr
au moins ne fonctionne pas avec les caractères multi-octets.Je ne pouvais pas utiliser @ ChrisDown car
python
n'a pas d'interfaces avec les classes de caractères POSIX.J'ai essayé Perl, mais c'est faux pour les points de code entre 128 et 255 pour les locales multi-octets autres que UTF-8 et n'utilise pas les bibliothèques de conversion du système.
la source
combining
etcombining_level3
(à savoiriswctype(i, wctype("combining"))
)