PHP: Beginner question about public URL and queries - php

I have started studying PHP, and there is this one question that I don't seem to understand.
For eg. I have a PHP script at a URL: http://example.com/Test.php
If this script has a query that expects a parameter from the user (from a GET) then I could easily execute it like this:
http://example.com/Test.php?uid=2
where the query could be a
SELECT * FROM USERS WHERE UID = 2
Now I read that if I want to get sensitive information/upload to server I should use POST, but even if I use POST, I could still do the same in Postman with the parameters, and the query still executes.
I read about SQL injections and found that PDO is useful because it sends the query separately from the data to the server.
I have rewritten the first query with PDO, but I can still execute it with URL saying http://example.com/Test.php?uid=2. What am I doing wrong here? Am I misunderstanding something?
Questions:
Is having public access to the scripts normal? Because it seems very unsecure to me.
How is POST safer than GET when I can reproduce the same behavior in Postman?
Why can I still run my code with PDO's with entering parameters in the URL? Isn't the point that we send them separately to the server, and there it gets executed?

Now I read that if I want to get sensitive information/upload to server I should use POST
Forget sensitive. There is practically nothing security related in your choice of HTTP methods. The only thing is that your log files might record query strings in GET requests.
See this answer for further reading.
Is having public access to the scripts normal?
Yes. The entire point of giving a script a public URL is to provide information in public.
Why can I still run my code with PDO's with entering parameters in the URL?
The point of parameterized queries is to prevent SQL injection, where special characters are added to the data so that a query other than the one you intended to run is run. See Bobby Tables for a more in-depth explanation.
If you don't want people to run your query at all, don't give it a public URL.
If you want to limit what values people can pass into it, then write code which limits those values.
This might involve logic like:
If the user is not logged in:
send them to the login page
If the user does not own the comment they are trying to edit:
throw an error message
Otherwise:
run the UPDATE query

Related

MySQLi PDO - incremeting integers gives incorrect result when starting at 0 [duplicate]

On my games page, I have a page where they play a game. On that page I have a query
$insert_user_activity = mysql_query("INSERT INTO game_activity (user_id,user_full_name,game_id,game_name) values ('$user_id','$full_name','$browser_id','$game_title')");
Which will log it into my database, it's just sitting on its own and when I refresh the page, it is submitted to the database twice for some reason.
The logic of your front controller is wrong.
The page where you are executing this query is called on every request made to your site, no matter whether it's a proper request or a call to a non-existent resource.
You must change the logic of the front controller so it wouldn't run the application for the invalid requests. Otherwise there will be not one but thousands false inserts when the site goes live.
what's the conditions on the page for which the query execute or in other way how are values of the variable you are getting on the page to execute the query if it is so than first check the existence of variables if the variables are set than run the query.
I was having problems with a query that was executed twice in Firefox but in other bowsers (Chrome and IE) did problem did not happen. I was searching for an answer and found this post.
I discovered this:
If i execute a simple insert query it gets inserted twice when i switch on the "net" functionality in Firebug this does not happen. Strange. Just wanted to add this to this post.
Still trying to solve this.
{edit} Update:
I have found a solutions, although it is not a pretty one. I check first wicth an select count if such record exists, if not then it will be inserted otherwise it will not be. Did the trick for me.

How safe is a PHP function from being called by exploitative means?

Background
I use .htaccess to redirect every URI to a single PHP file that displays the right page by calling different functions with different inputs based on the requested URI. I found myself checking user input twice. Once in the handling PHP file that checks first if everything is fine before calling the display function and than again within the display function, to make sure nobody exploits the function by calling it with wrong parameters (e.g. with the username of someone else). This means, that I need twice as many mysql querys etc. for checking valid inputs.
I can't just check within a function because based on those checks, the handling PHP file calls different functions. So I have to perform the checks at least there. But the more I think about it, the more I wonder, if it is necessary to check again within a function. I started this because I was worried that somebody might call one of my functions with improper input, but I guess if somebody can call one of my PHP functions and pass wrong parameters, I'm pretty much screwed already right? Because as far as I understand PHP, this would mean that this person already has access to my server at least via a shell or something like that.
I should further add, that I never ever call a function via a variable like discussed in this thread: Call PHP function from URL
Question
Is it a security risk, not to check the parameters passed to a function within that function, if you already checked it before the function call?
Good rule of thumb - Pretend EVERYONE is out to pwn your app! (Yes get out your tin foil hat!). Good practice would be to clean the data for example putting data in a database, you should still clean it coming back out of the database.
Unless you are in a position where one of your functions is providing the parameters and there is no way to access the (potentially insecure) function except through the preparation function then I would advise cleaning all data
HTHs - Thanks,
//P
Check out Private Public and Protected Functions

How to know what query is made to database and returned with in php?

A php code sent a query to the database say credentials from login page for verifying and something was returned say TRUE OR FALSE as status. Now my question is, if I do not know the code of the developer who wrote the login form, does there exist any way to find out what query is made to the database OR what has been returned by the database? Since I'm unaware of the developer's code which means I'll need a parallel script working in parallel with the login form. Can I also do that? The reason why I asked this question is I just want to sanitize the output data from the database as being a little paranoid, I can't trust the data coming from the database. Some XSS issue, nothing more.
if you are using codeignitor then,
To enable the profiler place the following function anywhere within your Controller functions:
$this->output->enable_profiler(TRUE);
for more help : http://ellislab.com/codeigniter/user-guide/general/profiling.html

Using urldecode() results in MySql error

I need to pass special symbols through the URL for my MySQL query. For example, I need to have a URL that is something like:
www.example.com/index.php?q=AND name LIKE '%hi%'
When I tried it at first, I got a 406 error. I looked it up and apparently I have to use urlencode() and urldecode(). I put those in, and the 406 error went away, but then I got a MySQL error:
mysql_fetch_array(): supplied argument is not a valid MySQL result resource
Usually when I get these it means the query isn't written properly. So I echoed MySQL query, and everything looked fine. I even removed the urldecode() and hard-coded into a variable what I wanted to be passed to the page, and the MySQL error went away. However, both queries from using urldecode() and not using that are EXACTLY the same, so I'm kind of confused.
I went onto the php.net documentation page for urldecode(), and there was a warning that said something like using _GET and urldecode() together can result in unexpected things, and that _GET already functions as a decoder (or at least that's how I interpreted the wording), so I removed urldecode() but still left in the _GET, and that resulted in the text not being decoded, so I guess I didn't interpret the documentation correctly.
Is urldecode() not compatible with MySQL queries? I'm fairly certain it's an issue with the encode/decode, since I already tested my code with hard-coded info that bypassed the encode/decode, and it worked fine. Maybe the urldecode() is somehow turning the characters into special ones that look the same but are internally different so MySQL can't read them?
Don't do this. It's wrong. Anyone can of course just end the query using a ; and start a new one, deleting everything or reading out users and passwords.
One easy and much better way to do this is to use www.example.com/index.php?q=hi as your URL, then on the server (let's assume PHP)
$queryString = mysql_real_escape_string($_GET['q']);
$query = "AND name LIKE '%$queryString%'";
// Then replace $query for whatever you were using $_GET['q'] for before.
// Feel free to rename my variables what you like!
This way, the user can't mess things up, and the URL looks cleaner. the mysql_real_escape_string function makes the string safe to use in the query by escaping things. Read http://php.net/manual/en/function.mysql-real-escape-string.php for more on that.
If you still aren't convinced this is useful, consider what happens if someone publishes a link that will drop your tables, and then Google crawls it once a week. Your data will be removed any time that Google happens to swing by.
Once you are happy with this technique, read up on mod_rewrite (if using Apache) to clean the URL up even more, mysqli and how it is an improved version of the mysql functions, and finally PHP Data Objects (PDO) which helps to clean the PHP up even more.
Rich has the right general idea, but even better than quoting is to use database parameters. It essentially places a "variable token" into your SQL query, and then passes the variable separately. The query ends up looking something like this:
SELECT ID, VALUE1, VALUE2
FROM MY_TABLE
WHERE VALUE3 = :param
And then in your code, you add a value to substitute in for :param, and then send that to the database alongside your SQL. (On some DB libraries, you'd use a ? instead of a :parametername.) It works better than quoting for three reasons:
First, you can keep the query string constant instead of having to rebuild it every time, which improves performance in your server.
Second, if you send the same constant query to the database multiple times with multiple different parameters, the database engine can cache the query plan, which improves performance on the DB.
Third, when you get used to writing your queries in parameterized style, it becomes natural, especially if you use a query function that takes a parameter list as an argument, so it's hard to get wrong. By contrast, it's easy to forget to quote something, and then you've accidentally opened a security hole in your program.
Exactly how parameterization works depends on the database and the DB access library you're using, but every SQL database supports them. You should look at how it's done for the system you're using. It really is the best way to work with SQL, especially when you have input coming from untrusted sources such as the Internet.
At some point after calling mysql_query() and before calling mysql_fetch_array() you should check that the query didn't return false, and print mysql_error() if it did. e.g.:
$result = mysql_query($query);
if (!$result) {
die(htmlenitites(mysql_error())." when running <pre>".htmlenitites($query)."</pre>");
}
But:
You shouldn't be using php's mysql functions, you should use PDO, and you should use prepared / parameterized queries.
You shuoldn't be letting SQL be passed from the client unless you really trust anything the client might type - e.g. this is for a back-end admin interface, and even then, it's probably bad practice unless you really need it (like you are writing phpMySQLAdmin)

Php script, query ran from value thats passed in

I am pretty new at php, quick note this is an android application that i am calling this script, I am not having the users make up the script lol. There is a series of checkboxs and when they check off certain ones it appends a script to the string builder. i am trying to run a query based on the value of a variable that is being passed in. Usually i do something like this,
mssql_query("UPDATE Userdata SET BrowseScript = '".$_REQUEST['sqlscript']."'
WHERE Userdata.Username = '".$_REQUEST['Username']."'");
and where it says .$_REQUEST[''] I can grab values that i pass in.
But this time the .$_REQUEST[''] is the whole script, so i want something like this
mssql_query($_REQUEST['sqlscript']);
and thats it i want it to run the query thats in that value, The query is correct, but it just will not return any value, I think i may have some type of syntax error or something, like i said i am new to php. Thanks for any help. Also I am not posting the whole code because everything is running ok, i just cant get that query to run. so all i need assistance with is the mssql_query part thanks again.
First of all there is huge security flaw in what you are doing. You should always sanitalize and escape the variables you use in your queries for example using mysql_real_escape_string or prepared statements.
Since you are importing whole script for your query, it could be that quotes are not escaped. You need to put these functions like this before your variables:
mysql_real_escape_string($_REQUEST['your_var']);
Using $_REQUEST in itself instead of proper $_GET or $_POST is vulnerable.
Tell your script to output the contents of $_REQUEST['sqlscript']
echo $REQUEST['sqlscript'];
Check that the output is correct. You might well find that there are some parsing errors, or just that your script is incomplete. Check for quotes (") and make sure the query is valid.
Also, you should never run a script from a request. Imagine if someone browsed to your site and typed
youtsite.com?sqlscript='drop * from tables';
Your entire database would be wiped.
For all that's holy, do not do this!
You do not just use request parameters and put them in SQL queries. You at the very least use mysql_real_escape_string (or whatever the MSSQL equivalent is, never used it). And you most certainly don't accept whole queries in the request and execute them sight unseen.
You're opening huge gaping security holes. Especially if you're new, stop that now before it becomes a habit!
example.com/foo.php?sqlscript=DROP TABLE users
Minimum required lecture: http://www.php.net/manual/en/security.database.sql-injection.php

Categories