View Single Post
Limited edition
Moff's Avatar
For å svare på spørsmålet først; jeg kan ikke se noen grunn til at dette problemet skal oppstå på bakgrunn av selve spørringen:

Kode

DELETE FROM form WHERE secretKey='$skey' AND email='$delete'
Dette vil slette alle rader fra tabellen "form" som har secretKey satt til $skey og email satt til $delete. Det er derfor ting som tyder på at problemet ligger et annet sted. Det første jeg hadde gjort her er å dobbeltsjekke hva som faktisk skjer i databasen. Er du helt sikker på at det slettes rader som ikke skal slettes? Hvordan vet du at dette skjer?

Gi oss gjerne en liten oversikt over noe eksempeldata fra tabellen din før og etter, sånn at vi kan sammenligne og se nøyaktig hva det er som foregår.

Men problemet du opplever her er ubetydelig sammenlignet med hvilke problemer du vil få hvis du publiserer denne koden på internett. Du har en gedigen SQL-exploit her. Det du gjør er å ta input fra en klient via $_POST-arrayet, og så dytter du denne inputen rett inn i en SQL-spørring uten å sjekke hva det er brukeren har skrevet inn.

Hvis jeg har lyst til å være litt ugrei med deg, så vil jeg gå inn på tjenesten din og oppgi at min e-postadresse er dette:

Kode

';drop table form;/*
Spørringen din ser slik ut:

Kode

SELECT * FROM form WHERE email='$delete'
Når skriptet ditt skal behandle min "e-postadresse" ovenfor, så blir spørringen da slik:

Kode

SELECT * FROM form WHERE email='';drop table form;/*'
Først kjører vi en SELECT med blank e-postadresse, og deretter kjører vi en DROP TABLE, som sletter hele tabellen og alt innhold i den. Avhengig av hvilke rettigheter MySQL-brukeren din har, så kan man gjøre veldig mye tullball her.

Det du må gjøre er å sørge for at input er vasket og ikke kan tolkes som kommandoer i spørringen din. Alle gode SQL-biblioteker skal støtte det vi kaller prepared statements, som er en trygg teknikk for å skrive spørringen først, og deretter fylle inn variablene du skal bruke. Personlig bruker jeg PDO i stedet for MySQLi, men så vidt jeg kan se så er syntaksen for MySQLi slik:

Kode

$query= $conn->prepare("SELECT * FROM form WHERE email= ?");
$query->bind_param("s", $_POST['delete']);
$query->execute();

$result = $query->get_result();
$query->close();

if($result->num_rows == 0) {
// 0 rader funnet
}
If-blokken din er også litt merkelig satt sammen. Vanligvis så pleier vi ikke å mikse forskjellige conditions i samme if-blokk. Det skal fungere slik du har skrevet det, men det er ikke helt stuerent. Det jeg mener er at du først har en sjekk om om SELECT-statementen ga resultater, deretter har du en elseif som både kjører DELETE-statementen og sjekker om den gikk bra, og til slutt har du en else.

Det vil si at du har flere conditions som strengt tatt ikke har noe med hverandre å gjøre, og det er også derfor du kan få litt pussige resultater. Det er også verdt å nevne at mysqli_query returnerer false kun hvis noe har gått galt, ikke hvis spørringen kjørte uten noen affected rows. Du vil derfor se meldingen om at data har blitt slettet så lenge DELETE-statementen ble kjørt, uansett om noe ble slettet eller ikke. For å unngå dette må du se på resultatet av spørringen og num_rows, som demonstrert i kodeeksempelet mitt ovenfor. I SQL så er det generelt ikke bra å basere seg på noe annet enn row count (affected rows) for å sjekke hva som har skjedd.

Et siste tips jeg kan komme med, som du bør tenke over, er at det kan være lurt å gi brukerne dine falske opplysninger. I et system som dette, så ville jeg gitt tilbakemelding om at informasjonen er slettet selv om den ikke har blitt det - fordi det gjør det umulig for folk å mine data fra deg. Ta for eksempel reset-passord-funksjoner på ulike nettsider; når de sier ifra at e-postadressen du skriver inn ikke eksisterer i deres system, så kan det fortelle deg alt du trenger å vite. Er personen du er på jakt etter registrert her eller ikke? Se for deg at du har kommet over privat-e-posten til en politiker, og du finner ut at denne adressen er i bruk på et snuskete nettsted, for eksempel. Slike ting trenger du ikke å gi folk informasjon om hvis du ikke må.
Sist endret av Moff; 25. april 2019 kl. 23:00.