I have a php file at my site, and I connect to db, get some records and list them in same file.
mysql_connect("localhost", "blabla", "blabla") or die(mysql_error());
mysql_select_db("blabla") or die(mysql_error());
$blabla1 = mysql_query("SELECT * FROM gallery WHERE id_cat=1");
$blabla2 = mysql_query("SELECT * FROM gallery WHERE id_cat=2");
$blabla3 = mysql_query("SELECT * FROM gallery WHERE id_cat=3");
So, is there anything I need to do for security? Like sql-injection or anything else. there is nothing going to url. It is just www.blabla.com/gallery.php.
This snippet is perfectly safe, because there are no variables put into the query string.
To work safely in case you have to deal with variables one day - be they directly coming in from the user, or from another data source - you may want to switch over to a mySQL library that supports parametrized queries, like PDO. Those eliminate the danger of injections completely, because they take care of escaping the incoming data automatically.
If you stick with the mysql_* functions, make sure you escape all incoming any data using mysql_real_escape_string() and ensure they are inserted within a pair of single quotes.
As long as your queries don't use parameters, SQL Injection is not a risk.
SQL Injection can only happen when the users (or other sources) can influence anything that is send to the database in SQL, for example searchwords
There are no security issues here. SQL injection might happen where you get input from the user and use it in your queries.
if gallery table contain some user input, then some XSS attack may be conducted. To prevent this, all untrusted user input must be prepared using htmlspecialchars() function before printing to the browser.
This snippet is safe, as there is no user provided input in the queries.
if you have userinput, for example by getting the category that should be displayed from the URL or from POST you should use prepared statements. this may you are safe even with user input. This is much safer than pure escaping because the sql is parsed and then the parameters are inserted. This is better for performance and the userinput can't change the structure of the sql query.
The only thing that you might want to consider, assuming that the connection code is in the web-accessible PHP script, is to either:
move the MySQL connection out of the
script and into a file outside of
the site's document root
or, use externally-sourced variables
(i.e. from a different file outside
of the document root) for the
username and password in place of
hard-coded details in the script
That way if, for whatever reason the server displays the code instead of rendering the PHP, then the details will remain safe from view
Related
Basically I am making a web application and I am going through the security of it to make my app as robust as I can.
Once you're logged in to my app I track that user based on session variables.
When SQL is performed it takes the users session variable to see who they are for example.
$name = $_SESSION['user_name'];
A example query would be something like this..
$query1 = "SELECT * FROM tableName WHERE userName = '$name'";
From reading online sites say things like I must not use "user input in SQL statements." Am I right in thinking that because I am using session variables the user does not have direct access to the sql statement or is session variables still "user input"?
If not should I just go through the normal SQL Injection prevention methods like...
Input validation (authenticating the data based on length, syntax
etc)
Checking user privileges making sure users have the least
privileges.
ect..
Thanks in advance for any comments anyone makes.
It doesn’t matter where the data came from as in any case you have to ensure that the data is interpreted as intended.
And one of the easiest way to ensure that is using parameterized statements, where the SQL code and parameter values are passed separately so that a parameter value can’t be mistakenly interpreted as SQL.
Prepared statements implement this parameterization, either native or emulated. With them you don’t have to worry about whether a value may be influenced by a user’s input.
Always escape input. What if their name is "David O'Connor" or something.
This name is assumedly user supplied, so do it.
Anyway, you shouldn't be directly issuing SQL queries, a function should be building them for you (or an ORM).
Am I right in thinking that because I am using session variables the user does not have direct access to the sql statement or is session variables still "user input"?
The problem you might have in your example is that the username might be something controller by the user. They might be able to change it or choose it depending on your application requirements.
I think the simplest way to prevent surprises is stop thinking too much and just protected your queries agaisnt SQL Injection.
I'm no expert on PHP, but I think you have prepared statements that will help you dealing with this security issue. Just use it. (it should be a slogan, "prepared statements, just use it." :D)
Any login/create-user page you have should do input validation before writing the userName column in your database and writing $_SESSION['user_name'].
AFTER that, your $_SESSION variable is safe. You have to do validation checks somewhere in the process:
Input -> store in database/session -> use
I recommend at the 1st arrow. Then the code snippets you wrote in the question are perfectly fine.
Am I right in thinking that because I am using session variables the
user does not have direct access to the sql statement
correct. $_SESSION-vars are stored on your server-filesystem and unless you introduce user-input ($_GET & $_POST, for example) into them there is no actual way of manipulation for these. If you generate $_SESSION['user_name'] without actual userdata you're well off. The hard part is getting the username without parsing input - one would be advised to use HTTP-data-filtering frameworks for these kinds of jobs.
I have pages that only display data from DB tables, the php pages only display the information they don't have any buttons, links, drop down menus, or forms.
Im using the old mysql and not the mysqli or PDO for syntax
Can I still get a SQl injection hack?
In order for SQL Injection to work, they need a way to send SQL Code to your server, as there is no input, it is in theory impossible for them to Inject SQL. (Although I am not an expert in the subject)
I would still recommend you to use a framework like mysqli or PDO, you should familiarize yourself with such frameworks as they became the norm in website design.
SQL Injection works by injecting strings into the SQL you're executing.
This is easiest if the application presents you with a nice text box whose content it glues into a SQL query, but it's also possible through other means.
For instance, if your reporting application uses any kind of the HTTP request to show data, an attacker can use WGET to spoof the request and inject SQL. For instance, if your reports have a URL format of http://myserver/report.php?month=february and you use february to build a SQL query, you're vulnerable.
It all depends on the query source. If ANY part of your SQL query comes from a user input (in other words; if not your whole query string is a string constant) then you are not safe.
For example:
SELECT * FROM USERS ;
SELECT * FROM myTable WHERE id = 5;
is safe but
SELECT * FROM myTable WHERE id = (some variable derived from user input like querystring or post-form)
is DEFINETELY not.
You should use
SELECT * FROM myTable WHERE id = #0
syntax for maximum security. This is the only one proven way to keep safe from SQL injection.
If the query is independent of the request you are safe. Be warned that mean users are very creative. You might have some dependency on user data which you are not aware of. E.g. a script like this might be broken:
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$sql = "SELECT * FROM entities WHERE id = 7 and locale = '$locale'";
Disclaimer: I'm not aware if Locale::acceptFromHttp() does some validation. Let's just assume for the context of this post it doesn't.
I don't want to say it's not possible to write safe code without prepared statements. OTOH it really doesn't hurt using them.
SQL injection occurs if user-controllable data is used in an SQL statement without proper processing:
The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.
Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
Note that user-controllable data include any data that can be influenced by the request of a user, directly or indirectly.
Conversely, this means if your SQL queries don’t contain any user-controllable data, i. e., the queries are fixed in code and are not influenced by any changeable input, it cannot vulnerable to SQL injections.
I have pages that only display data from DB tables, the php pages only display the information they don't have any buttons, links, drop down menus, or forms.
I would dare to say that such a setup is just impossible.
The very idea of having a dynamical web-page, served by a php script from database, is to use the same script to show different content from database.
So - either you indeed have only set of static pages (which I doubt) - you need no PHP/database for them then - just static HTML would be enough.
Or - most likely - you have dynamical pages showing content based on user input of some sort - and thus perfectly vulnerable.
In my php code i can get data with php $_GET method. Here is code look like this..
<?php
<a href='userprofile.php?uname=$uname'>$uname</a>
?>
If i click the the link it's show user profile page and so that userprofile.php page's url look like this.
http://localhost/evantechbd1/userprofile.php?uname=shibbir
My question is how do i prevent this url from sql injection or any other attack.
If I write:
http://.......uname=shibbir'OR'='-1-'
then it's show:
SHIBBIR%27OR%27%3D%27-1-%27'S PROFILE.
BUT I want whatever text is provided to that link it's must be show only valid username profile page.
Any idea.
The best way is to use a prepared statement, see the examples here, although I normally do some data validation even on data that is going to be used in a prepared statement.
For example, if someone registers, there are only certain characters allowed in a username and I use that same check when someone enters a username to be fetched.
You can't prevent someone from ATTEMPTING the attack, you can only prevent the attack from succeeding. However, what that prevention actually IS depends entirely on what you're going to use the database. There is no 'magic bullet' function that will make every bit of data safe in every case, as many 'sanitization' functions destroy data that is necessary in other usage cases.
e.g. there is no point in doing an SQL injection attack prevention with (say) mysql_real_escape_string() if the bad data is never going to be used in an SQL query. Doing htmlspecialchars() when the string is not going to be used in HTML context is similarly useless.
Before using $uname in your SQL, escape it.
For example, if you use the old but gold PHP MySQL extension:
$uname = mysql_real_escape_string($uname);
$res = mysql_query("SELECT * FROM users WHERE name = '$uname'");
If $uname is shibbir'OR'='-1-', after using the function I wrote, it will be shibbir\'OR\'=\'-1-\', that is unable to break your query.
Read more here:
http://php.net/manual/en/function.mysql-real-escape-string.php
http://www.php.net/manual/en/security.database.sql-injection.php
The other issue then is cross site scripting exploits. There are several ways of dealing with this but the usual way is to check that $_GET[ 'uname' ] exists as a username in your database first before using it in the html block.
I'm trying to secure my script a bit after some suggestions in the last question I asked.
Do I need to secure things like $row['page_name'] with the mysql_real_escape_string function? example:
$pagename = mysql_real_escape_string($row['page_name']);
I'm asking mainly because when I do secure every row I get some errors like when trying number_format() it throws number_format() expects parameter 1 to be double, string given while when it is not secured with mysql_real_escape_string it works.
Can someone clear this for me? Do I only need to secure COOKIE's or the row fetches too?
I got the suggestion in this post: HERE (look at the selected answer)
You're doing it backwards. Presumably $row is a row coming out of the database. You don't mysql_real_escape_string on the way out of the database, you use it on data going into the database to prevent SQL injection. It prevents people from submitting data that contains executable SQL code.
Once the data is safely in the database, you're done with mysql_real_escape_string (until you attempt to update that data). User data coming out of the database needs to be run through htmlspecialchars before it hits the page to prevent script injection.
Basically, on the way to the database, just before your insert/update runs, you need to escape potentially executable SQL. On the way to the browser, just before strings leave your app for the browser, you need to escape potentially executable JavaScript and/or interpretable HTML. Escaping should be the last thing you do with a piece of data before it leaves your app for either the browser or database.
This is by no means a complete answer.
Before writing any more code you need to stop and consider exactly what it is you are trying to accomplish.
In other words, what are you gaining by running the mysql_real_escape_string function?
Generally speaking, you escape data submitted by the client. This is to help prevent sql injection. Also, you should go further to actually validate that what the client sent in is acceptable (ie. "Sanity Check"). For example, if you are expecting a numeric entry, don't accept strings and range check the values. If you are expecting string data like a name, don't accept HTML, but again range check to verify length is acceptable. Both of these situations occur when the client submits data, not when you are writing it back out.
Going a little further, your cookies should be encrypted and marked with the httponly flag to tell the browser that it is not for use in client side script. Even with that, you shouldn't trust the data in the cookie at all; so go ahead and run your sanity checks and still escape those values in queries.
I highly recommend that you go to the OWASP website and read through all of the issues to get a better understanding of how attacks work and how to defend against them. Web App security is too important to just start coding without really knowing what's going on.
BTW, kudos to you for learning about this and trying to defend your site. Too many devs don't even think about security at all.
If you use the PDO extension to build clean requests, you can create functions that will do this (secure strings and define their type) :
An exemple where $text is a string of text and $number is an integer :
public function InsertThis($number, $text) {
$pdo = $this->getPdo();
$sth = $pdo->prepare("INSERT INTO my_table (number, text) VALUES (:number, :text");
$sth->bindParam('number',$number,PDO::PARAM_INT);
$sth->bindParam('text',$text);
$sth->execute();
}
http://php.net/manual/en/book.pdo.php
You only need to use mysql_real_escape_string() when inserting/updating a row where the values have come from untrusted sources.
This includes things like:
$_GET
$_POST
$_COOKIE
Anything that comes from the browser
Etc..
You should only use it when putting things into the database, not when you are taking things out, as they should already be safe.
A safer way altogether is to use the PDO class
mysql_real_escape_string does not "secure" anything. It escapes characters that can be used in sql injection attacks. Therefore the only values that you should escape are the ones supplied by your users. There should be no need to escape things that come out of your own database.
I read a lot about filtering data which my web site get from user to make web site secure in sql injenction and xss . . .
but I saw a lot function in php so I can't make decide what to do . . .
please help me make it more secure
You're asking a couple questions here, so I'll try to break it down:
SQL Injection
Problem
This can occur when you pass user input directly to the database, something like this:
$query = "SELECT * FROM Table WHERE field = " . $_POST['field'];
$result = mysql_query($query);
The user can put whatever they want into the 'field' field on the form, and the database will execute it. This means a user could enter a malicious string which prematurely terminates your intended query and then runs a query of their own.
Solution
Don't directly construct your queries with user input. Instead, you should look into using prepared statements (This is typically handled with the PDO library). Prepared statements can take several forms, but they all involve using placeholders in the actual query string to tell the database where to stick other data you'll pass in later. That way the database can handle any appropriate escaping itself. The code would look a bit like this:
$statement = $db->prepare("SELECT * FROM Table WHERE field = :field");
$statement->bindValue(":field", $_GET['field']);
$statement->execute();
In this case, :field indicates the placeholder for the value later supplied by bindValue. PDO will take care of the escaping as needed.
That said, you should still sanitize any user data as needed.
XSS
Problem
Cross-Site Scripting, or XSS, occurs when unsanitized user input is passed directly back to the browser. If the user entered JavaScript commands, these commands could be executed in another users browser, possibly allowing the original hacker to gain access to that users credentials.
Solution
Rather than going into a lot of detail here, I'll simply say that this can be avoided by setting the HttpOnly flag on any cookies you set, so that they cannot be accessed in JavaScript (malicious or otherwise), and by never, ever echoing back unsanitized inputs to a user.
Sanitizing User Inputs
PHP has some nice features built in for sanitizing many forms of user input. I'll simply recommend that you check out the filter_var function and the various filters it can apply.
Never just echo user input back to the user. You should do your best to validate your inputs and reject anything that doesn't conform, but for inputs you need to display back to the user, always use something like htmlentities(). For a heavier but much more thorough option, you can take a look at the HTML Purifier library.
Hope that gets you started in the right direction.
Most SQL injections can be prevented with mysql_real_escape_string(), assuming you're running MySQL. Other database systems also have similar functions.
Protecting your site from XSS attacks is more complicated. The simplest way to prevent javascript code injection is stripping away all HTML tags with strip_tags(), but that will prevent using harmless tags like <b> as well, though they can be whitelisted if needed.
The only generic advice I can give you is to learn:
Prepared statements to avoid SQL injections
A custom markup languages like StackOverflow is using to avoid XSS attacks