Avatar billede heavybreezer Nybegynder
13. september 2003 - 16:00 Der er 13 kommentarer og
2 løsninger

Forhindre SQL hack?

Jeg har lavet et loginsystem på min hjemmeside, men da jeg viste det til en kammerat, viste han mig noget..

Han kunne "hacke" sig ind.. Han kunne logge ind, som den sidst oprettede bruger, UDEN brug af password og brugernavn. Han fik selvfølgelig lov! ;)

Men han viste mig dette, som er fundet på nettet:

-------------------------------------------------------
SQL Hacking
--------------------------------------


Mange webprogrammoerer taenker sig ikke om naar de skriver kode.
Mange firmaer ansaetter folk der er selvlaerte og som ikke har
nogen reel erfaring med virkelige systemer. Derfor opstaar der
til tider kode der ikke er gennemtaenkt. Jeg vil i denne artikel
gennemgaa hvordan man udnytter det mest ugennemtaenkte hul.

Mange dynamiske sider der er lavet i asp, php eller lign.
vil have et administrations modul. For at faa adgang til dette
modul skal man indtaste et brugernavn og en adgangskode.
"Hullet" opstaar hvis brugernavn og adgangskode sendes direkte
til databasen. Lad os tage et eksempel:

Vi forestiller os at der i html koden findes to input felter,
et der hedder username og et der hedder password. Strengen der
smides efter databasen vil kunne se saaledes ud (php-like):

sqlstring = SELECT * FROM user WHERE usernm='$username' AND passwd='$password';

forklaring: vaelg alt fra tabellen "user" hvor attributen "usernm"
er lig med det indtastede i feltet "username" og attributen "passwd"
er lig med det indtastede i feltet "password". Det hele laegges ind i
streng variablen sqlstring og den sendes herefter til databasen.
Det der saa kommer tilbage vil vaere en bruger, hvis brugernavnet
eksisterer og adgangskoden er korrekt. Det ser jo alt sammen fint ud.
Problemet opstaar saa hvis man istedet for brugernavn og adgangskode
indtaster gyldig SQL. Det forventes at alt mellem ' og ' er et
brugernavn. Hvis man starter feltet "username" med en ' afsluttes
attributen "usernm" med det samme og resten af linien fortolkes
som SQL. Det samme gaelder for feltet "password".

Nu skal vi saa overveje hvad vi kan goere for at overbevise
databasen om at vi skal have noget retur, for hvis vi ikke faar
noget retur tror script sprogret ikke at brugernavnet findes.

Vi starter vores brugernavn felt med ' og tilfoejer noget der
altid vil vaere sandt. Noget vi altid kan bruge, som altid vil vaere
sandt er ingenting er lig med ingenting, eller 0=0. Nu skal vi saa
bare lige soerge for at afslutte vores brugernavn felt med en '
for at terminere vores SQL saetning. Her henledes tankerne paa ''=''
der altid vil vaere sandt. For at faa den ud af "usernm='$username'" skal vi
som sagt starte og slutte med '. Derfor vil kunne noejes med

'or''='

der vil afslutte scriptets SQL og indsaette vores, som saa vil afsluttes
til sidst, da vi nemlig opnaar:

"usernm=''or''=''"

Det vil altid vaere sandt. Det samme gaelder for adgangskode feltet.
I de fleste tilfaelde vil den foerste bruger der bliver oprettet vaere
admin eller en tilsvarende bruger med mange rettigheder. Men hvis man
vil vaere sikker paa at vaere en bestemt bruger kan man bare indtaste det
som brugernavn. For adgangskoden vil stadig altid vaere rigtig, og man
vil faa adgang som den bruger man har indtastet.

Hvis du vil undgaa at dette sker for dig, saa kan man let omgaa problemet.
Hvis man anvender php kan man udnytte metoderne addSlashes og
addHtmlSpecialChars, der vil tilfoeje esc characters og lave vores SQL
streng om til \'or\'\'=\' og derfor vil det ikke vaere gyldig SQL laengere.

En anden maade at sikre sig paa kunne vaere at man ikke sender
adgangskoden til databasen, men kun brugernavnet, og saa selv tester
for om adgangskoden er korrekt med sit script. Naar man nu er igang
kunne man overveje at tjekke for hvor mange brugere databasen returnerer.
Returnerer den mindre end 1 findes brugernavnet ikke, og returnerer den
flere end 1 er der opstaaet en fejl, under forudsaetning af at brugernavnet
er unikt. Er der flere end 1 er det man overvejer om det er et
forsoeg paa et hack.

Nu hvor vi er i gang med sikkerheden skulle man overveje enten at
lave en ssl forbindelse mellem bruger og server, eller at have
brugernavnene i databasen krypteret og kryptere adgangkoden paa klient siden
med javascript og saa undersoege om de to krypterede adgangkoder er det samme.
---------------------------------------------------------

Hvordan undgår jeg dette sker for mig?!
Jeg har prøvet og prøvet, men kan stadig "logge ind", ved at hacke mig selv

Og hvis han kan gøre det ved mig, hvad forhindrer så en anden??
Avatar billede squashguy Nybegynder
13. september 2003 - 16:05 #1
mysql_escape_string() kan du bruge til at udskadeliggøre alle strenge. eksempel:


$user = mysql_escape_string($user);
$sql = "select * from bla where user='$user'";
Avatar billede squashguy Nybegynder
13. september 2003 - 16:07 #2
sql injection er en meget udbredt teknik til at hacke hjemmesider, da mange glemmer at tage højde for dette.
Avatar billede fangel Nybegynder
13. september 2003 - 16:11 #3
eller bare

addslashes() der 'uskadeligører' tegn som

'
"

osv...

---

man skal altid have sådan nogle ting i baghovedet - ligsom man også skal uskadeligøre html tegn (eller fjerne dem)... de kan uskadeligøres emd

htmlentities()

Morten
Avatar billede fangel Nybegynder
13. september 2003 - 16:11 #4
hov, det med addslashes stod der...
Avatar billede heavybreezer Nybegynder
13. september 2003 - 16:12 #5
Kan du ikke sætte din kode ind i denne:

<?
include ("config.php");
mysql_connect($host,$user,$pass);
mysql_select_db($db);
$query = mysql_query("SELECT navn, password, email, id FROM community WHERE navn='$navn' AND password='$password'");
if (mysql_num_rows($query) == "0"){
?>

Det er min.....

Sorry, men har ikke den helt store erfaring med php :)
Avatar billede heavybreezer Nybegynder
13. september 2003 - 16:14 #6
Den sidste kommentar til squashguy  :)
Avatar billede fangel Nybegynder
13. september 2003 - 16:17 #7
desuden vil det også hjælp med disse 2 tiltag:

register_globals = off

--- forklaring ---

fordi man tjekker om man er logget ind via cookie, og sp bare tjekker om cookien findes ved

if($cookienavn){

dette vil kunne omgås med fil.php?cookienavn=1

For at se om cookien findes bliver ma så nød til at at tjekke mod $_COOKIE['cookienavn'] - denne kan ikke fås via fx adresselinie

---

error_reporing = E_ALL

--- forklaring ---

alle fejl bliver vidst, dvs man blive nød til at indføre mere fejlsikre metoder - tjekke om variabler er sat med isset() istedet for bare at tjekke på variabelens navn...

---

desuden kan det være godt med eget error_handling/output_buffering system, da man så kan fjerne den del af siden der er blevet genereret, og bbare vise en standard fejlmedelelse!

så vil en evt hacker ikke få videre indsigt i din side ved små uskyldige fejl!

Morten
Avatar billede squashguy Nybegynder
13. september 2003 - 16:20 #8
<?
include ("config.php");
mysql_connect($host,$user,$pass);
mysql_select_db($db);

$navn = mysql_escape_string($navn);
$password = mysql_escape_string($password);

$query = mysql_query("SELECT navn, password, email, id FROM community WHERE navn='$navn' AND password='$password'");
if (mysql_num_rows($query) == "0"){
?>
Avatar billede heavybreezer Nybegynder
13. september 2003 - 16:21 #9
dea_pg -> Du skriver meget, men kan ikke helt forstå det... :|
Sorry, men jeg er sgu ikke så god til dette...

En login.html, hvor en form så poster password input og bruger input til godkend.php.... Og den ser sådan ud:

<?
include ("config.php");
mysql_connect($host,$user,$pass);
mysql_select_db($db);
$query = mysql_query("SELECT navn, password, email, id FROM community WHERE navn='$navn' AND password='$password'");
if (mysql_num_rows($query) == "0"){
?>
<center>
<font color="red">Forkert Navn og/ell. Kodeord</font><br>
Prøv igen eller opret dig som medlem.
</center>
<?
} else {
while($r = mysql_fetch_array($query)) {
$s_navn = $r["navn"];
$s_password = $r["password"];
$s_email = $r["email"];
$s_id = $r["dato"];
}
session_start();
session_register ("s_navn");
session_register ("s_password");
session_register ("s_email");
session_register ("s_id");
header ("location: test.php");
}
?>

Kan du ikke prøve at sætte de ting ind, som du siger??
Avatar billede fangel Nybegynder
13. september 2003 - 16:22 #10
<?

include ("config.php");

$dbhandle = mysql_connect($host,$user,$pass)or die(mysql_error());
mysql_select_db($db, $dbhandle)or die(mysql_error()); // se kommentar 1


$navn = htmlentities(addslashes($_POST['navn']));
$paswd = htmlentities(addslashes($_POST['password'])); // gætter på det kommer fra form - se kommentar 2

$query = mysql_query("SELECT navn, password, email, id FROM community WHERE navn='$navn' AND password='$paswd'")or die(mysql_error());
if (mysql_num_rows($query) == "0"){
?>

---

1) tilføjet brug af 'or die(mysql_error())' ved fejl vil scriptet stoppe, og udskrive mysqs fejlmed.
desuden er der tilføjet brug af dbhandle, så select_db bliver nød til at bruge det connect (meget paranoidt - men ok)

2) tilføjet htmlentities() og addslashes() - så bliver ' + " og html uskadelig gjodt...
desuden blives $_POST[] til at få fat på variablerne så de ikke kan komme via adresselinie (eller cookie eller andet)

---

til register_globals skal du bruge følgende prefixes

$variabelnavn = variabler du selv har lavet i scriptet
$_GET['variabelnavn'] = fra adresselinie
$_POST['variabelnavn'] = fra en form
$_COOKIE['variabel']
Avatar billede fangel Nybegynder
13. september 2003 - 16:24 #11
hov, fik trykket udfør

$_COOKIE['variabel'] = fra cookie
$_SESSION['variabel'] = fra session
$_SERVER['variabel'] = ting som PHP_SELF
$_FILES['variabel'] = bruges til filupload - læs manualen for forklaring

---

bare brug

$_SESSION['s_navn'] = $s_navn;

til at skrive til session - det er den nye måde at køre det på

Morten
Avatar billede heavybreezer Nybegynder
13. september 2003 - 16:24 #12
Tak begge to!
dea_pg -> lægger du et svar?
Avatar billede fangel Nybegynder
13. september 2003 - 16:38 #13
svaa'r

Morten
Avatar billede fangel Nybegynder
13. september 2003 - 17:00 #14
tak ;)
Avatar billede fangel Nybegynder
14. september 2003 - 10:42 #15
nu vi havde gang i det, så fandt jeg en artikel i PHP|Architect : "Wrting secure code i PHP" (du kan hente 1 nummer gratis fra www.phparch.com - det er denne månedes udgave)

der var også et afsnit om MySQL - det har jeg være så lumsk at copy past:


--- PHP|Architect 01/2003, side 55 - af Theo Spears ---
SQL

Whenever general web application security is men-tioned, SQL injection is never far away. SQL injection is when an attacker uses malicious data to change an SQL query, making it do something other than intended. For example supposing you had a query like

sql_query (  SELECT * FROM members WHERE user-name=  '$username'  AND password= '$password'  );

This would normally select all details about the cur-rent user from the database (checking their password at the same time). However, with a bit of imagination it can be made to do something more. Supposing $username is equal to  ; DELETE FROM members;  - . When the query is constructed by filling in the variables it becomes:

SELECT * FROM members WHERE username= ''; DELETE FROM members; -'      AND password= 'pass'

As you can see the query has become two queries, delimited by the semicolon (;), and will neatly wipe out your member list. The  -  at the end tells the SQL pars-er everything following it is a comment and prevents any parse errors. In SQL possibly dangerous characters are  ', ?  and \, assuming all your values are inside quotes.
In spite of the potential severity of SQL injection, usu-ally while programming in PHP you don t need to worry about it as often. The first reason for this is the PHP setting called magic_quotes_gpc. This automati-cally escapes any dangerous data coming from the user. For example  ; DELETE FROM members;  would become \ ; DELETE FROM members;  and would pre-vent the sql engine thinking it had reached the end of the string. This does not mean you can completely for-get about SQL injection. Data which does not come from the GPC variables (e.g. something selected from the database itself) is not protected. For this you need to use an escaping function.
The built-in escaping function in PHP is  'addslashes()'  . This should be safe enough. However, some database interfaces also provide their own functions, such as  'mysql_escape_string() '. If the extension your database uses has a function like this I suggest you use it. This means your code is more likely to stay cor-rect if that database engine is changed in some strange way.
The other reason it is not often a problem only applies to the MySQL database engine, but since the majority of PHP powered sites on the web use MySQL I feel justified in mentioning it. MySQL only allows one query per call to mysql_query, so in fact it is impossible to add another query adding or deleting from the data-base. It is still possible, however, to modify the query that is run, and MySQL version 4.0 offers many more features, so you should still be careful.
---

Det kan anbefales at du henter nummeret gratis og læser artiklen (starter side 50)

Morten
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
Vi tilbyder markedets bedste kurser inden for webudvikling

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