errore di sintassi e problema di modsecurity

Ciao a tutti, sono nuovo su questo portale e mi sto inoltrando nel mondo php.

Come ogni novizio sto riscontrando dei problemi nel creare alcune mie applicazioni, la maggior parte le risolvo con le ricerche su internet ma a queste due non riesco a trovare una soluzione, quindi mi rivolgo qui per cercare un'aiuto. Veniamo al dunque:

Il server mi restituisce un'errore del genere:

PHP Parse error:  syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in /home/www/html/edit.php on line 13,

la porzione di codice in questione è:

10. if($_GET['id'])
11.    header("Location: index.php");
12. // get id value
13. $sql = "select * from elenco_mat WHERE id = $_GET['id']";
14. $query = mysql_query($sql) or die("Query non valida: " . mysql_error());

se poi trasformo in questo modo:

10. $id = $_GET['id'];
11. $sql = "select * from elenco_mat WHERE id = $id";
12. $query = mysql_query($sql) or die("Query non valida: " . mysql_error());

sembrerebbe funzionare, ma a questo punto mi restituisce un'altro errore:

ModSecurity: Access denied with code 500 (phase 4). Pattern match "(?:\\b(?:(?:s(?:elect list because it is not contained in (?:an aggregate function and there is no|either an aggregate function or the) GROUP BY clause|upplied argument is not a valid (?:(?:M(?:S |y)|Postgre)SQL|O(?:racle|DBC)))|S(?:yntax error converti ..." at RESPONSE_BODY. [file "/etc/httpd/modsecurity.d/modsecurity_crs_50_outbound.conf"] [line "23"] [id "970003"] [msg "SQL Information Leakage"] [severity "WARNING"] [tag "LEAKAGE/ERRORS"] [hostname "localhost"] [uri "/edit.php"] [unique_id "UJD6nKwRCIQAAGrKErQAAAAD"]

e questo si riferisce quando vado a fare l'update :

if ($_POST['submit'])
      {
          $link=mysql_connect("$databaseHostName","$databaseUserName","$databaseUserPassword")       or die ("Non riesco a connettermi a $databaseHostName");
      mysql_select_db ($databaseName, $link) or die ("Non riesco a selezionare il db $databaseName<br>");          

                     
//trasformiamo in variabili i post
  
   $coord=$_POST['mod_coord'];
   $pos=$_POST['mod_pos'];
   $pers=$_POST['mod_pers'];
   $matricola=$_POST['mod_matricola'];
   $matricola=strtoupper($matricola);
   $unit=$_POST['mod_unit'];
   $unit=strtoupper($unit);
   $qnt=$_POST['mod_qnt'];
   $prezzo=$_POST['mod_prezzo'];
   $data=$_POST['mod_data']; 
     
     
//aggiornamento dai database
$dati=" UPDATE seriale SET id_coord = '$coord',
                           id_pos = '$pos',
                           id_pers = '$pers',
                           matricola = '$matricola',
                           unit = '$unit',
                           qnt = '$qnt',
                           prezzo = '$prezzo',
                           data = '$data'
                           where id =  '$_GET['id']'";
                       
mysql_query ($dati, $link)
        or die ("Non riesco ad eseguire la query $dati");
                Echo "I Dati sono stati archiviati con successo nel DataBase $database";
                if($risultato)
{echo "<script type=text/javascript>alert('inserimento dati nel database riuscito');</script>";}
else {echo "<script type=text/javascript>alert('inserimento dati nel database fallito, riprova');</script>";} 
} mysql_close($link);
//redirect back to the view page
echo "<br><a href='index.php'>Home</a>";
?>

potete aiutarmi?

Grazie!

inviato 4 anni fa
zebmckey
modificato 4 anni fa
X 0 X

Il primo caso da te per altro risolto è da manuale!

$sql = "select * from elenco_mat WHERE id = $_GET['id']";

Mai e dico mai passare una variabile globale ad una query di database! Se no si crea una via grande come un'autostrada per le sql injection.

Come errore però il parser del PHP ha dato il classico sbagli di voler passare un array come una normale variabile. La forma corretta per un array passato in una stringa è: $s = "stringa {$array['pippo']}"; cioè incapsulare l'array tra le parentesi graffe.

Il secondo errore sembrerebbe dovuto al fatto che il database non sembrerebbe essere in MySQL ma in PostGree quindi l'istruzione mysql_ non lo capisce.

Il consiglio a questo punto è di comprarti un libro su PHP molto completo, o in alternativa fare molte prove.

Se hai database diversi dal MySQL meglio sarebbe passare al sistema PDO che ti permette di gestire più tipi di SQL. http://it1.php.net/manual/en/book.pdo.php

risposto 4 anni fa
Marco Grazia
@marcograzia Grazie per la tua risposta, ma è sicuro che il database è un mysql, quindi l'errore in questo caso dov'è? io passo un post e lo trasformo in variabile e poi passo la variabile all'update. Puoi aiutarmi a capire meglio? grazie!zebmckey 4 anni fa
X 0 X

L'errore del primo script è causato dall'errato inserimento della variabile $_GET['id'] nella stringa. Infatti, in generale, quando si inserisce un elemento di un array in una stringa non bisogna mettere i singoli apici. L'istruzione va quindi scritta così:

$sql = "select * from elenco_mat WHERE id = $_GET[id]";

Per quanto riguarda il modsecurity (che meriterebbe un'altra domanda!!!) credo che il problema sia legato alla creazione della query, effettuata inserendo senza alcun controllo o filtraggio il valore $_GET['id'] che potrebbe venir manipolato da un utente malizioso. Immagina cosa potrebbe capitare se $_GET['id'] valesse "1 OR 1 = 1".

Nella seconda versione dello script ti consiglio di trasformare:

$id = $_GET['id'];

in

$id = intval($_GET['id']);
risposto 4 anni fa
Gianni Tomasicchio
Grazie tutti faccio un test con i vostri suggerimenti e vi faccio sapere.zebmckey 4 anni fa
X 0 X

Credo di aver compreso l'errore, sono stato un po' superficiale nella mia prima risposta e mi sono lasciato fuorviare da quei riferimenti a PostGre e Oracle.

Puoi trovare indicazioni anche qui http://www.modsecurity.org/projects/modsecurity/apache/feature_content_injection.html (in inglese).

Insomma per farla breve quello script dal punto di vista della sicurezza è fatto davvero male :-) e mod_security te l'ha segnalato.

In particolare nella query ripeti lo stesso errore di gioventù fatto nella prima parte:

//aggiornamento dai database
$dati=" UPDATE seriale SET id_coord = '$coord',
...... taglio ......
                           where id =  '$_GET['id']'";

Non si passa un valore in quel modo ad un database o si rischia davvero che qualcuno ti mandi a quel paese tutto il database. Mod_security te l'ha segnalato.

Oltre creare un valido sistema di escaping per la GET dovresti fare la stessa cosa anche per gli altri valori.

Con i database non si scherza.

Un'ultima cosa che non riguarda il database ma l'HTTP; tu passi i valori sia via GET che POST in un'unica sessione?

risposto 4 anni fa
Marco Grazia
Vi ringrazio davvero per la vostra collaborazione, come avevo detto all'inizio sto imparando e quindi per forza di cose commetto errori. Per quanto riguarda la tua domanda sul passaggio di GET e POST è si con GET prendo l'ID della query precedente e con POST passo i dati alle variabili. Spero di non aver commesso un errore madornale :(zebmckey 4 anni fa
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda