Protejare intr-un fel fisier PHP?

Am facut un sistem de “views”, merge super nicio problema. Dar intrebarea mea este daca fisierul .php poate sa fie vulnerabil?
Din HTML cu ajax fac apel catre “update_value.php”, in el este doar atat:

<?php
	$id = $_POST["sad"];
    $link = mysqli_connect("localhost", "root", "", "rpg");
    mysqli_query($link, "UPDATE vtab SET Views=Views+1 WHERE ID='$id'");
    mysqli_close($link);
?>

Daca il accesez in directorul in care este imi spune (DIN BROWSER): Notice : Undefined index: sad in C:\xampp\htdocs\index2\update_value.php on line 2.
Intrebarea mea este daca trebuie protejat intr-un fel sau e ok asa.

Daca inteleg eu bine, tu incerci sa deschizi fisierul ala de pe disk ? Daca da, eroarea respectiva este pentru ca atunci cand il deschizi asa, variabila $_POST nu este populata, asa cum este atunci cand faci un ajax request.

Pe langa asta, scriptul tau este vulnerabil la SQL Injection. Trebuie sa folosesti prepared statements ca sa scapi de aceasta vulnerabilitate

2 Likes

Stiu din ce cauza este eroarea, am spus ca totul merge perfect. L-am accesat din browser doar “ca idee” sa o expun aici. Insa intrebarea mea era doar daca trebuie protejat intr-un fel, adica spre exemplu sa nu-l mai poti accesa din browser ci doar atunci cand se face “ajax” din fisierul HTML.

Asigura-te de urmatoarele:

  • Te protejezi de input invalid
  • Te protejezi de sql injection

La ce este acolo, cam atat vad eu.

1 Like

Nu stiu de ce ai trecut cu vederea ce a zis Razvan mai sus, sql injection nu e de trecut cu vederea.

Poti sa verifici daca cheia aia exista inainte de a obtine valoarea (bail out daca nu exista), daca nu-ti place sa dea eroare asa.

Am incercat dar dupa nu se mai actualizeaza in baza de date… $id afiseaza doar INT, nu e varchar sau ceva.
Codul:

<?php
    $link = mysqli_connect("localhost", "root", "", "rpg");
    $id = $_POST["sad"];
    $id = mysqli_real_escape_string($id);
    mysqli_query($link, "UPDATE indexano SET Views=Views+1 WHERE ID='$id'");
    mysqli_close($link);
?>

Nu mai da, asa am facut si eu inainte. Dar e ok sa fie asa? Adica se pot accesa intr-un fel datele din .php sau n-are nimic daca ramane asa atata timp cat e protejat sql_injection?

Este suficient

$id = (int) $_POST["sad"];

Dar de unde iti vine $id?

Si cred ca poti folosi isset ca sa verifici daca intr-adevar ai ceva in acel post si in caz ca nu ai nimc sa dai un mesaj de eroare

if(!isset($_POST["sad"])){
    echo "post not net";
}
//le code 

Scuze ca tot editez!

Nici nu cred ca se pune problema de SQL Injection aici. ID vine de la un tabel din html in care este un foreach sa-mi afiseze niste articole. E ceva de genul: <a class=“bla bla” sid="’.$row[‘ID’].’", ID = ID-ul din baza de date a articolului.
JS:

$.ajax({
        type: "POST",
        data: { "sad": $(this).attr('sid') },
        url: "update_value.php"
    });

Iti dai seama ca nu tu esti ala care ar face sql-injection, ci altcineva, care ar posta in sad-ul ala cu totul altceva decat vrei tu.

1 Like

Try this:

curl -sk -d "sad=123" http://my.server.com/update_value.php

sau

curl -sk -d "sad=123' OR ID >'1" http://my.server.com/update_value.php
1 Like

Codul tău este vulenrabil la SQL injection, fară nici o îndoială.

  1. În anului Domnului 2019 (spre 2020) îți recomand cu încredere să folosești PDO împreună cu Prepared Statements. O să ai câteva linii de cod în plus, dar te va scăpa de alte bătăi de cap.
  2. Dacă totuși nu vrei să folosești PDO, îti recomand să folosești filter_input pentru a procesa orice date venite din browser (request).
  3. Ca să întelegi mai bine să de ce codul tău este vulnerabil recomand OWASP, chiar dacă informațiile de acolo sunt mai greu de digerat pentru un începător, merită efortul.
5 Likes

Am rezolvat problema cu “is_numeric”, intrucat “SAD” nu este numar se returneaza cu 1, se anuleaza tot.

<?php
    $link = mysqli_connect("localhost", "root", "", "rpg");
    $id = $_POST["sad"];
    if(!is_numeric($id)) return 1;
    mysqli_query($link, "UPDATE indexano SET Views=Views+1 WHERE ID='$id'");
    mysqli_close($link);
?>

Presupunând că ăla e cam tot codul:

  • Dacă nu există parametrul $_POST[‘sad’], se va genera o eroare de care n-are nevoie nimeni.
  • Conectarea la baza de date ai putea s-o faci după verificarea parametrului.
  • De dragul discuției, căci nu va genera o eroare, “1.1” sau ‘-4.0002’ este numeric.
1 Like

E si o problema conceptuala la ce faci acolo, tu nu numeri de cate ori incarci o pagina ci de cate ori se face acel ajax request. De ce anume ai ales ajax? Poate ar trebui sa te protejezi si impotriva unui script care trimite automat acel request de pe alt server, de exemplu, ca sa nu poata umfla oricine views pt un anumit id fara ca macar sa incarce pagina.

Daca fisierul nu e accesibil din browser, atunci nu va fi accesibil nici prin Ajax. Ce mai poti face (pentru ca tu vrei ca scriptul ala sa fie apelat doar printr-o metoda post), este sa verifici la inceput daca metoda care apeleaza scriptul este POST. Daca nu este, poti sa intorci eroare, sau orice altceva. Asta o poti face in felul urmator:

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
 // error 
}
... <codul tau aici>

Daca mi-ai dat mai multe detalii cum as putea face asta ar fi super.

Multumesc, o sa pun si metoda asta + metoda is_numeric inainte de conectarea MySQL.