Co może być sposobem, aby pobrać listę wszystkich znaków w danej klasy postaci (jak blank
, alpha
, digit
...) w obecnej lokalizacji.
Na przykład,
LC_ALL=en_GB.UTF-8 that-command blank
idealnie, w moim systemie Debian, wyświetlałby coś takiego:
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
A w lokalizacji C może wyświetlać się coś takiego:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Oznacza to reprezentację znaku w ustawieniach narodowych pod względem tablic bajtów (takich jak UTF-8 w pierwszym przykładzie i pojedynczego bajtu w drugim), równoważny znak kodowy Unicode i opis.
Kontekst
(edytuj) Teraz, gdy luka została już łatana i ujawniona, mogę dodać trochę kontekstu.
Zadałem to pytanie w czasie, gdy badałem CVE 2014-0475 . glibc
wystąpił błąd polegający na tym, że pozwala użytkownikowi na użycie takich ustawień LC_ALL=../../../../tmp/evil-locale
narodowych w stosunku do standardowej ścieżki wyszukiwania ustawień regionalnych systemu, a tym samym pozwala na użycie dowolnego pliku jako definicji ustawień regionalnych.
Mógłbym stworzyć locale łobuz na przykład za pomocą jednego bajta na znak charset gdzie większość znaków wyjątkiem s
, h
a kilka innych zostało uznane półfabrykatów i która stałaby bash
prowadzonym sh
podczas parsowania typowy Debiana /etc/bash.bashrc
plik (i które mogłyby być wykorzystane, aby uzyskać powłoki dostępu, na git
pod warunkiem, że serwer hostingowy bash
jest używany jako powłoka logowania git
użytkownika serwera oraz że ssh
serwer akceptuje LC_*
/ LANG
zmienne i że osoba atakująca może przesyłać pliki na serwer).
Teraz, gdybym kiedykolwiek znalazł LC_CTYPE
(skompilowaną definicję ustawień regionalnych), w /tmp/evil
jaki sposób miałbym dowiedzieć się, że była to nieuczciwa metoda i w jaki sposób.
Moim celem jest więc dekompilacja definicji ustawień regionalnych, a jeśli nie, to przynajmniej wiem, które znaki (wraz z ich kodowaniem) należą do danej klasy znaków.
Mając to na uwadze:
- Rozwiązania, które sprawdzają pliki źródłowe dla ustawień narodowych (definicje ustawień regionalnych, takie jak te w
/usr/share/i18n/locale
Debianie) nie są w moim przypadku przydatne. - Właściwości znaków Unicode są nieistotne. Dbam tylko o to, co mówi lokacja. W systemie Debian, nawet pomiędzy dwoma lokalizacjami systemu UTF-8, nie mówiąc już o fałszywych ustawieniach, lista znaków w klasie może być inna.
- Narzędzia podoba
recode
,python
alboperl
że zrobić bajtów / multi-bajt do / z konwersji znaków nie może być stosowany jako oni mogą (aw praktyce nie) dokonać konwersji w inny sposób niż lokalizacji.
źródło
/usr/share/i18n/locales/i18n
... który oczywiście pochodzi głównie z bazy znaków znaków Unicode. Oczywiście byłoby miło mieć polecenielocale
(przynajmniej GNU) pobiera wiele informacji przechowywanych w wielu kategoriach, rzeczy, które nie są najważniejsze w LC_CTYPE i LC_COLLATE. Zastanawiam się, czy istnieje ukryty interfejs API do pobierania tych informacji lub dekompilacji informacji regionalnych.recode
iuconv
może dać ci to, co mówisz, że szukasz. Być może nawetluit
iod
chyba…perl
wcale nie potrzebujesz .LC_CTYPE
z zaledwieod -A n -t c <LC_CTYPE | tsort
Prawdopodobnie próbowałeś go już, ale nigdy nie słyszałem o tym wcześniej i byłem poprzez czytanieinfo
i przypomniało mi to - i wydaje się do pracy. Są też,ptx
ale myślę, że to mniej istotne. W każdym razie, jeśli nie wypróbowałeś go i zdecydowałeś się to zrobić - uczciwe ostrzeżenie - wymaga to trochę cierpliwości. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1Odpowiedzi:
MOŻLIWE ROZWIĄZANIE KOŃCOWE
Więc wziąłem wszystkie poniższe informacje i przedstawiłem to:
UWAGA :
Używam
od
jako ostatniego filtru dla preferencji i ponieważ wiem, że nie będę pracował ze znakami wielobajtowymi, które nie będą poprawnie obsługiwane.recode u2..dump
wygeneruje wyjście bardziej podobne do określonego w pytaniu i poprawnie obsłuży szerokie znaki.WYNIK
API PROGRAMATORA
Jak pokażę poniżej,
recode
dostarczy ci pełną mapę postaci. Zgodnie z jego instrukcją robi to najpierw zgodnie z bieżącą wartościąDEFAULT_CHARSET
zmiennej środowiskowej lub, jeśli to nie działa, działa dokładnie tak, jak określono:Warto również zauważyć
recode
, że jest to interfejs API :#include <recode.h>
Do porównywania ciągów przyjaznych na arenie międzynarodowej Standardy
POSIX
iC
definiująstrcoll()
funkcję:Oto osobno umieszczony przykład jego użycia:
Jeśli chodzi o
POSIX
klasy postaci, już zauważyłeś, że użyłeśC
API, aby je znaleźć. W przypadku znaków i klas Unicode możesz użyć zestawu znakówrecode's
zrzutu z nazwami, aby uzyskać pożądany wynik. Z instrukcji ponownie :Używając podobnej składni do powyższej w połączeniu z dołączonym testowym zestawem danych , mogę uzyskać własną mapę znaków za pomocą:
WYNIK
Ale dla zwykłych postaci
recode
najwyraźniej nie jest to konieczne. To powinno dać ci nazwane znaki dla wszystkiego w 128-bajtowym zestawie znaków:WYNIK
Oczywiście reprezentowanych jest tylko 128 bajtów, ale to dlatego, że moje ustawienia regionalne, charmapy utf-8 lub nie, używają zestawu znaków ASCII i nic więcej. To wszystko, co dostaję. Gdybym jednak uruchomił go bez
luit
filtrowania,od
odwróciłbym go i wydrukowałbym ponownie tę samą mapę\0400.
Istnieją jednak dwa główne problemy z powyższą metodą. Po pierwsze, kolejność sortowania w systemie - w przypadku lokalizacji innych niż ASCII wartości zgryzu dla zestawów znaków nie są po prostu
seq
ważne, co, jak sądzę, jest prawdopodobnie rdzeniem problemu, który próbujesz rozwiązać.Cóż,
tr's man
strona GNU stwierdza, że będzie rozwijała[:upper:]
[:lower:]
klasy w kolejności - ale to niewiele.Wyobrażam sobie, że można zaimplementować jakieś ciężkie rozwiązanie,
sort
ale byłoby to raczej niewygodne narzędzie do API programowania zaplecza.recode
zrobi to poprawnie, ale któregoś dnia nie zakochałeś się w programie. Może dzisiejsze zmiany rzucą na to bardziej przyjazne światło, a może nie.GNU oferuje również
gettext
bibliotekę funkcji i wydaje się, że jest w stanie rozwiązać ten problem przynajmniej wLC_MESSAGES
kontekście:Możesz także użyć rodzimych kategorii znaków Unicode , które są niezależne od języka i całkowicie rezygnują z klas POSIX, lub być może w celu wywołania pierwszej z nich, aby dostarczyć ci informacji wystarczających do zdefiniowania drugiej.
Ta sama witryna internetowa, która zawiera powyższe informacje, omawia także
Tcl
własną implementację wyrażeń regularnych zgodną z POSIX, która może być kolejnym sposobem na osiągnięcie celu.I na koniec wśród rozwiązań zasugeruję, że możesz przesłuchać
LC_COLLATE
sam plik w celu uzyskania kompletnej i uporządkowanej systemowej mapy znaków. Może się to wydawać trudne, ale po skompilowaniu go osiągnąłem sukces,localedef
jak pokazano poniżej:Jest to wprawdzie obecnie wadliwe, ale mam nadzieję, że to pokazuje przynajmniej taką możliwość.
NA PIERWSZY RÓŻ
To naprawdę nie wyglądało dużo, ale potem zacząłem zauważać
copy
polecenia na całej liście. Powyższy plik wydaje się na przykładcopy
w „en_US” , a innym naprawdę dużym, który wydaje się, że wszyscy w pewnym stopniu się nim dzieląiso_14651_t1_common
.Jest dość duży:
Oto wprowadzenie do
/usr/share/i18n/locales/POSIX
:...
Możesz
grep
oczywiście to zrobić, ale możesz po prostu:Zamiast. Dostałbyś coś takiego:
... I WIĘCEJ
Wydaje mi się, że jest też
luit
terminalowepty
urządzenie tłumaczące UTF-8 , które działa pośrednio w XTerms bez obsługi UTF-8. Obsługuje wiele przełączników - takich jak rejestrowanie wszystkich przekonwertowanych bajtów do pliku lub-c
jako prosty|pipe
filtr.Nigdy nie zdawałem sobie sprawy, że było tak wiele - lokalizacje i mapy postaci i tak dalej. To najwyraźniej bardzo ważna sprawa, ale myślę, że wszystko dzieje się za kulisami. Istnieje - przynajmniej w moim systemie - kilkaset
man 3
powiązanych wyników dla wyszukiwań związanych z ustawieniami regionalnymi.A także jest:
Trwa to bardzo długo.
Te
Xlib
funkcje obsługi to cały czas -luit
jest częścią tego pakietu.Te
Tcl_uni...
funkcje mogą okazać się przydatne również.tylko trochę
<tab>
ukończenia iman
poszukiwań i nauczyłem się sporo na ten temat.Za pomocą
localedef
- możesz skompilowaćlocales
w swoimI18N
katalogu. Dane wyjściowe są funky i nie są wyjątkowo przydatne - wcale nie tak jakcharmaps
w ogóle - ale możesz uzyskać format raw tak, jak określiłeś powyżej, tak jak ja:Następnie
od
możesz przeczytać - bajty i ciągi:Mimo że daleko mu do wygrania konkursu piękności, jest to użyteczny efekt. I
od
jest konfigurowalna, jak chcesz go mieć, a także, oczywiście.Chyba też o nich zapomniałem:
Prawdopodobnie o nich zapomniałem, ponieważ nie mogłem zmusić ich do pracy. Nigdy nie używam
Perl
i nie wiem, jak poprawnie załadować moduł. Aleman
strony wyglądają całkiem nieźle. W każdym razie coś mówi mi, że wywołanie modułu Perla jest co najmniej trochę trudniejsze niż ja. I znowu, były już na moim komputerze - i nigdy nawet nie używam Perla. Jest też kilka takich,I18N
które tęsknie przewinąłem, wiedząc dobrze, że ich też nie sprawię.źródło
i18n
), które mogły zostać użyte w celu wygenerowania ustawień regionalnych, których aktualnie używam. Informacje o ustawieniach regionalnych prawdopodobnie pochodzą z/usr/lib/locale/locale-archive
lub/some/dir/LC_CTYPE
, i to jest część związana z moimi ustawieniami regionalnymi, która jest przechowywana w plikach, których szukam.LC_STUFF
archiwum za pomocąlocaledef
- robi to również. Myślę, że mogę to również pokazać. Można również zobaczyć, że i prawie wszystko inne zstrings
lubod
lub którykolwiek z pozostałych. W każdym razie tak zrobiłem. Ale nawiasem mówiąc -charmaps
są to ustawienia regionalne, których obecnie używasz - ilocaledef
również o tym poinformują. Też torecode
robi.od,
recode
,uconv
i reszta. Ale to był mój błąd - to nie tak,localedef
że to wyciąga, tylko torecode
zrobi. Musisz to sprawdzićinfo recode
- i opróczrecode
polecenia tabeli pokazuję, że jest bardzo to samo - i myślę, że poradzi sobie w ten sam sposób. Nie tylko wyciąga twój zestaw z cienkiego powietrza. W każdym razie miałem duże nadzieje na teperl
moduły - wypróbowałeś coś takiego?iswblank(3)
wszystkich możliwych wartości postaci.W systemach GNU, FreeBSD lub Solaris to brutalne podejście działa:
Chociaż dla C / POSIX
wchar_t
jest nieprzejrzystym typem, który nie ma związku z Unicode i gwarantuje jedynie, że obejmie wszystkie znaki obsługiwane przez ustawienia regionalne systemu, w praktyce w większości systemów obsługujących Unicode, wartości odpowiadają punktom kodu Unicode a same definicje ustawień regionalnych są oparte na Unicode.Unicode ma być nadzbiorem wszystkich znanych zestawów znaków, więc zapętlanie wszystkich prawidłowych punktów kodu w Unicode (od 0 do 0xD7FF i 0xE000 do 0x10FFFF) powinno zawierać przynajmniej wszystkie znaki obsługiwane przez dany zestaw znaków.
W tym przypadku używamy standardowego interfejsu API ustawień regionalnych systemu, aby sprawdzić, które z nich są danego typu i przekonwertować go na postać zakodowaną w kodowaniu ustawień regionalnych. Używamy
perl
i jegocharnames
modułu tylko, aby uzyskać nazwę z danego punktu kodowego Unicode.W lokalizacjach korzystających z kodowania stanowego, takich jak ISO-2022-JP, upewniamy się, że zakodowana forma jest wyświetlana z domyślnego stanu początkowego.
Nie znalazłem systemu, w którym zainstalowano ustawienia regionalne ze stanowym kodowaniem znaków, ale przynajmniej w systemach GNU można wygenerować takie, aby można było wprowadzić nieuczciwe ustawienia regionalne (a przynajmniej narzędzia GNU nie działają poprawnie w tych systemach lokalizacje). Na przykład z niestandardowymi ustawieniami narodowymi używającymi ISO-2022-JP ze zwykłymi
ja_JP
ustawieniami narodowymi otrzymuję:Porównać z:
W ISO-2022-JP
1B 24 42
sekwencja (\e$B
) przełącza się z ASCII do stanu, w którym znaki są wyrażane jako 2 (7-bitowe) bajty (tutaj 21 21 dla tej PRZESTRZENI IDEOGRAFICZNEJ). W EUCJP są to te same bajty, ale przełączanie stanu odbywa się poprzez odwrócenie ósmego bitu (A1 = 21 | 0x80
), co czyni go bardziej bezstanowym.Oznacza to, że w tych stanowych kodowaniach istnieje kilka sposobów na napisanie danego znaku (na przykład poprzez wstawienie kilku z tych sekwencji przełączających stan ), a pokazana sekwencja według tego kodu powyżej jest tylko jednym z nich (kanoniczna od początku stan domyślny).
Podczas gdy w normalnych ustawieniach narodowych znaki nie mogą znajdować się poza 0..0xD7FF, 0xE000..0x10FFFF, w przypadku nieuczciwych ustawień regionalnych dowolna postać z zakresu obsługiwanego przez wchar_t może być. Na przykład mogę utworzyć ustawienia narodowe, w których znaki U + DCBA lub U + 12345678 (lub byłyby znakami, jeśli byłyby dozwolone) byłyby spacjami . Dlatego chcesz skompilować ten kod,
-D SUPPORT_ROGUE_LOCALES
aby je uwzględnić, ale oznacza to, że skanowanie całej listy zajmuje dużo więcej czasu.Nie mogłem użyć rozwiązania @ mikeserv, ponieważ
recode
używa własnych konwersji, nie jest już obsługiwane i obsługuje tylko znaki Unicode do 0xFFFF, a GNUtr
przynajmniej nie działa ze znakami wielobajtowymi.Nie mogłem użyć @ ChrisDown, ponieważ
python
nie ma interfejsów do klas znaków POSIX.Próbowałem Perla, ale jest fałszywy dla punktów kodowych od 128 do 255 dla wielobajtowych ustawień narodowych innych niż UTF-8 i nie korzysta z bibliotek konwersji systemu.
źródło
combining
combining_level3
iswctype(i, wctype("combining"))