SQL injection in LIMIT (from PHP) - php

I have the following code :
$req = mysql_query("SELECT * FROM table WHERE id='".mysql_real_escape_string($id)."' ORDER BY lastupdate DESC LIMIT ".mysql_real_escape_string($_GET['start']).", 15 ");
For some reason it seems like I can inject some (unusable) SQL code into the $_GET['start'] parameter.
For example : 1,100 # (url encoded like this : +1%2C+100%23)
I'm fairly sure you can't really use it to do any damage or steal anything from my db (UNION can't work because of ORDER BY, and mysql_query() doesn't allow multiple queries
I know I should add intval() to make sure it is an integer. My main question is WHY... Why does it work? I really don't understand.
Thank you very much for your insights.

You should parse it into an integer.
$req = mysql_query("SELECT * FROM table WHERE id='".(int)$id."' ORDER BY lastupdate DESC LIMIT ".(int)$_GET['start'].", 15 ");
Additionally, you should strongly consider using mysqli or PDO
The mysql_* , mysqli_* functions have no idea of what the structure of your table is. The function mysql_real_escape_string considers everything as string, and just makes it safe.

Related

Does ORDER BY and WHERE clause have different precedence?

I am currently fetching data using the statement
$queryfetchBookings="SELECT `id`,`sessionHeld`,`fk_student_id`,`channelName`,`video_duration`,`audio_duration`,`category`,`dateBooked`,`timeSlot`,`duration`,`category`,`studentName`,`overallRating`,`chat_duration` FROM `one_to_one_bookings` WHERE fk_co_id=".$co_id;
I now want to add an
ORDER BY `id` ASC
to the end but whatever variation I have tried results in failure.(Does not fetch data). Need advice on how to proceed.
Different variations that i have tried:
First of all, you should use prepared statements to avoid SQL injection, and not concatenating strings to your query.
You are doing wrong your concatenation in PHP, you need to add a . and some quotes:
$queryfetchBookings="SELECT `id`,`sessionHeld`,`fk_student_id`,`channelName`,`video_duration`,`audio_duration`,`category`,`dateBooked`,`timeSlot`,`duration`,`category`,`studentName`,`overallRating`,`chat_duration`
FROM `one_to_one_bookings` WHERE fk_co_id=".$co_id." ORDER BY `id` ASC";
The problem was at the end of the query:
WHERE fk_co_id=".$co_id." ORDER BY `id` ASC";
I am not sure about how the server you are using works, but in oracle it would not work because after the WHERE clause you are adding a ";". At least in oracle this would mean that the query is over, so I am guessing this is why it is not considering your last sentence.
I hope I can help :)

PHP - Remove quotes in MySQL query [duplicate]

I am trying to refer to a column name to order a query in an application communicating with an Oracle database. I want to use a bind variable so that I can dynamically change what to order the query by.
The problem that I am having is that the database seems to be ignoring the order by column.
Does anyone know if there is a particular way to refer to a database column via a bind variable or if it is even possible?
e.g my query is
SELECT * FROM PERSON ORDER BY :1
(where :1 will be bound to PERSON.NAME)
The query is not returning results in alphabetical order, I am worried that the database is interpreting this as:-
SELECT * FROM PERSON ORDER BY 'PERSON.NAME'
which will obviously not work.
Any suggestions are much appreciated.
No. You cannot use bind variables for table or column names.
This information is needed to create the execution plan. Without knowing what you want to order by, it would be impossible to figure out what index to use, for example.
Instead of bind variables, you have to directly interpolate the column name into the SQL statement when your program creates it. Assuming that you take precautions against SQL injection, there is no downside to that.
Update: If you really wanted to jump through hoops, you could probably do something like
order by decode(?, 'colA', colA, 'colB', colB)
but that is just silly. And slow. Don't.
As you are using JDBC. You can rewrite your code, to something without bind variables. This way you can also dynamically change the order-by e.g.:
String query = "SELECT * FROM PERS ";
if (condition1){
query = query+ " order by name ";
// insert more if/else or case statements
} else {
query = query+ " order by other_column ";
}
Statement select = conn.createStatement();
ResultSet result = select.executeQuery(query);
Or even:
String columnName = getColumnName(input);
Statement select = conn.createStatement();
ResultSet result = select.executeQuery("SELECT * FROM PERS ORDER BY "+columnName);
ResultSet result = select.executeQuery(
"SELECT * FROM PERS ORDER BY " + columnName
);
will always be a new statement to the database.
That means it is, like Thilo already explained, impossible to "reorder" an already bound, calculated, prepared, parsed statement. When using this result set over and over in your application and the only thing, which changes over time is the order of the presentation, try to order the set in your client code.
Otherwise, dynamic SQL is fine, but comes with a huge footprint.

MySQL ORDER BY statement returning boolean?

I have absolutely no idea why this is happening, but my simple MySQL statement using an ORDER BY ... DESC command gives a really weird error when I try to perform the query.
The error is
mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in E:/.../home.php on line 23
And my code is:
$data = mysql_query("SELECT * FROM `blogposts` LIMIT 0, 30 ORDER BY id DESC");
while($results = mysql_fetch_assoc($data))//error here
I can't find out why. Any help is appreciated.
Oh, by the way, I know that everyone who looks at this question is going to rip into me for still using mysql.* libraries and there will be a highly upvoted comment about the evils of it and the fact that I am vulnerable to SQL injection. To answer before it's asked, as it were, this is not going online, it's purely a home project running on localhost. So don't even bother lecturing me.
ORDER BY clause must come before the LIMIT clause
SELECT * FROM `blogposts` ORDER BY id DESC LIMIT 0, 30

Is there a better way of getting an item from a MySQL db?

I'm fairly novice with SQL (reading right now). I'm wondering if there is a better way in PHP to get a MySQL data item than the following:
$sql = "SELECT `topic_id` from `topics` WHERE `user_id` = ".$userId." AND `topic` = ".$topic.";";
$topicRow = mysql_query($sql);
$row = mysql_fetch_array($topicRow);
$topicId = $row['topic_id'];
I mean, 4 variables were created to get 1 item. Am I doing something incorrectly?
Thank you
The amount of vars is not a real issue, you could put the sql-string in your query if you want, but you're not really winning anything measurable. Please do not look for efficiency there. While the answers of #genesis and #patapizza are correct as far as I can see, they do not help you in any way to better your code, but only make it less readable.
You should look into parametereized queries (take a look at using PDO): You should split your content ($userId) and your SQL-command.
An example from the manual:
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute(array(150, 'red'));
$red = $sth->fetchAll();
You don't have to escape the various things you put in your query, so you're save from injection.
(ow, and coincidently, only using 2 variables.. jeeeej :) )
Unless you have not SQL-escaped $userId and $topic your code is susceptible to SQL-injection. I would also use the PDO API instead which is database management system independent.
http://php.net/manual/en/book.pdo.php
You could always use a database abstraction layer, like ADOdb.
The thing is, you do not want to constantly get involved into escaping variables, and query concatenation is something which shouldn't be done in many places in the code. Having all that, the best thing you can do, is Really, using something like ADOdb, or make something of your own, in case ADOdb doesn't respond to your needs.
It is absolutely incorrect, from an architect's point of view, to mix logic, real program logic, with stuff like technical means of getting at your data (open connection, define command, get result, read result, etc). In that logic you just have to Get your data. You don't need to see a database connection in your logic.

Is there a better, more "Standard" way to perform SQL queries in PHP without using a framework?

For the longest time, I've been using the following basic formatting for SQL queries within my PHP:
$sql = "SELECT * FROM `user-data` WHERE `id` = '".$id."' LIMIT 1;";
$fn = mysql_fetch_assoc(mysql_query($sql));
While this works flawlessly, it can get really messy for longer bits of code, and something deep inside of my conscience cringes at the string concatenation every time I do it. Still, it works and I use it almost everywhere without major issues. (That's a tame example, I'm not dense enough to pass user data directly into an SQL string without escaping it first, etc etc.)
What I'd like to do is something a bit more object oriented, but I'm not sure what the best approach would be. It'd be nice to just be able to sql->insert($values [, $where, $extra]); or something similar, using PHP's natural Associative Array types to pass in the query strings in a more simplified manner. Less flexible? Yes. More readable? Heck yes, and harder to make "silent" syntax errors at that.
What are the community's takes on this? What approaches have you seen to this problem that were the most effective for projects you were working on?
Not that it matters, but I personally don't do much more complicated than SELECTs, INSERTs, and UPDATEs, with occasional nesting of subqueries, but that's mostly because my SQL flavor doesn't do stored procedures.
PDO is a good, solid, secure solution that many frameworks build off of. If you're going to start from the bottom, PDO is a solid foundation.
Maybe it would make you a little happier at least to use PHP's string variable substitution:
$sql = "SELECT * FROM `user-data` WHERE `id` = '$id' LIMIT 1;";
There is MDB_QueryTool I never tried.
IMHO Zend_DB is really cool, the zend framework allow you to use only the part you are interested in so you might want to take it a look event if you don't want the full framework.
what I like in Zend_DB is the table select syntax
$userRowset = $user->fetchAll( $user->select()
->where('name LIKE ?', $name . '%')
->order('id ASC')
->limit(10)
);
You can easily see all the criterias and table involved so I find better then doing plain SQL. Just one warning Zend_DB doesn't handle all the SQL, so time to time you would have to write plain SQL but that's really rare.
Doctrine is an ORM wrapped around PDO.
Another vote for doctrine. Don't waste your time with PDO. I can't emphasize this enough. Go with an orm. Forget about wasting time writing CRUD methods, custom caching logic, and worrying about premature optimization such as "overhead" resulting from a library. The overhead incurred by spattering statements like "select * from app_users" and their associated ugly heredocs isn't worth it.
If you need to fall back to sql, you can. The other 90% of the time you're in a state of bliss.
http://www.doctrine-project.org/
You can use mysqli to write little place holders in you SQL and then fill them in. It should be less susceptible to SQL injection attacks than string concatenation.
$conn = new mysqli($server, $username, $password, $database);
$stmt = $conn->prepare('SELECT * FROM people WHERE age = ? AND name != ?');
$stmt->bind_param('is', 20, "Austin");
Try:
$stat2 = <<<SQL
SELECT * from YOUR.DET_TABLE
WHERE ID = ?
ORDER BY ID, EFF_DT
SQL;
$d_cur = $conn->prepare($stat2);
$status = $d_cur->execute(array($selected));
I've been wondering why I am always seeing the more complicated form of string building like this:
"literal string " . $a . " more literal", rather than "literal string $a more literal", or in your case:
"SELECT * FROM `user-data` WHERE `id` = '".$id."' LIMIT 1;";
instead of this:
"SELECT * FROM `user-data` WHERE `id` = '$id' LIMIT 1;";
For more complicated expressions, I like to use sprintf (but I was a c programmer for a long time):
$sql = sprintf("SELECT * FROM `user-data` WHERE `id` = '%s' LIMIT 1", $id);
This can also be written in this format:
$sql = sprintf("
SELECT *
FROM `user-data`
WHERE `id` = '%s'
LIMIT 1",
$id);
In this case, it doesn't buy much, but when there are several variables embedded in the string, it makes it easier to manage.

Categories