2 पॉइंट द्वारा GN⁺ 2025-01-10 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Windows का Best-Fit character conversion UTF-16 strings को ANSI code page में बदलते समय मिलते-जुलते दिखने वाले characters से replace करता है, और यही व्यवहार Path Traversal, Argument Injection, RCE तक जाने वाला WorstFit attack surface बन जाता है
  • समस्या उस structure में पैदा होती है जहाँ ANSI API, C/C++ runtime, compiler द्वारा insert किया गया startup code, और developers द्वारा non-wide character API का उपयोग एक साथ overlap करते हैं; GetCommandLineA, GetEnvironmentVariableA, getenv, int main() paths प्रभावित होते हैं
  • CVE-2024-4577 में Chinese/Japanese code pages पर U+00AD - में बदल गया और PHP-CGI patch bypass हो गया; Filename Smuggling में ¥, , fullwidth slash / या \ में बदलकर path confusion पैदा करते हैं
  • Argument Splitting में fullwidth double quote या Yen/Won sign command-line parsing characters बना देते हैं, जिससे wget.exe, tar.exe, openssl.exe, java.exe जैसे CLI tools में arguments inject किए जा सकते हैं; PHP·Python·Node.js·Rust की सामान्य argument escaping भर से इसे रोकना मुश्किल है
  • Mitigation के लिए Windows का UTF-8 option चालू करना होगा या developers को Wide Character API और _wgetcwd, _wgetenv, wmain() जैसे wide character paths इस्तेमाल करने होंगे; Microsoft द्वारा सभी Windows editions में UTF-8 को default करने तक ऐसी समस्याएँ दोहराई जा सकती हैं

Windows encoding structure और Best-Fit

  • शुरुआती दौर में Windows ANSI code pages इस्तेमाल करता था, और भाषा/क्षेत्र के हिसाब से 1252, 932, 936, 949, 950 जैसे code pages अलग-अलग होते थे
    • ACP(ANSI Code Page) file operations, environment variables जैसी अधिकतर application और system settings में इस्तेमाल होता है
    • OEMCP(Original Equipment Manufacturer Code Page) मुख्यतः console read/write जैसे device communication में इस्तेमाल होता है
    • chcp ACP नहीं बल्कि OEMCP दिखाता है, इसलिए यह इस research के केंद्र में मौजूद ACP जाँचने का साधन नहीं है
  • Windows ने 1990s के मध्य में Unicode पर transition किया, और आज core API UTF-16 based wide character इस्तेमाल करती हैं
    • file system, system information, text processing जैसी core APIs wide character API में migrate हो चुकी हैं
    • UTF-8 feature मौजूद है, लेकिन ज्यादातर languages में default रूप से चालू नहीं है; लेख में इसे beta stage बताया गया है
  • Backward compatibility की वजह से Windows API ANSI version और Unicode version दोनों provide करती है
    • ANSI API में GetEnvironmentVariableA की तरह A suffix होता है
    • Unicode API में GetEnvironmentVariableW की तरह W suffix होता है
    • ANSI API call होने पर Windows internal UTF-16 string को RtlUnicodeStringToAnsiString या WideCharToMultiByte से ANSI string में convert करता है

Best-Fit कैसे WorstFit बनता है

  • Best-Fit वह व्यवहार है जिसमें जब UTF-16 character target ANSI code page में exact represent नहीं हो पाता, तो उसे मिलते-जुलते दिखने या महसूस होने वाले character से map कर दिया जाता है
    • उदाहरण के लिए Windows-1252 में U+221E को 8 पर map किया जाता है
    • √π⁷≤∞ ANSI API से गुजरने पर "vp7=8" जैसा बदल सकता है
  • Mapping हर code page में अलग तरह से काम करती है
    • ¥ U+00A5 Japanese 932 code page में \ पर map होता है
    • Central European 1250 code page में यह Y पर map होता है
    • अधिकतर दूसरे code pages में यह नहीं बदलता
  • सिर्फ Windows API को direct call करने पर नहीं, बल्कि CRT functions और सामान्य main function paths में भी वही conversion होता है
    • getenv जैसे non-wide CRT functions में Best-Fit conversion apply होता है
    • int main(int argc, char* argv[], char* envp[]) रूप में arguments और environment variables लेने पर भी conversion बीच में आता है
    • इसकी वजह compiler द्वारा insert किया गया CRT startup code और ANSI Windows API usage का combination है
  • Mapping जाँचने के लिए Best-fit Mapping Grepper और Unicode.org का WindowsBestFit raw mapping data देखे जा सकते हैं

पहला WorstFit case: PHP-CGI CVE-2024-4577

  • CVE-2024-4577 WorstFit attack का ऐसा case है जिसमें Chinese/Japanese code page पर set PHP-CGI server को सिर्फ ?%ADs request से compromise किया जा सकता था
    • प्रभावित code pages 932(Japanese), 936(Simplified Chinese), 950(Traditional Chinese) हैं
    • threat character ­ U+00AD है
  • 2012 की PHP-CGI vulnerability Apache द्वारा query string को CGI program के पहले argument के रूप में automatic process करने से पैदा हुई argument injection थी
    • ?-s जोड़ने पर page source code leak और RCE संभव था
    • PHP patch का तरीका यह था कि query string dash से शुरू हो तो argument parsing रोक दी जाए
  • Best-Fit की वजह से U+00AD soft hyphen Chinese/Japanese code pages में - में convert हो जाता है, जिससे मौजूदा patch bypass हो गया
    • ?%ADs PHP-CGI के नजरिए से -s जैसा behave कर सकता है
    • इसी case के बाद research team ने पहली बार Best-Fit शब्द देखा

Filename Smuggling: path characters के convert होने की समस्या

  • Filename Smuggling ऐसा attack है जिसमें filename में मौजूद Unicode characters ANSI API path में / या \ में बदलकर path traversal बना सकते हैं
    • संबंधित APIs में GetCurrentDirectoryA, getcwd, FindFirstFileA, findfirst*, GetFullPathNameA आदि शामिल हैं
    • प्रभावित code pages 874, 125x, 932(JP), 949(KR) हैं
    • threat characters U+FF0F, U+FF3C, ¥ U+00A5(JP), U+20A9(KR) हैं
  • Chrome V8 का Developer Shell d8.exe internal implementation में current working directory पाने के लिए GetCurrentDirectoryA() इस्तेमाल करता है
    • अगर malicious Unicode characters वाला working directory बनाया जा सके, तो ANSI API access के समय यह path traversal payload में बदल जाता है
    • उदाहरण के तौर पर अनचाहा C:/windows/win.ini access संभव है
  • mruby के Dir.getwd() का Windows implementation ANSI CRT function _getcwd() पर निर्भर करता है
    • return value polluted हो सकती है, और Path Traversal तक जा सकती है

Cuckoo Sandbox: Path Traversal से RCE तक

  • Python में Windows फ़ाइल सिस्टम access के लिए string wide है या narrow, इसके आधार पर wide API या ANSI API इस्तेमाल की जा सकती थी
    • PEP 529 के बाद Windows फ़ाइल सिस्टम encoding को UTF-8 पर standardize किया गया
    • Python 2 और Python 3.6 से पहले के Python 3, WorstFit attack के लिए vulnerable बने रहे
  • Cuckoo Sandbox एक automated malware analysis platform है, और इसका latest official version Python 2.7 पर निर्भर करता है
    • Cuckoo, Cuckoo Host और VM Cluster से मिलकर बना है
    • uploaded sample को VM में isolated तरीके से execute किया जाता है, और network packets, dropped files और logs को अपने mechanism से sync किया जाता है
  • अगर malware Unicode filename वाला dropped file बनाता है, तो Cuckoo Host की Python path handling में Path Traversal हो सकता है
    • उदाहरण PoC AAAA\u00a5..\u00a5..\u00a5..\u00a5..\u00a5..\u00a5conf\u00a5cuckoo.conf path बनाता है
    • analysis खत्म होने के बाद जब user web interface में download button दबाता है, तो Python file operation trigger होता है
    • Cuckoo Host, बदले हुए ../ वाले path को process करके attacker को sensitive data भेज सकता है
  • attacker cuckoo.conf डाउनलोड कर सकता है और Flask PIN calculate करने के लिए जरूरी sensitive information जुटाकर Sandbox Host पर RCE हासिल कर सकता है
    • demo video Video 11 के रूप में उपलब्ध है

Argument Splitting: command-line parsing बदलने वाला Best-Fit

  • Argument Splitting ऐसा attack है जिसमें GetCommandLineA output या non-Unicode int main() path में command-line string बदल जाती है और arguments अलग हो जाते हैं
    • संबंधित API और paths हैं GetCommandLineA, int main()
    • प्रभावित code pages हैं 874, 125x, 932(JP), 949(KR)
    • threat characters हैं U+FF02, U+FF3C, ¥ U+00A5(JP), U+20A9(KR)
  • उदाहरण PHP code escapeshellarg() से URL को सुरक्षित तरीके से wrap करने के बाद wget.exe -q चलाता है, लेकिन input " --use-askpass=calc " से calc.exe चलाना संभव है
    • वही input Node.js, Rust, Python में बदलने पर भी defend नहीं होता
    • Python के latest version के subprocess.run(["wget", "-q", ...]) example में भी यह काम करता है
  • Windows नए process को पूरा command line एक ही string के रूप में पास करता है, और executable उसे खुद parse करता है
    • यह UNIX-like systems जैसा structure नहीं है, जहां argument array हमेशा पास होता है
    • CreateProcess API सीधे lpCommandLine parameter लेती है
  • सामान्य command-line parsing में अहम characters space, tab, double quote और backslash होते हैं
    • space और tab quote mode न होने पर arguments को अलग करते हैं
    • " quote mode को toggle करता है
    • \ कुछ sequences में double quote और backslash को escape करता है
  • ज्यादातर languages की standard libraries इन rules के हिसाब से user arguments को escape करती हैं, लेकिन escaping Best-Fit conversion से पहले खत्म हो जाती है
    • PHP escapeshellarg double quote को space में बदलता है, argument को quote से wrap करता है और backslash handle करता है
    • Python subprocess, list2cmdline से Microsoft CRT command-line parsing rules के अनुसार escape करता है
    • इसके बाद ANSI conversion में U+FF02 अगर " U+0022 में बदल जाए, तो original command-line syntax बदल जाता है
  • सिर्फ int main() इस्तेमाल करने वाले programs भी vulnerable हो सकते हैं
    • compiler binary में mainCRTStartup generate करता है, और यह startup function CRT library से link होता है
    • अगर CRT internals ANSI API से command line लेकर parse करते हैं, तो Best-Fit conversion बीच में आ जाता है
    • इस behavior की वजह से किसी खास programming language की standard library भर से attack को पूरी तरह रोकना मुश्किल है

Argument Splitting के वास्तविक उदाहरण

  • ElFinder PHP backend पर आधारित open source web file manager है, और default रूप से Windows server तथा archive creation/extraction को support करता है
    • archive processing shell command execution से implement की गई है, और arguments को escapeshellarg से escape किया जाता है
    • tar format processing में Windows built-in tar.exe इस्तेमाल होता है
    • aaa" "--use-compress-program=calc" "bbb.tar जैसे tar filename से --use-compress-program argument inject करके arbitrary command execution संभव है
    • demo English-configured Windows server, Code Page 1252 के आधार पर है, और इसे 125x code pages तथा Code Page 874 पर भी काम करना चाहिए बताया गया है
    • demo video Video 12 के रूप में उपलब्ध है
  • TortoiseGit में इस्तेमाल होने वाले modified plink.exe के case में, malicious URI को clone input के रूप में डालने पर code execution trigger हो सकता है
    • detailed content curated list में देखा जा सकता है
    • demo video Video 13
  • RStudio SVN version control को support करता है, और अगर maliciously crafted folder में SVN project हो तो एक click से calculator execution संभव है
    • detailed content curated list में देखा जा सकता है
    • demo video Video 14
  • Microsoft Excel का case Argument Splitting और Windows के “Open-With” feature को मिलाने वाला CVE-2024-49026 है
    • Windows file extension के हिसाब से handler table maintain करता है, जिसे ftype और assoc से check किया जा सकता है
    • filename handler program के arguments का हिस्सा बनता है, इसलिए filename के जरिए attack apply किया जा सकता है
    • dots, slash, backslash और double quote को fullwidth form में बदले हुए filename से Excel.exe में argument injection कराया जाता है
    • Excel में खुद further exploitation के लिए suitable arguments नहीं हैं, इसलिए NTLM Relay और RBCD/ADCS को साथ इस्तेमाल करके RCE हासिल किया जाता है
    • demo video Video 15

Environment Variable Confusion

  • Environment Variable Confusion तब होती है जब GetEnvironmentVariableA, GetEnvironmentStringsA, char *getenv() environment variables का Best-Fit में बदला हुआ version लौटाते हैं
    • प्रभावित code page और threat characters निर्दिष्ट नहीं हैं
    • Apache HTTPd के मामले में 0x00-0xFF शामिल है
  • इस attack के सफल होने के लिए environment variable को user द्वारा control किया जा सकना चाहिए
    • ऐसा तब होता है जब parent process अपने बनाए child process को जानकारी पास करता है
    • CGI में query string, HTTP header आदि HTTP request की काफी जानकारी environment variables के रूप में पास की जाती है
  • WAF bypass का उदाहरण उस स्थिति को देखता है जहां CGI script routing service की तरह काम करती है
    • Apache configuration में ऐसा rule है जो REQUEST_URI में /admin शामिल होने पर reject करता है, ताकि /cgi.pl/admin पर remote access रोका जा सके
    • Windows Perl के WorstFit behavior की वजह से admin के किसी हिस्से को Best-Fit equivalent से बदलकर bypass किया जा सकता है
    • Code Page 1250 में à U+00E0 ANSI conversion के दौरान a में बदल जाता है
    • /cgi.pl/%E0dmin request server-side rule में अलग path जैसी दिखती है, लेकिन जब Perl CGI script ANSI API से PATH_INFO पढ़ती है तो इसे /admin के रूप में process किया जाता है
  • PHP-CGI on Windows में कुछ configurations में file existence check oracle और संभावित LFI की पुष्टि हुई
    • वजह PATH_INFO और अन्य path-related environment variables के handling का तरीका है
    • /index.php/foo/bar request Apache के हिसाब से REDIRECT_URL, REQUEST_URI, PATH_INFO, PATH_TRANSLATED जैसे environment variables में पास होती है
    • सिर्फ इस जानकारी से PHP filename और अतिरिक्त PATH_INFO की boundary को साफ तौर पर अलग करना मुश्किल है, और php-cgi.exe इसकी व्याख्या करता है
  • Japanese code page में ¥ का उपयोग करने पर web server और PHP-CGI की path interpretation अलग हो जाती है
    • web server पूरे /..¥..¥windows/win.ini/foo को अतिरिक्त PATH_INFO के रूप में process करता है
    • PHP-CGI को REQUEST_URI=/index.php/..\..\windows/win.ini/foo जैसा converted value मिलता है और वह actual PHP file व PATH_INFO को अलग करने की प्रक्रिया में भ्रमित हो जाता है
    • Apache में non-existing file और existing file के response में फर्क से file existence oracle संभव है
    • IIS में doc_root directive set होने पर /index.php/..¥..¥..¥windows/win.ini/ जैसे path से C:\Windows\win.ini को include करके पढ़ने वाला LFI संभव है
    • यदि included file executable हो या user-control वाला code रखती हो, तो यह संभावित RCE तक ले जा सकता है, लेकिन यह scenario real-world applications में दुर्लभ bug के रूप में वर्गीकृत करने जैसा है

Disclosure और fix process की मुश्किलें

  • research team ने programming languages, open source projects, और Windows built-in CLI programs की कई समस्याएं उनके upstream maintainers को report कीं
    • सबसे ज्यादा debate Argument Splitting पर हुई
    • कुछ vendors ने माना कि user input को command line में पास करना अपने-आप में vulnerability है
  • जिम्मेदारी किसकी है, यह अस्पष्ट होना भी समस्या था
    • problematic code compile के दौरान automatically insert होने वाले mainCRTStartup() और MSVCRT/UCRT के अंदर ANSI API calls तक फैला है
    • यह अलग करना मुश्किल है कि समस्या developer द्वारा wmain() न इस्तेमाल करने की है, या CRT द्वारा command line को गलत तरीके से split करके main() को गलत arguments देने की
    • कुछ projects केवल source code देते हैं, और Windows prebuilt executable को internet पर third-party volunteers distribute करते हैं
  • fix सिर्फ main() को wide-character version में बदलने भर की बात नहीं है
    • function signature बदलने पर variable definitions और argument parsing logic को char * से wchar_t * based तरीके से फिर से लिखना पड़ता है
    • यह process तकलीफदेह और error-prone है
  • Curl ने जवाब दिया कि यह Windows feature है, इसलिए fix की कोई plan नहीं है; जबकि Microsoft द्वारा port किए गए Curl ने entry को wmain() में बदल दिया है, इसलिए Windows built-in curl.exe प्रभावित नहीं है
    • Curl official build binary Argument Splitting attack से प्रभावित है
    • पूरी report HackerOne पर public है
  • OpenSSL OPENSSL_WIN32_UTF8 environment variable के जरिए arguments को wide character format में process कर सकता है
    • मूल उद्देश्य UI में UTF-8 display problem को ठीक करना था, लेकिन यह Argument Splitting attack को भी mitigate करता है
    • default OpenSSL usage में developers को अक्सर यह पता नहीं होता कि यह environment variable set करना चाहिए, और -engine argument का उपयोग कर arbitrary code execution संभव है
  • Perl official distribution Windows prebuilt executable नहीं देती, और Strawberry Perl और ActiveState Perl जैसे third-party installers आम तौर पर इस्तेमाल होते हैं
    • दोनों distributions Argument Splitting attack से प्रभावित हैं
    • Perl maintainer से चर्चा के बाद निष्कर्ष निकला कि “यह Perl bug से ज्यादा Microsoft bug जैसा है”, इसलिए यह अभी unresolved है
  • Microsoft को तीन मामले MSRC में report किए गए, और शुरू में सभी severity criteria से कम मानकर reject कर दिए गए
    • कई बार फिर से open करने के बाद सिर्फ Excel case तीसरे प्रयास के बाद accept हुआ
    • बाकी cases अभी तक unresolved हैं
    • MSRC ने जवाब दिया कि यह किसी अलग application द्वारा untrusted input को command line में डालकर execute करने वाली vulnerability पर निर्भर करता है, और इसे exploitable बनाने वाली technique खुद vulnerability requirements पूरी नहीं करती
  • CERT/CC से भी मदद मांगी गई, और कुछ महीनों बाद Microsoft ने GetCommandLineA documentation में security warning जोड़ी
    • warning सिर्फ GetCommandLineA में जोड़ी गई, जबकि सावधानी की जरूरत वाली ANSI APIs अभी और भी हैं

Reported affected targets और status

  • disclosure process के दौरान confirm और report किए गए items इस प्रकार हैं
    • 2024/05/07: PHP php-cgi.exeCVE-2024-4577
    • 2024/06/13: Curl Official BuildWon’t Fix
    • 2024/06/13: Apache Subversion svn.exeCVE-2024-45720
    • 2024/06/16: Microsoft Tar tar.exe — Won’t Fix
    • 2024/06/19: Microsoft Excel excel.exeCVE-2024-49026
    • 2024/06/19: Microsoft PhoneBook rasphone.exe — Won’t Fix
    • 2024/06/19: Oracle Java java.exe — Pending Fix
    • 2024/06/19: Perl perl.exe — Won’t Fix
    • 2024/07/15: Perforce p4.exeCVE-2024-8067
    • 2024/08/05: PostgreSQL psql.exe — Won’t Fix
    • 2024/08/08: Putty plink.exe — Fixed
    • 2024/08/19: OpenSSL openssl.exe — Other
    • 2024/08/19: wkhtmltopdf wkhtmltopdf.exe — EOL
    • 2024/08/19: GNU Wget — No Reply

बचाव उपाय और बचा हुआ attack surface

  • WorstFit हमला operating system स्तर की समस्या है, इसलिए जब तक Microsoft सभी Windows editions में UTF-8 को default रूप से enable नहीं करता, इसी तरह की issues बार-बार सामने आ सकती हैं
  • users जो कर सकते हैं, वह है Windows के UTF-8 option को check करके enable करना
    • यह feature अभी भी beta stage के रूप में दिखाया जाता है, और side effects होंगे या नहीं, यह निश्चित नहीं है
  • developers को जहां तक संभव हो Wide Character API का उपयोग करना चाहिए
    • CRT भी _wgetcwd, _wgetenv जैसे wide character versions प्रदान करता है
    • अगर non-wide paths का उपयोग जारी रखा गया, तो internal implementation ANSI API को call कर सकती है और WorstFit हमले के exposure में आ सकती है
  • Windows की backward compatibility के कारण ANSI API और भी जगहों पर छिपी हो सकती हैं
    • उदाहरण के तौर पर RegQueryValueA जैसी Windows Registry query प्रभावित हो सकती है, लेकिन vulnerable scenario खोजने होंगे
    • research team ने Active Directory में भी Best-Fit behavior observe किया

1 टिप्पणियां

 
GN⁺ 2025-01-10
Hacker News की रायें
  • यह काफ़ी पेचीदा समस्या है। Microsoft की “best fit” code mapping एक सार्वजनिक, लेकिन असल में “अंदाज़े पर आधारित” mapper है, जो व्यापक Unicode को ASCII में बदलता है और पूरे सिस्टम में फैला हुआ है।
    यह mapper बहुत-सी जगहों पर default रूप से linked रहता है, और Microsoft जिस तरह backward compatibility को देखता है, उससे लगता है कि यह आगे भी शामिल रहेगा। Exploit आम तौर पर तब निकलते हैं जब अजीब code points “अहसास के हिसाब से” slash, hyphen, quotes जैसी चीज़ों में map हो जाते हैं। Modern language के अंदर इन्हें सही Unicode के रूप में validate किया जाता है, लेकिन shell command या Win32 API में जाते ही control सौंपने के बाद ये एक अलग तरीके से संकुचित रूप में convert हो जाते हैं। curl maintainer के शब्दों में, यहाँ “curl पीड़ित है”, लेकिन सवाल यह है कि अपराधी कौन है। अगर server user input को validate करते समय और system library को पास करते समय उसे अलग-अलग तरह से दबा/बदल देता है, तो आखिरकार समस्या होगी। Win32 की तरफ़ best fit conversion बंद करने का option समाधान हो सकता है, लेकिन मैं Windows expert नहीं हूँ, इसलिए यह अनुमान है। ऐसा करने पर भी official API या उन software के साथ interaction जारी रहेगा जिन्होंने अभी इसे बंद नहीं किया है।

    • opt-out का मतलब Unicode Windows API इस्तेमाल करना है, यानी "a" पर नहीं बल्कि "w" पर खत्म होने वाले functions इस्तेमाल करना। यह तरीका "\\?\" prefix लगाने या manifest को सही तरीके से set करने पर 260 characters से ज़्यादा path वाली समस्या भी साथ में हल करता है, और Windows XP के बाद से उपलब्ध और recommended रहा है।
      Non-Unicode API अभी भी इतनी आम क्यों इस्तेमाल होती हैं, यह मुझे ठीक से समझ नहीं आता। यह कल्पना करना मुश्किल है कि वजह Windows 98 या Windows 2000 support करने की इच्छा है।
    • Windows में Windows XP से manifest file मौजूद है, जो legacy behavior बंद करने का तरीका है। मेरी याद में, manifest न होने पर GetWindowsVersion तक current version return नहीं करता था। इसमें opt-out जोड़ना और किसी दिन इसे Visual Studio का default बनाना बहुत मुश्किल नहीं लगता।
      एक और ज़रूरी चीज़ किसी तरह की linting है। Modern applications में ANSI WinAPI functions call करने की आम तौर पर कोई वजह नहीं होती। Locale को UTF-8 पर set करके सिर्फ़ 8-bit functions इस्तेमाल करने का तरीका भी हो सकता है, लेकिन वह कितना ठीक चलता है, पता नहीं। मेरी जानकारी में कुछ settings और headers भी हैं जो argv, printf, std::cout को UTF-8 में काम करने देते हैं और अजीब conversion के बिना WinAPI के लिए सिर्फ़ UTF-8/UTF-16 conversion functions इस्तेमाल करवाते हैं। Microsoft को यह प्रक्रिया एक जगह document करनी चाहिए।
    • Security vulnerability हो या न हो, अगर Windows पर Unicode arguments को ठीक से handle नहीं किया जा रहा है तो यह curl का bug भी है।
    • Code points को characters में ढीले-ढाले तरीके से map करने का तरीका Unicode में हमेशा खटकता रहा है।
  • यह कुछ हद तक predictable है, लेकिन W/A confusion के दौर में करीब 10 साल Windows development और Wine API hacking करने वाले के तौर पर भी मेरे लिए यह नया था।
    Windows card game Munchkin जैसा है: कई features संयोग से ऐसे जुड़ जाएँ तो वे अविश्वसनीय रूप से random और powerful exploit में बदल सकते हैं। यह अच्छी बात है कि ANSI subsystem को UTF-8 में बदला जा रहा है, और theory में इससे ऐसी बहुत-सी समस्याएँ कम हो सकती हैं। यह भी उत्सुकता है कि Rust team को process creation API में एक और fix करना पड़ेगा या नहीं।

    • Rust standard library default रूप से ANSI API का लगभग इस्तेमाल नहीं करती। लेख में Rust पर काम करने वाला attack नहीं दिखाया गया, और अगर ऐसा कोई attack है तो उसे ज़रूर report करना चाहिए।
      बेशक Rust process boundary के पार होने वाली चीज़ों को control नहीं कर सकता। Rust द्वारा चलाया गया application अगर ANSI API इस्तेमाल करता है, तो समस्या उस तरफ़ होगी, लेकिन वह उस application की ज़िम्मेदारी है।
  • अगर मेरी याद सही है, तो “ANSI को धीरे-धीरे हटाना और Wide Character API के इस्तेमाल की सिफ़ारिश करना” NT 3.5 के समय से Microsoft की official position रही है।
    दुर्भाग्य से, बड़ी अड़चनों में से एक Microsoft की C/C++ runtime library msvcrt.dll का implementation तरीका है। _wfopen(), _wgetenv() जैसे non-standard wide functions internally Win API के W functions इस्तेमाल करते हैं, लेकिन fopen(), getenv() जैसे standard narrow functions wide version में convert करने के बजाय सीधे A functions इस्तेमाल करते हैं। और A functions आम तौर पर Unicode conversion failure report नहीं करते, बल्कि best-fit तरीके से ढक देते हैं। C में लिखे software को Windows पर port करने वाला कोई व्यक्ति standard functions के इस्तेमाल को पूरी तरह Microsoft के non-portable functions से बदलना नहीं चाहेगा। उस point से यह असल में full rewrite जैसा हो जाता है।

    • पिछले 2 साल में Microsoft docs पढ़कर मेरा impression उलटा था। दिशा यह लगी कि application manifest में activeCodePage को UTF-8 पर set करें और सिर्फ़ “ANSI” functions इस्तेमाल करें।
    • Portable code में Windows build के लिए main और fopen जैसे standard functions को wide counterparts में #define किया जाता है।
      इससे char* और plain string literals सीधे इस्तेमाल नहीं किए जा सकते, इसलिए tchar type define किया जाता है, जो Linux पर char और Windows पर wchar_t होता है, और string literals के लिए _T() macro define किया जाता है। आम तौर पर बिना ज़्यादा सोचे यह ठीक काम करता है।
    • आजकल सच में चिढ़ाने वाली बात यह है कि Google पर Win32 API search करने पर हमेशा -W variant के बजाय -A variant पहले आता है। robots.txt में कुछ अजीब है या नहीं, पता नहीं, लेकिन जिस API के लिए नए code में -W variant इस्तेमाल करने की recommendation है, उसका default रूप से legacy API return होना अजीब है।
    • Microsoft की C/C++ runtime msvcrt.dll को Universal C Runtime(UCRT)[1] ने replace कर दिया है, और UCRT C99 compliant है।
    • Windows को pathnames को इस मूर्खतापूर्ण encoding handling के बिना सीधे byte sequence की तरह treat करने वाली API देनी चाहिए थी। UNC paths introduce करते समय शायद ऐसा किया जा सकता था।
  • खुद लिखे application या patched EXE में “Ansi” code page को सचमुच UTF-8 पर force करने के दो तरीके हैं।
    एक manifest file इस्तेमाल करना है, और यह Windows 10 के कुछ specific builds से काम करता है। इसे build के बाद किसी भी EXE पर भी apply किया जा सकता है, इसलिए program में जबरन UTF-8 support डाला जा सकता है। यह console mode programs के लिए खास तौर पर उपयोगी है। दूसरा “App Locale” जैसे tools द्वारा इस्तेमाल की जाने वाली hack अपनाना है। एक तरीका NTDLL की undocumented function call शामिल करता है। ठीक कौन-सा function चाहिए, पता नहीं, लेकिन RtlInitNlsTables और RtlResetRtlTranslations संबंधित हो सकते हैं।

  • Microsoft सभी Windows editions में UTF-8 को default रूप से चालू करेगी या नहीं, यह पक्का नहीं है। बहुत-सी पुरानी applications किसी खास code page या प्रति character 1 byte मानकर चलती हैं, इसलिए वे टूट सकती हैं।
    इससे भी subtle बात यह है कि कुछ applications wide characters से ANSI में convert करते समय bytes की संख्या नहीं बढ़ेगी, ऐसा मानकर मौजूदा buffer को reuse करती हैं। UTF-8 में ऐसा नहीं होता, और पुराने code pages में ज़्यादातर यह सही बैठता था, इसलिए नई vulnerabilities बन सकती हैं। इसके बजाय Win32 xxxA API से Best-Fit logic हटाकर, जिन characters को map नहीं किया जा सकता उन्हें ऐसे x जैसे character से बदलना, जिसका कोई common meta meaning न हो, कहीं कम breakage वाला लगेगा।

    • ऐसी application का एक उदाहरण Adobe After Effects है[0]। कम से कम पहले ऐसा था, अब मैं Windows इस्तेमाल नहीं करता।
      [0] https://tambre.ee/blog/adobe_after_effects_windows_utf-8/
    • अगर अभी तक नहीं है, तो OS API versioning लाकर नए API version या नए SDK को target करने वाली नई/updated apps को default रूप से UTF-8 assume करने दिया जा सकता है। किसी खास API version से नीचे legacy mode में emulation कर दी जाए। Windows में पहले से ही कई Windows versions के behaviour की नकल करने वाला shim concept है।
    • UTF-8 से पहले वाले Windows में भी default code page बदलने पर apps के अजीब व्यवहार करने की समस्या पहले से थी। इसलिए users को UTF-8 option देना वाजिब है।
      Best-Fit mapping से पैदा होने वाली समस्याओं को देखते हुए इसे default बनाना भी वाजिब है, लेकिन Microsoft को users को पुराना code आसानी से चलाने का तरीका खोजने में मदद करनी होगी। कम वाजिब तरीका यह होगा कि Best-Fit mapping से “special” ASCII characters तक जाने वाली सारी mappings हटा दी जाएं, लेकिन static रूप से CRT link करने वाली apps को इससे मदद नहीं मिलेगी। यह vulnerabilities को भी ठीक नहीं करेगा, इसलिए अच्छा समाधान नहीं है। कभी-कभी security vulnerability backward compatibility तोड़ने को आगे बढ़ाने की वजह बन जाती है।
  • Microsoft को कम से कम 1 साल पहले से इस समस्या की जानकारी थी। क्योंकि उसने CA2101[1] नाम का खास code analysis rule जारी किया था, जिसमें best-fit mapping के इस्तेमाल को स्पष्ट रूप से discouraged किया गया था।
    Rule description में security vulnerability का जिक्र था, लेकिन details को जानबूझकर vague रखा गया था।
    [1] https://learn.microsoft.com/en-us/dotnet/fundamentals/code-a...

  • हर चीज़ को char * से wchar * में बदलने की जरूरत नहीं है। मिले हुए wide characters को UTF-8 में convert कर दें, या अगर unpaired surrogates जैसी invalid sequences तक allow करनी हों तो Rust के WTF-8 जैसी किसी चीज़ में convert करके आगे भी char इस्तेमाल कर सकते हैं।
    बेशक ANSI या OEMCP strings को UTF-8 strings के साथ mix न करने का ध्यान रखना होगा, लेकिन सिर्फ UTF-8 इस्तेमाल करें तो आसान है। Classic https://utf8everywhere.org/ site इसी approach की सिफारिश करती है।

  • अपने personal Windows computer पर कुछ सालों से UTF-8 mode चालू रखा हुआ था, इसलिए अनजाने में इस bug से बचा हुआ था। यह वही setting है जो article के नीचे दी गई है।
    पुराने foreign games में खराब characters दिखते थे, इसलिए इसे चालू किया था, और “Beta” लिखा होने के बावजूद मुझे कोई bug या side effect महसूस नहीं हुआ।

    • दिलचस्प है, लेकिन मेरे मामले में उस checkbox ने random apps को बहुत ज्यादा crash कराने के अलावा कुछ नहीं किया। लगता है कि इसके सही काम करने पर यह निर्भर करता है कि बंद होने पर user का default code page क्या है।
    • अभी-अभी “Beta: Use Unicode UTF-8 for worldwide language support” option चालू किया है। देखना दिलचस्प होगा कि कितनी apps टूटती हैं।
  • मैं सोच रहा था कि beta checkbox manifest में ActiveCodePage को UTF-8 पर set करने जैसा ही है या नहीं, लेकिन docs[0] देखने पर साफ है कि GDI per-process code page को follow नहीं करता और checkbox द्वारा set किए गए single global code page को ही follow करता है।
    अपनी app में *A API के लिए पूरी तरह UTF-8 में opt-in न कर पाना थोड़ा अफसोसजनक है। फिर भी article में highlight की गई समस्याओं के लिए यह अभी भी valid workaround या defense-in-depth measure हो सकता है।
    [0] https://learn.microsoft.com/en-us/windows/apps/design/global...

  • हे भगवान। मुझे पता था कि Windows API इस तरह का best-fit conversion देती है, लेकिन यह नहीं पता था कि मेरे default code page 949[1] में कई ANSI functions का default behaviour यही है।
    इस point पर तो इसे gets की तरह बस ban कर देना चाहिए। [1] मुझे पता है कि UTF-8 code page 65001 मौजूद है। लंबे समय तक यह सचमुच इस्तेमाल के लायक नहीं था, और अब भी compatibility problems झेल रहा है।