Lo que podría ser una manera de recuperar una lista de todos los personajes de una clase de caracteres dada (como blank
, alpha
, digit
...) en la localización actual.
Por ejemplo,
LC_ALL=en_GB.UTF-8 that-command blank
idealmente, en mi sistema Debian, mostraría algo como:
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
Y en la configuración regional C podría mostrar algo como:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Es decir, la representación del carácter en la configuración regional en términos de matrices de bytes (como UTF-8 en el primer ejemplo y un solo byte en el segundo), el punto de código de caracteres Unicode equivalente y una descripción.
Contexto
(editar) Ahora que la vulnerabilidad ha sido parcheada y revelada por mucho tiempo, puedo agregar un poco de contexto.
Hice esa pregunta en el momento en que estaba investigando CVE 2014-0475 . glibc
tenía un error en el sentido de que permitía al usuario usar configuraciones regionales como las LC_ALL=../../../../tmp/evil-locale
que se resuelven en relación con la ruta de búsqueda de configuración regional del sistema estándar y, por lo tanto, permite usar cualquier archivo como definición de configuración regional.
Podría crear un entorno local malicioso, por ejemplo, con un solo byte por juego de caracteres donde la mayoría de los caracteres excepto s
, h
y algunos otros se consideraron espacios en blanco y eso se bash
ejecutaría sh
al analizar un /etc/bash.bashrc
archivo Debian típico (y eso podría usarse para obtener acceso de shell en un git
el servidor de alojamiento, por ejemplo, bash
se utiliza como el shell de inicio de sesión del usuario del git
servidor y que el ssh
servidor acepta LC_*
/ LANG
variables y que el atacante puede cargar archivos al servidor).
Ahora, si alguna vez encontré una LC_CTYPE
(definición de configuración regional compilada) /tmp/evil
, ¿cómo podría descubrir que era una canalla y de qué manera?
Por lo tanto, mi objetivo es descompilar esas definiciones de configuración regional y, si no, al menos saber qué caracteres (junto con su codificación) están en una clase de caracteres dada.
Así que con eso en mente:
- Las soluciones que miran los archivos de origen para la configuración regional (las definiciones de configuración regional como las
/usr/share/i18n/locale
de Debian) no son útiles en mi caso. - Las propiedades de los caracteres Unicode son irrelevantes. Solo me importa lo que dice la localidad. En un sistema Debian, incluso entre dos configuraciones regionales del sistema UTF-8, y mucho menos las falsas, la lista de caracteres en una clase puede ser diferente.
- Las herramientas como
recode
,python
operl
que realizan la conversión de byte / multi-byte a / desde caracteres no pueden usarse, ya que pueden (y en la práctica lo hacen) realizar la conversión de una manera diferente a la configuración regional.
fuente
/usr/share/i18n/locales/i18n
... que, por supuesto, proviene en gran medida de la base de datos de caracteres Unicode. Por supuesto, sería bueno tener un comandolocale
(al menos la de GNU) recupera muchas de las informaciones almacenadas en muchas de las categorías, cosas que no son las más importantes en LC_CTYPE y LC_COLLATE. Me pregunto si hay una API oculta para recuperar esa información o descompilar la información del entorno local.recode
yuconv
puede darle lo que usted dice que está buscando. Posiblemente incluso justoluit
yod
supongo ...perl
nada, creo.LC_CTYPE
conod -A n -t c <LC_CTYPE | tsort
Probablemente ya lo hayas probado, pero nunca antes había oído hablar de eso y estaba leyendoinfo
y me recordó esto, y parece funcionar. También hay,ptx
pero creo que es menos relevante. De todos modos, si no lo ha intentado y decide hacerlo, advertencia justa, requiere un poco de paciencia. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Respuestas:
POSIBLE SOLUCIÓN FINAL
Así que tomé toda la información a continuación y llegué a esto:
NOTA :
Lo uso
od
como el filtro final anterior por preferencia y porque sé que no trabajaré con caracteres de varios bytes, que no manejará correctamente.recode u2..dump
ambos generarán una salida más parecida a la especificada en la pregunta y manejarán los caracteres anchos correctamente.SALIDA
API DEL PROGRAMADOR
Como lo demuestro a continuación,
recode
le proporcionaré su mapa completo de personajes. De acuerdo con su manual, lo hace de acuerdo con el valor actual de laDEFAULT_CHARSET
variable de entorno o, en su defecto, funciona exactamente como usted especifica:También vale la pena señalar
recode
que es una API :#include <recode.h>
Para una comparación de cadenas internacionalmente amigable Los estándares
POSIX
yC
definen lastrcoll()
función:Aquí hay un ejemplo de su uso ubicado por separado :
Con respecto a las
POSIX
clases de caracteres, ya has notado que usaste laC
API para encontrarlos. Para caracteres y clases unicode, puede usar el juego de caracteresrecode's
dump-with-names para obtener el resultado deseado. De su manual nuevamente :Utilizando una sintaxis similar a la anterior combinada con su conjunto de datos de prueba incluido , puedo obtener mi propio mapa de caracteres con:
SALIDA
Pero para los personajes comunes,
recode
aparentemente no es necesario. Esto debería darle caracteres con nombre para todo en el conjunto de caracteres de 128 bytes:SALIDA
Por supuesto, solo se representan 128 bytes, pero eso se debe a que mi configuración regional, utf-8 charmaps o no, usa el juego de caracteres ASCII y nada más. Entonces eso es todo lo que obtengo. Sin
luit
embargo, si lo ejecutara sin filtrarlo,od
lo rodaría e imprimiría el mismo mapa nuevamente hasta\0400.
Sin embargo, hay dos problemas principales con el método anterior. Primero está el orden de clasificación del sistema: para los entornos locales que no son ASCII, los valores de mordida de los conjuntos de caracteres no son simplemente in
seq
uence, lo que, según creo, es probablemente el núcleo del problema que está tratando de resolver.Bueno, la
tr's man
página de GNU afirma que expandirá las[:upper:]
[:lower:]
clases en orden, pero eso no es mucho.Me imagino que podría implementarse una solución de mano dura,
sort
pero sería una herramienta bastante difícil de manejar para una API de programación de back-end.recode
hará esto correctamente, pero el otro día no parecías demasiado enamorado del programa. Tal vez las ediciones de hoy arrojen una luz más amigable o tal vez no.GNU también ofrece la
gettext
biblioteca de funciones, y parece ser capaz de abordar este problema al menos para elLC_MESSAGES
contexto:También puede usar categorías de caracteres Unicode nativas , que son independientes del idioma y renuncian a las clases POSIX por completo, o tal vez recurrir a las primeras para proporcionarle suficiente información para definir las últimas.
El mismo sitio web que proporcionó la información anterior también analiza
Tcl
la propia implementación de expresiones regulares que cumple con POSIX, que podría ser otra forma de lograr su objetivo.Y por último, entre las soluciones, sugeriré que puede interrogar el
LC_COLLATE
archivo en sí para obtener el mapa de caracteres del sistema completo y en orden . Puede que esto no parezca fácil, pero logré algo de éxito con lo siguiente después de compilarlolocaledef
como se muestra a continuación:Es, sin duda, actualmente defectuoso, pero espero que al menos demuestre la posibilidad.
AL PRIMER RUBOR
Realmente no parecía mucho, pero luego comencé a notar
copy
comandos en toda la lista. El archivo anterior parece estarcopy
en "en_US", por ejemplo, y otro muy grande que parece que todos comparten hasta cierto punto esiso_14651_t1_common
.Es bastante grande:
Aquí está la introducción a
/usr/share/i18n/locales/POSIX
:...
Puede hacerlo,
grep
por supuesto, pero podría simplemente:En lugar. Obtendrías algo como esto:
... Y MÁS
También hay
luit
unpty
dispositivo de traducción UTF-8 terminal , supongo que actúa como intermediario para XTerms sin soporte UTF-8. Maneja muchos modificadores, como registrar todos los bytes convertidos en un archivo o-c
como un|pipe
filtro simple .Nunca me di cuenta de que había tanto en esto: las configuraciones regionales y los mapas de caracteres y todo eso. Aparentemente esto es un gran problema, pero supongo que todo sucede detrás de escena. Hay, al menos en mi sistema, un par de cientos de
man 3
resultados relacionados para búsquedas relacionadas con la configuración regional.Y también hay:
Eso va a continuar por un muy largo tiempo.
Las
Xlib
funciones manejan esto todo el tiempo,luit
es parte de ese paquete.Las
Tcl_uni...
funciones también pueden resultar útiles.solo un poco de
<tab>
finalización yman
búsquedas, y he aprendido bastante sobre este tema.Con
localedef
: puede compilarlolocales
en suI18N
directorio. El resultado es funky y no extraordinariamente útil, no comocharmaps
en absoluto, pero puede obtener el formato sin procesar tal como lo especificó anteriormente como lo hice yo:Luego con
od
usted puede leerlo: bytes y cadenas:Aunque está muy lejos de ganar un concurso de belleza, esa es una salida utilizable. Y
od
es tan configurable como quieras que sea, por supuesto.Supongo que también me olvidé de estos:
Probablemente me olvidé de ellos porque no pude hacer que trabajaran. Supongo que nunca uso
Perl
y no sé cómo cargar un módulo correctamente. Pero lasman
páginas se ven muy bien. En cualquier caso, algo me dice que encontrarás que llamar a un módulo de Perl es al menos un poco menos difícil que yo. Y, nuevamente, estos ya estaban en mi computadora, y ni siquiera uso Perl. También hay notablemente algunosI18N
que me desplacé con melancolía sabiendo muy bien que tampoco los haría funcionar.fuente
i18n
) que pueden o no haber sido utilizados para generar la configuración regional que estoy usando actualmente. La información del entorno local probablemente proviene de/usr/lib/locale/locale-archive
o/some/dir/LC_CTYPE
, y esa es la parte relevante para mi entorno local que se almacena en los archivos que busco.LC_STUFF
archivo del archivolocaledef
, también lo hace. Puedo demostrar eso también, supongo. También puede ver eso y prácticamente todo lo demás constrings
o conod
el resto. Lo hice, de todos modos. Pero, por cierto,charmaps
son la configuración regional que está utilizando actualmente, ylocaledef
también informará sobre eso. También eso es lo querecode
hace también.od,
recode
,uconv
y el resto. Pero fue mi error, no eslocaledef
que lo extraiga, esrecode
eso lo hará. Tienes que echarle un vistazoinfo recode
, y además delrecode
comando de tabla que muestro hay casi lo mismo, y creo que manejará las cosas de la misma manera. No solo saca su juego de caracteres de la nada. En cualquier caso, tenía muchas esperanzas para esosperl
módulos. ¿Probaste alguno?iswblank(3)
para todos los valores de caracteres posibles.Al menos en los sistemas GNU, FreeBSD o Solaris, este enfoque de fuerza bruta funciona:
Si bien según C / POSIX,
wchar_t
es un tipo opaco que no tiene relación con Unicode y solo se garantiza que cubre todos los caracteres admitidos por la configuración regional del sistema, en la práctica, en la mayoría de los sistemas que admiten Unicode, los valores sí corresponden a los puntos de código Unicode y las definiciones locales están basadas en Unicode.Unicode está destinado a ser un superconjunto de todos los conjuntos de caracteres conocidos, por lo que recorrer todos los puntos de código válidos en Unicode (0 a 0xD7FF y 0xE000 a 0x10FFFF) debe enumerar al menos todos los caracteres admitidos por un conjunto de caracteres dado.
Aquí, estamos utilizando la API estándar de la configuración regional del sistema para verificar cuáles son de un tipo determinado y convertirlo a su forma codificada en la codificación de la configuración regional. Usamos
perl
y sucharnames
módulo solo para obtener el nombre de un punto de código Unicode dado.En las configuraciones regionales que usan codificaciones con estado como ISO-2022-JP, nos aseguramos de que el formulario codificado se muestre desde un estado inicial predeterminado.
No he encontrado un sistema que haya instalado entornos locales con una codificación de caracteres con estado, pero al menos en los sistemas GNU, es posible generar algunos para que se pueda hacer un entorno local no autorizado (y al menos las herramientas GNU no funcionan correctamente en esos sistemas). locales). Por ejemplo, con una configuración regional personalizada que utiliza ISO-2022-JP con una
ja_JP
configuración regional normal , obtengo:Comparar con:
En ISO-2022-JP, la
1B 24 42
secuencia (\e$B
) cambia de ASCII a un estado donde los caracteres se expresan como 2 bytes (7 bits) (aquí 21 21 para ese ESPACIO IDEOGRÁFICO). Mientras que en EUCJP, son los mismos bytes, pero el cambio de estado se realiza al voltear el 8vo bit (A1 = 21 | 0x80
), lo que lo hace más apátrida.Eso significa que en esas codificaciones con estado, hay varias formas de escribir un carácter dado (por ejemplo, insertando varias de esas secuencias de cambio de estado ), y la secuencia que se muestra con ese código anterior es solo una de ellas (la canónica de una inicial estado predeterminado).
Mientras que para un escenario normal, los personajes no pueden estar fuera 0..0xD7FF, 0xE000..0x10FFFF, para un pícaro local, cualquier carácter en la gama que admite wchar_t puede ser. Por ejemplo, podría crear un entorno local donde U + DCBA o U + 12345678 caracteres (o serían caracteres si se permitieran) son espacios en blanco . Es por eso que querría compilar ese código
-D SUPPORT_ROGUE_LOCALES
para cubrirlos, aunque eso significa que lleva mucho más tiempo escanear toda la lista.No pude usar la solución de @ mikeserv ya que
recode
usa sus propias conversiones, ya no se mantiene y solo admite caracteres Unicode hasta 0xFFFF, y GNUtr
al menos no funciona con caracteres de varios bytes.No pude usar @ ChrisDown ya
python
que no tiene interfaces para las clases de caracteres POSIX.Intenté con Perl, pero es falso para puntos de código entre 128 y 255 para entornos locales de varios bytes que no sean UTF-8 y no usa las bibliotecas de conversión del sistema.
fuente
combining
ycombining_level3
(a saberiswctype(i, wctype("combining"))
)