Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I know, that PDO won't let me use the "param system" on tables. My problem is, that I store all table names as variables / static variables in an object named "Tables" (so I can update table names centrally).
I just can't find an answer to the question, if it's a good idea / not bad practice to build the query by using my static variables (users can't change the table names / browse through tables, so that shouldn't be a security problem)
Example:
$statement = $this->pdo->prepare('SELECT `category-id`, `icon`, `name` FROM ' . Tables::$BOARD_CATEGORIES);
Can I use this technique, or should I stick with the normal "static" way?
Thanks :)
The primary security benefit of the parametrized prepared statement is that it prevents the insertion of strings from untrustworthy sources into your SQL statement before the statement is parsed by the DB; after the statement is parsed and prepared, only value substitutions are allowed, not executable clauses.
You could think of your original SQL query as "a string from a trustworthy source." If it improves maintainability, I see no reason to build up your query from smaller strings provided all such strings are also from trustworthy sources, such as your Tables class. (I do wonder, though, how often you expect to rename your tables.)
Whether it is or isn't "best practice" I'm not prepared to say, but I did see something similar in industry when I worked with The Great Azure Empire (a false name for a real company), and I think even "best practice" should not be seen as dogma.
Answer:
It depends on the code you are using to develop and modify your Tables object. In general though, conventional methods are more tested and safer. The only real difference between your code and normally used PDO code is how you are generating your sql statement. If you use your own code to create the sql statement that is being prepared, you have to be completely sure that user input will not modify the structure of that sql statement. It is riskier and if not needed would be advised against, however if you absolutely need it for your site, then make absolute sure that the code generating the Tables object can't be maliciously manipulated by users.
Elaborating on the answer:
The real difference between your code and the general way PDO is used is that you are generating the sql statement differently. Normally, you would see code as follows:
$sql = "SELECT `category-id`, `icon`, `name` FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(":id", $id);
$stmt->execute();
(I am assuming that you are also binding your parameters in your code since that would be after the preparing process you show in your question).
So since the only real difference between what you are doing with your table is generating the sql statement, you just have to make complete sure that there is absolutely no way for user input to influence your sql structure, because if there is, then the prepare statement will not keep your database safe.
In general, people tend to prefer to use conventional and tested methods, however if you absolutely need to use your table object to generate the sql statement, make sure that the code that creates and updates the object is defended from user input.
Related
Could anyone help me with my query?
I am currently converting all my old PHP code to use PDO.
I was wondering when is it necessary to use the prepare function for my querys?
I currently have this query.
$sql = "SELECT deckName FROM decks WHERE deleted = '0' ORDER by deckName";
None of it is dynamic apart from maybe the deleted column.
I am using the below to reiterate my data on screen.
foreach($DBH->query($sql) as $row){ echo $row['deckName']?> }
Should I still be using this as good practice or is the above good enough?
$sth = $DBH->prepare("SELECT deckName FROM decks WHERE deleted = '0' ORDER by deckName");
I am not quite sure how to use the fetch statement correctly when reiterating data from the row?
Thanks in advance :)
Hayley
If you send a constant string to the database and do never mix in "untrusted input" the security concern is in my experience irrelevant, and only a potential performance aspect remains, which depends on the underlying database. IF the preparation step of an expensive to parse query may be spared for the execute phase (prepare, bind=NOOP here, execute) of all invocations after the first.
So guessing from the tags, that you use mysql and do not use memcached or the like as an intermediate layer, you might just want to measure the performance, otherwise you could migrate to direct queries.
When the "Project" later needs variable parametrization of the query (based on untrusted input e.g. from the network), you should use again prepare, to shield against injection attacks. Maybe then it will be good to find out "how to use the fetch statement correctly when reiterating data from the row" ...
Amending to the answer to accomodate the "uppercased nevers" for using variables in queries from the comments:
There is a practical reason for me writing "receiving untrusted input" instead of "never this and never that". In my experience there is a slippery slope, when it comes to variables: Without auditing the wider context of the $sql variable in above question - even the whole query is potentially vulernable to injection attacks.
Also internal refactorings of building query strings from constants may lead to mixing further variables to compose a (more complex) string that acts as a query.
For a more balanced / gap minimizing hardening I would suggest:
Documenting a specific map of say "trusted boundaries" in a code realizing an app, and based on that, enforcing strict validation of any input crossing these boundaries - i.e. variables transporting values accross - is in most cases effective and efficient.
Adding the common sense concept of layered security / separation of concerns will then naturally lead to using prepared statements when "such input" (that crossed a boundary) is to be "injected" as parameter.
I am reluctant to hand out simple recipes giving an optimistic sense of security, when one deals with such a scyscraper like application stack as db based web apps usually do.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I usually use mysql_query() to get data from mysql database. But some people use binding to set results. What is the different between then? In my view both give the same result. But i feel binding is bit complicated. Can anyone please what are the advantages of using bind? Thank you.
Data binding offers enhanced protection from SQL injection attacks (sometimes referred to as SQLIA). SQL injections are malicious attempts to gain access to your database for reasons outside intended use. Use your imagination here. As a result, using mysql_connect is a really bad idea and the library is deprecated as of PHP 5.5.0. For a more comprehensive overview, see this article.
Binding is not as complicated as it seems if you break down a SQL query, it can very easily explained.
Take the following code in the old mysql library as an example:
mysql_query(
"INSERT INTO users (username, password, user_data) VALUES ('derek_jeter', 'password', 'additional_data')"
);
This code is vulnerable to SQLIA. With a library such as PDO, you just need to add an extra step to avoid the issue entirely. To achieve the same result in a safer library, you just need to translate the above code into the following:
$db->prepare("INSERT INTO users (username, password, user_data) VALUES (:username, :password, :additional_data)";
$db->execute(
array("username" => "derek_jeter", "password" => "password", "additional_data" => "additional_data")
);
Binding sends the data to be inserted into MySQL separately from the query, and understands how to parse it for insertion without risking safety of the database. With the execute function, you just pass the array with keys corresponding to the placeholder data you defined in the prepare function.
Note: I'm using the word "function", but since the PDO library is actually an object you manipulate, the functions contained in the PDO class are technically referred to as "methods".
There's a bit more you'll need to do before you can just run queries in PDO (such as instantiating the PDO connection and class), but I'll refer you to the docs which explain everything in great detail.
Also, here's a tutorial I used when I first started using PDO and MySQLi.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I've design this small function and I would like to know if anyone thinks it's safe enough, or if not, why.
function safeSQLI($INPUT){
// Trim un-needed spaces
$safe_input = trim($INPUT);
// Replace any SQL commands
$safe_input = str_ireplace("drop", "", $safe_input);
etc...
// Escape the result
$safe_input = mysql_real_escape_string($safe_input);
// Return the "Safe" result
return $safe_input;
}
Answer: No, it's not safe at all. I am now using PDO and I think I was missing something great before now.
str_ireplace() is generally a bad choice, because it doesn't work recursive. Try the following:
$safe_input = 'DELDELETEETE * FROM users';
Will result in:
DELETE * FROM users
So, your entire function falls back to mysql_real_escape_string() and everything that came before is useless. The point is: It's not impossible to write proper filtering methods, but it can be a real challenge to cover every single case there is.
You want to either follow a whitelisting approach and allow only certain types of content. This is tough to implement in the real world.
Or a blacklisting approach and deny certain characters. Most SQL injection vulnerabilites happen because one can inject additional commands in a string. If you escape the ' (or use mysql_real_escape_string(), you are usually safe). However, it depends on your web app if additional filtering is required or not.
Or use prepared statements.
It does prevent injection, provided you use quotes like you should:
SELECT * FROM `users` WHERE `name`='$username'
For example.
However it is complete overkill. mysql_real_escape_string is sufficient to make an input safe, provided you use the quotes as above.
I spent all day today trying to get some database work done on a server that had been locked down to return "Not Acceptable" HTTP responses if "anything that looked like a database table name was present in the request". Needless to say, it took significantly longer than it needed to, when a simple mysql_real_escape_string would have sufficed.
Not safe at all. Try running this:
echo safeSQLI("drdropop tatableble TABLE_NAME");
That never let you insert a post about SQL in your blog.
I think use prepare statements and mysql_real_escape_string is safe enough.
PS: And you can avoid DDL sentences at BD level, with permissions.
This question already has answers here:
How to escape strings in SQL Server using PHP?
(14 answers)
Closed 9 years ago.
I can sanitize and validate my input as much as possible but that definitely doesn't cover everything and if I scrub hard enough, thoroughly enough, I will completely wipe away my input.
I realize there are a lot of posts out there about this topic but it seems like they always go back to PDO or Mysql (yes - even if someone posts about SQL Server, half the answers they receive suggest mysql_real_escape_string - crazy world). I cannot use either. Even as I type and the little "similar questions" appear on the right of my screen, I keep clicking on various links and nothing fully answers my question.
I am using SQL Server. I am using PHP 5.2.4. I cannot use PDO (because...? my boss said 'no' and that's enough reason).
Is there a way I could write a safe way to prepare my own query statements?
In the past, I have tried to build a statement like this in the PHP. (where $input_* variables are some form of user input or I pulled them out of something)
$query = "
declare #varID int
declare #var1 int
declare #var2 varchar(100)
set #varID = cast('$input_ID' as int)
set #var1 = cast('$input_var1' as int)
set #var2 = cast('$input_var2' as varchar(100))
update table_name_goes_here
set var1 = #var1,
var2 = #var2
where ID = #varID;
";
# $query is then executed
but that can be vulnerable, too... obviously.... And the last thing I do is remove all necessary punctuation (sometimes I know they will have no reason to use certain characters)
But there has to be some other option... right? And mssql_bind only works for stored procedures, which is a definite option but I'm not sure if I want to volunteer to expand my responsibilities to include maintenance in the actual database by making insert/update procedures.
I would say that "because the boss said 'no'" is a terrible reason. Tell him (her?) that he is wrong. I know little of PHP, but regardless of the language, the only foolproof way to prevent injection is through paramaterized queries, or stored procedures. If the only way to do that in PHP is to use PDO, then use PDO.
Here is your reasoning for using PDO: https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
http://msdn.microsoft.com/en-us/magazine/cc163917.aspx
And why is there any SQL in the code at all? It is much easier to maintain if it is in the database, generally in the form of stored procedures.
You haven't answered the question "How do you intent to talk to the MS SQL database if PDO isn't allowed", but I assume there are the mssql_* functions to be used.
These do not have an escaping function readymade, but it seems they offer you to use prepared statements - which will do the job.
Otherwise you would have the security-relevant task to create an escaping function yourself. The character replacement is not really complicated when you first look at it, and you might be lucky to only have to cover your exact use case with a defined encoding. So this might really be as easy as looking up in the MSSQL manual which characters in a string are not allowed as a simple character, and how to escape them.
Be alerted though that you might miss edge cases, and if you can avoid it, I'd rather use the prepared statement feature.
Update: I misread the manual, mssql_execute() only calls stored procedures, not prepared statements. Can't you store procedures? Would be an easy way out. But I'd like to know how you are supposed to talk to the database anyways.
Update2: I found a link in a comment on php.net for mssql_bind pointing back to an SO answer about escaping: How to escape strings in SQL Server using PHP?
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
This is a security question meant for PDO prepared statements. Using PDO I know that the risk of sql injection is virtually impossible and that the class handles all of that for you. Coming from using them mysql_* stack I always feel as if I'm not handling security issues well enough. I'm usually used to writing hundreds of lines of code just to deal with security while now I'm literally just writing queries.
Is there really any security threats with PDO statements that I have to worry about other than length of the string in the db?
Definitely yes.
As a matter of fact, native prepared statements are good for simple schoolbook cases only.
Means you still have to write some "hundreds of lines" for whatever complex cases. I made a small digest of such cases in the PDO tag wiki. Main disadvantages are
no placeholders for identifiers. You have to format and inject them manually like in old good mysql_* code.
no placeholders for arrays. Means you still have to write some code manually and later inject it in the query - so, there is still a possibility to slip into some trouble.
Therefore you need a higher level of abstraction even upon PDO. A common solution is to use some sort of Query Builder which offered by every modern framework.
But personally I hate query builders as they seems too bloated to me, pretending to replace whole SQL but obviously failing with it. So, I don't understand why use SQL written in PHP when I can use pure SQL. For this purpose I created an abstraction library of mine, to correct all the disadvantages of native prepared statements, safeMysql. It has placeholders for everything you need and thus makes queries much safer than PDO, yet it makes application code dramatically shorter.
Means with safeMysql you indeed can "just literally write queries":
$sql = "SELECT * FROM articles WHERE id IN(?a) ORDER BY ?n LIMIT ?i"
$data = $db->getAll($sql, $ids,$_GET['order'], $limit);
$sql = "INSERT INTO stats SET pid=?i,ip=inet_aton(?s),?u ON DUPLICATE KEY UPDATE ?u";
$db->query($sql, $pid, $ip, $data, $data);
Just compare these 2-liners with amount of code you will need to write using raw PDO.
I think the answer is pretty close to yes for "sql injection attacks".
mysqli prepared statements and mysqli_real_escape_string
There are still many other types of attacks, but at least all your values are escaped.
Relying on PDO to "fix" your security is like relying on a compiler to find your bugs.