3

Let's say I have a file called query.sql with the following content in it:

SELECT * FROM `users` WHERE `id`!=".$q->Num($_POST['id'])."

And in my php-script, which has a html form with input named "id" in it, I do the following trick:

$sql=file_get_contents('query.sql');
$query= eval("return \"$sql\";");
//here follows something like $mysqli->query($query); and so on..

I am not concerned about sql-injections since I'm using prepared statements and $q->Num performs is_int check. But is it safe to use eval such way?

As far as I understand, what is actually eval-ed here is "${_POST['id']}" and it evals to some string value the user entered. And this becomes dangerous only if I eval this string second time. While I eval string only once user's input is just string and can not be interpreted as php-code by compiler and no php-injection is possible.

UPDATE Thank you for proposing different methodologies and stressing need to use prepared statements. But this not my question at all. My question is all about php-injections. Is such use of eval bad? If yes, why?

Georgy Nemtsov
  • 786
  • 1
  • 8
  • 19
  • 4
    Why not just use the line `$query = $sql`? What is the `eval` line meant to accomplish? – David Robinson Jan 23 '13 at 16:34
  • 3
    @DavidRobinson: He's trying to parse the `$q->Num($_POST['id'])` insde the `query.sql` file. – gen_Eric Jan 23 '13 at 16:34
  • `eval` is strictly to take code from the file & run it as `php`. If the query is already in a text file, just load it & assign it to a variable as David Robinson suggests. But not clear on the value of this whole process to parse the `$q->Num($_POST['id'])`. Seems quite hacky as expressed here. – Giacomo1968 Jan 23 '13 at 16:36
  • 1
    Sounds like a terrible idea. If you're using `eval`, you're doing it wrong 99.999% of the time. Write eval-free code. – deceze Jan 23 '13 at 16:37
  • 2
    I would personally rather have `SELECT * FROM users WHERE id!={PostId}` in the file and then substitute out the `{PostId}` in PHP. – lc. Jan 23 '13 at 16:40
  • SQL injections are possible! If `NUM()` fails for some reason. Read my answer – hek2mgl Jan 23 '13 at 16:48
  • `eval()` is almost always unsafe. Where it isn't unsafe, it is almost always inefficient. Even in the best cases, there is almost always a better way of doing things than `eval()`. – SDC Jan 23 '13 at 17:02
  • If `$q->Num` only returns an int, then there is no issue here. If `$_POST['id'] = '""; DROP TABLE users; -- ';`, then `$q->Num` will return `0`, right? If so, then it *should* be fine. – gen_Eric Jan 23 '13 at 17:03

4 Answers4

2

The eval statement - although I would try to find a way without using eval - is not vulnerable for PHP injection because $sql is enclosed in double quotes "; One can not ending this quoting with a prepared variable in PHP.


I am not conserned about sql-injections since I'm using prepared statements

Aren't you? ;) You are!

Why do you add the $id to the query using the '.' operator (string manipulation)? If you really use the benefits from prepared statements I would expect something like a bindParam()

Note how prepared statements prevent from SQL injections: The SQL query syntax is been kept separate from arguments. So the server would

  1. parse the SQL query
  2. apply arguments

As the query has been already parsed before arguments will been applied, the query syntax cannot be manipulated by the arguments.

If you prepare a MySQL query that has been created using '.' and external inputs you are potentially vulnerable against SQL injections

What you are doing defeats the principals of prepared statements

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • 3
    No you dont use bindParam. You use : `.$q->Num($_POST['id']).` – hek2mgl Jan 23 '13 at 16:41
  • Please trust me, I use it. I didnt post content of my Num function and whole q class which performs db queries. It is not about my question at all.. – Georgy Nemtsov Jan 23 '13 at 16:51
  • I really don't believe it. However, in any case the short answer: Don't use eval – hek2mgl Jan 23 '13 at 16:56
  • 1
    No matter what `Num` does, you're not using it as a bound parameter. – Jonnix Jan 23 '13 at 17:00
  • `Num` checks whether its parameter is integer and then puts it in private array of parameters of `q` class and make a unique key to put in query string. When `q->execute($query)` is called this parameters are passed to bindParam() function and unique keys are replaced with '?'. So I am definitely using prepared statements. If I give all listings it'll be huge question nobody would read :(. – Georgy Nemtsov Jan 23 '13 at 17:05
  • Ok, understood. I've done something like this: ` ... and make a unique key to put in query string ... ` once too. :). I've made some tests with your eval and would not say it is vulnerable for PHP injections. But do you need it? – hek2mgl Jan 23 '13 at 17:12
  • Yes it is very convinient to separate queries from php-scripts in my framework. – Georgy Nemtsov Jan 23 '13 at 17:17
  • Ok understood.. Still investigating... (Btw: Tends to be after all a good question ) :) You shoud consider to add information from the comments to the question itself – hek2mgl Jan 23 '13 at 17:18
2

There is no need to use eval - put in a token, and replace it:

// file query.sql
SELECT * FROM `users` WHERE `id`!="{id}";

//php
$sql = file_get_contents('query.sql');
$query = str_replace("{id}", $_POST['id'], $sql);

Update No, it's not safe. Someone could edit your query.sql script to do anything you want. You may say "the app is internal only", or "i have permissions locked down" or whatever - but at the end of the day there are no guarantees.

Adam Hopkinson
  • 28,281
  • 7
  • 65
  • 99
  • Just be sure to escape the `$_POST['id']` value before replacing :-P (or replace it with a `?` and use `bindParam`) – gen_Eric Jan 23 '13 at 16:45
  • Thanks, I know there are many options, finally I can just form my query in php-script. Methodology is not the question. The question was "is it safe to do it such way, and if not why?" – Georgy Nemtsov Jan 23 '13 at 16:48
  • Well I suppose that posibility to edit query.sql is even less that editing all my php-scripts. I have .sql's in separate directory, in which I prohibited access via web server config. – Georgy Nemtsov Jan 23 '13 at 18:31
1

Reference from this Answer.

https://stackoverflow.com/a/951868/627868

The main problems with eval() are:

Potential unsafe input. Passing an untrusted parameter is a way to fail. It is often not a trivial task to make sure that a parameter (or part of it) is fully trusted.

Trickyness. Using eval() makes code clever, therefore more difficult to follow. To quote Brian Kernighan "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it"

Community
  • 1
  • 1
Rush
  • 740
  • 4
  • 13
-1

Let's consider the following code:

$sql=file_get_contents('query.sql');
$query= eval("return \"$sql\";");

The danger points at this are:

  • if the file query.sql is modified from what you expect, then it could be used to execute any arbitrary code in your program.

  • the name of the file is shown hard-coded; if this isn't the case, then a malicious user could find a way to load an unexpected file (possibly even one from a remote site), again resulting in arbitrary code execution.

  • the only reason to use a file for this (rather than hard coding the SQL code directly in the program) would be because you want to use it as a config file. The problem here is that the syntax in this file is invalid for both SQL and PHP. Due to the way it's run in the eval(), it also requires that the syntax is exactly correct. Use the wrong quotes or miss one out, and it'll blow up. This is likely to result in brittle code, that fails badly rather than gracefully when the config is marginally incorrect.

There doesn't appear to be a direct SQL injection attack here, but that's really the least of your worries when it comes to eval().

I have personally worked in projects where code existed that worked pretty much exactly the way you've described. There were some very nasty bugs in the system as a direct result of this, and they have been difficult to rectify without wholesale rewrites. I would strongly recommend stepping back from this idea and using a sensible templating mechanism instead as recommended by others in the comments.

SDC
  • 14,192
  • 2
  • 35
  • 48
  • You are wrong. Note my answer. Although I wouldn't do it too. But what the OP mentioned in comments sounds not THAT bad – hek2mgl Jan 23 '13 at 17:35