Avatar billede mydream Nybegynder
07. december 2011 - 11:01 Der er 9 kommentarer og
1 løsning

Sql injection og logins til MSSQL

Jeg er flere gange blevet ramt af SQL Injection og har forsøgt at forsvare mig mod det.

Mit spørgsmål er:
jeg har et login til MSSQL, som bruges på frontend og et login som kun bruges der hvor jeg selv er logget ind.

Når der forsøges SQL injection fra frontend, bør det så ikke kun få indflydelse på de tabeller, hvor jeg har givet mit offentlige login permission til at update/delete/inserte?

Bør det ikke være sådan, at hvis jeg har en tabel, hvor det offentlige login ikke har permissions til, så er den tabel sikker?
Avatar billede keysersoze Guru
07. december 2011 - 11:40 #1
Som jeg forstår din forklaring så jo - har den pågældende connections bruger kun skrive-rettigheder kan man via SQL Injection ikke slette.

Nu ved jeg ikke hvor langt du er i dit forsvar, men selvom flere brugere med hver deres rettigheder er en fremragende idé bør det ikke være forsvaret mod SQL Injections - det bør derimod være din kode, primært ved brug af parametre.
Avatar billede mydream Nybegynder
07. december 2011 - 11:51 #2
Jeg har godt set det med parametre, men jeg har et virkelig stort site + 3 mellemstore, så det vil tage mig en evighed at lave alt om. Dertil kommer at jeg ikke har erfaring med parametre.

Jeg tænkte at jeg kunne gøre det med de forskellige logins og så dertil gøre noget ekstra (f.eks. parametre) der hvor brugerne via debatforum, anmeldelser mm. har adgang til at ændre i databasen.

Hvorfor skriver du at du ikke synes at det er nok i forsvaret mod injections?
Avatar billede softspot Forsker
07. december 2011 - 11:54 #3
Det er vel ikke kun et spørgsmål om at der kan slettes eller rettes i data, men også om data er sikre mod uvedkommendes snagen...? I så fald er det vel bedst helt at undgå SQL-injections og som keysersoze skriver, så er parameteriserede forespørgsler til databasen vejen frem. Både keysersoze og jeg selv (blandt andre) har skrevet artikler om emnet. Min egen ligger her på eksperten: www.eksperten.dk/guide/1250
Avatar billede mydream Nybegynder
07. december 2011 - 12:02 #4
Smiler - ja det link var jeg gået i gang med, men det er lidt over mit niveau. Du har ret i det med snagen, men det er ikke tophemmelige ting, jeg har liggende i databasen.

Hvis jeg nu skal starte med parametre et sted, hvor er det så typisk, at man bliver angrebet? Er det et tilfældigt sted eller vil det være et sted som debatforum eller anmeldelser?
Avatar billede softspot Forsker
07. december 2011 - 12:38 #5
Jeg er faktisk ikke inde i det skidstfolks tankegang, men jeg vil tro det handler om at finde en vej ind - og i den opgave er ingen midler vel for dårlige. Jeg kunne forestille et forsøg på, med vilje - selvsagt :-) - at angive ugyldige data for at få siden til at fejle og udlevere kostbare oplysninger om datastrukturer og/eller databaseplacering/-forbindelsesoplysninger osv. som kan bruges til det videre angreb...

Når man så ved lidt mere, vil man givetvis forsøge at lure hvordan sidens kode i øbrigt er skruet sammen og angribe der hvor man tror huller kunne eksistere.

Men som sagt, er det ikke noget jeg har brugt meget energi på at lure (hvilket nok er en stor fejl!). Jeg har bare lært, at man skal være paranoid, når det kommer til sikkerhed (ikke kun SQL Injections, men også XSS og CSRF er i top 5 over mest gængse sikkerhedsproblemer på en stor del af internettes websites).

Teknikken med Command-objektet behøver ikke være meget mere kompliceret end at kalde Execute direkte på connectionobjektet. Det drejer sig som udgangspunkt om at få lavet nogle centrale rutiner der understøtter brugen og så vil 80-90% af dine opslag være lige så simple som at benytte de traditionelle sammensatte SQL-sætningen og conn.execute.

Eksempel:

sql = "SELECT felt1, felt2 FROM tabel1 WHERE id = ?"
set cmd = GetCommand(sql)
set rs = cmd.Execute( , array(request.QueryString("id")))
do while not rs.eof
  ' do your thing
  rs.MoveNext
loop
rs.close

Personligt synes jeg ikke dette er mere kompliceret at overskue eller kode, for den sags skyld, end sammensatte SQL-sætninger (snarere mindre) og så er det meget mere sikkert!

Denne kode læner sig op af nogle forudsætninger, nemlig at GetCommand er i stand til at oprette og returnere et commandobjekt og forbinde det til en database (via et connection-objekt). Den kode kan sagtens ligge i en includefil, som du blot skal sørge for at inkludere i de sider hvor databaseopslag skal bruges. Du inkluderer givetvis en fil med connectionoplysninger i forvejen, så du kunne blot definere funktionen i denne fil og være klar til arbejdet med commands på alle relevante sider...

Husk det ikke kun er input fra formularfelter der kan være farlige. Alt hvad der komme udefra (cookies, importerede data fra kilder du ikke har tillid til (alle andre end dig selv!) er også kandidater for SQL-Injections og XSS. Det er meget muligt at kilden ikke selv har onde intentioner, men hvis kilden ikke selv er tilstrækkeligt beskyttet mod disse angreb, kan du risikere også at komme til at lide under dette. Den risiko er der jo ingen grund til at tage på sig :-)
Avatar billede mydream Nybegynder
08. december 2011 - 09:41 #6
I forhold til parametre, hvad står de tre tal så for?

Cmd.Parameters.Append(Cmd.CreateParameter("id", 3, 1, 50, Request.Querystring("id")))
Avatar billede mydream Nybegynder
08. december 2011 - 09:57 #7
Og hvorfor må jeg ikke pakke dette kodestykke ind i en function, som kan kaldes (så jeg ikke skal skrive det hver gang)

function open()
Set Conn = Server.CreateObject("ADODB.Connection")
strDSN = application("dbconn")
Conn.Open strDSN
Set Cmd = Server.CreateObject("ADODB.Command")
Cmd.ActiveConnection = Conn
end function

open()
Avatar billede softspot Forsker
08. december 2011 - 11:02 #8
Ad #6: benyt den korte form jeg refererede til, så skal du ikke tænke på CreateParameter og Parameters.Append :-)

Ad #7: Jeg vil tro du mangler at erklære (populært kaldt at Dim'e) Conn og Cmd-variablerne udenfor funktionen...

Jeg vil dog umiddelbart anbefale at du splitter de to handlinger op, således du har et sæt funktioner til at åbne og lukke forbindelsen til databasen og en der opretter et commandobjekt.

Eksempel:

function OpenConn()
  Set Conn = Server.CreateObject("ADODB.Connection")
  strDSN = application("dbconn")
  Conn.Open strDSN
  set OpenConn = conn
end function

function CloseConn(conn)
  on error resume next
  conn.close
end function

function GetCommand(conn, sql)
  Set Cmd = Server.CreateObject("ADODB.Command")
  set Cmd.ActiveConnection = Conn
  cmd.commandtext = sql
  cmd.commandtype = 1
  set GetCommand = cmd
end function

Bemærk at du med dette setup så lokalt skal vedligeholde en connection-variabel, samt sende denne connectionvariabel med til GetCommand-funktionen.

Eksempel:

dim cn, cmd, rs, sql

sql = "SELECT felt1, felt2 FROM tabel1 WHERE id = ?"
set cn = OpenConn()
set cmd = GetCommand(cn, sql)
set rs = cmd.execute(, array(request.querystring("id")))

' do the looping-thing!

rs.close
set rs = nothing
call CloseConn(cn)
set cn = nothing

NB: Du behøver ikke være bekymret for at åbne og lukke forbindelsen mange gange, da der er connection pooling på IIS senere end version 5, såvidt jeg husker...

Vær desuden opmærksom på at hvis der sker en fejl, vil din forbindelse, med denne metode, ikke blive lukket igen, så du skal sørge for at håndtere fejl og få lukket din forbindelse hver gang.

Aternativt kan du pakke de tre funktionaliteter ind i en class. Det giver også mulighed for at håndtere lukning af en evt. åben forbindelse, hvis der skulle ske en fejl, mens den er åben.

Eksempel:

class Database
  private conn
  private strConn

  private sub class_initialize()
    strConn = ".. dine forbindelsesinformationer .."
    set conn = nothing
  end sub

  private sub class_terminate()
    call Close()
  end sub

  public sub Open()
    call Close()
    set conn = Server.CreateObject("ADODB.Connection")
    conn.Open strConn
  end sub

  pubilc sub Close()
    on error resume next
    if not conn is nothing then
      conn.close
    end if
    set conn = nothing
  end sub

  public function GetCommand(sql)
    dim cmd
    if conn is nothing then
      call Open()
    end if
    set cmd = Server.CreateObject("ADODB.Command")
    set cmd.ActiveConnection = conn
    cmd.CommandText = sql
    cmd.CommandType = 1
    set GetCommand = cmd
  end function
end class

' Opret et globalt db-objekt, så det er let at referere til
dim db
set db = new Database

Denne klasse benyttes så således:

dim cmd, sql, rs

sql = "SELECT felt1, felt2 FROM tabel1 WHERE id = ?"
set cmd = db.GetCommand(sql)
set rs = cmd.execute(, array(request.querystring("id")))

' do the looping-thing!

rs.close
set rs = nothing
db.Close

Nu behøver du ikke tænke på om der sker fejl og siden lukker før forbindelsen, for når siden ophører med at eksistere, vil Database-klassens Class_Terminate-event blive kaldt... også selvom der er sket en fejl. Det er standard COM-opførsel :-)
Avatar billede mydream Nybegynder
08. december 2011 - 20:22 #9
Softspot, du må meget gerne lægge et svar. Jeg har ikke fået det helt til at virke endnu, men jeg nærmer mig.
Avatar billede softspot Forsker
08. december 2011 - 22:11 #10
Sig til hvis der er noget ang. mine foreslag du skal have hjælp til... :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester