0

I'm an amateur in php. I have a website where I load projects from a DB and for example when I want to load a proyect the url is like this

www.mywesite.com/proyecto.php?id=1

I did a .htaccess to use this url:

www.mywebsite.com/proyecto/id/1

.htaccess

<ifModule mod_rewrite.c>
  Options +FollowSymLinks
  RewriteEngine on
  RewriteRule proyecto/id/(.*)/ proyecto.php?id=$1 
  RewriteRule proyecto/id/(.*) proyecto.php?id=$1 
  RewriteRule ^([^\.]+)$ $1.php [NC,L]
  ErrorDocument 404 /error404.php
</ifModule>

The problem now is that the variables are undefined because of the change of the url I think. This is how I get the variables

$valorid = $_GET['id'];
$connection = new 
PDO('mysql:host='.$host.';dbname='.$db_name.';charset=utf8',''.$username.'', ''.$password.'');
foreach($connection->query('SELECT * FROM grafica WHERE id = '.$valorid.'') 
as $row) {

}

And I set the like this

<?php echo $row['nombre'] />
Nimantha
  • 6,405
  • 6
  • 28
  • 69
  • 2
    Can you include the `.htaccess` file content? – Twisty May 17 '18 at 17:17
  • 1
    Also, this SQL Statement is vulnerable to SQL Injection. This will allow potentially harmful SQL statements to be injected into your code. You should consider PDO Prepared statements. https://stackoverflow.com/questions/134099/are-pdo-prepared-statements-sufficient-to-prevent-sql-injection – Twisty May 17 '18 at 17:19
  • Oh god, thanks for your advise, I will try to change it. I will follow that link you provided me and try. Here is the .htaccess ` Options +FollowSymLinks RewriteEngine on RewriteRule proyecto/id/(.*)/ proyecto.php?id=$1 RewriteRule proyecto/id/(.*) proyecto.php?id=$1 RewriteRule ^([^\.]+)$ $1.php [NC,L] ErrorDocument 404 /error404.php ` – user3430043 May 17 '18 at 18:38
  • I am worried about what you say, Is this a secure conection ? `$connection = new PDO('mysql:host='.$host.';dbname='.$db_name.';charset=utf8', ''.$username.'', ''.$password.''); $statement = $connection->query('SELECT * FROM grafica ORDER BY ID DESC'); while($row = $statement->fetch(PDO::FETCH_ASSOC)) {` – user3430043 May 17 '18 at 18:54
  • I have moved your .htaccess code into your Post. In the future, please use 'Edit' to edit your post. In regards to your security question, this is more secure, yet will result in a much larger dataset that you will then have to iterate in PHP. Basically, if you are expecting a number via GET, you must sanitize the input from the user so they do not send some other data to your script. – Twisty May 17 '18 at 19:17
  • Thank you Twisty. Can you give me some advise how can I make a secure connection like this (SELECT * FROM grafica WHERE id = :id) taking the variable from the url and, how can I print data from that ID for example name, age etc. ? – user3430043 May 17 '18 at 19:42

1 Answers1

1

In regards to your question, this was already answered here: URL rewriting with PHP

In the future, please make sure to search for possible solutions. Consider the following in your .htaccess file:

<ifModule mod_rewrite.c>
  Options +FollowSymLinks
  RewriteEngine on
  RewriteRule ^/proyecto/id/([0-9]+)/$ /proyecto.php?id=$1 
  RewriteRule ^([^\.]+)$ $1.php [NC,L]
  ErrorDocument 404 /error404.php
</ifModule>

This is the first step to creating a more secure GET Request. For example, this will pass:

www.mywebsite.com/proyecto/id/1/

While a malicious attempt should fail:

www.mywebsite.com/proyecto/id/%5Cxbf%5Cx27%20OR%201%3D1%20%2F*

This would pass \xbf\x27 OR 1=1 /* to your script and could be potentially harmful payload. Since this value is not 0 through 9, the rewrite condition should not be met.

On to your SQL Query. This is the next level of defense, we want to ensure that we only use an integer variable type. To do this, we want to sanitize the input from the browser in some way. More than one way to do this. We can do it before passing the variable to the query or we can use PDO Functions.

Example 1: Santize the variable before Query

Instead of using:

$valorid = $_GET['id'];

Where whatever is entered as id will be placed in the variable, we can force it to be a number. Something like:

$valorid = sprintf("%d", $_GET['id']);

This is a less used method, since it's basically formatting the variable into a digit.

Example 2: Using PDO Prepared Statement

Refer to: http://php.net/manual/en/pdo.prepared-statements.php

Consider the following:

$conn = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8",$username, $password);
$stmt = $conn->prepare('SELECT * FROM grafica WHERE id = ? LIMIT 1');
if ($stmt->execute(array($_GET['id']))) {
  while ($row = $stmt->fetch()) {
    // Do the needful
  }
}

This is considered a better method. One, we have improved the statement with LIMIT 1 to ensure we only get 1 result. Two, PDO will prepare the statement and ensure that all potentially harmful elements are handled, commented, or obscured.

Prepares an SQL statement to be executed by the PDOStatement::execute() method. The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers for which real values will be substituted when the statement is executed. You cannot use both named and question mark parameter markers within the same SQL statement; pick one or the other parameter style. Use these parameters to bind any user-input, do not include the user-input directly in the query.

Hope that helps.

Twisty
  • 30,304
  • 2
  • 26
  • 45