I want to allow users as well as me(the admin) to delete data in mysql.
I used to have remove.php that would get $_GETs from whatever that needed to be deleted such as... remove.php?action=post&posting_id=2. But I learned that anyone can simply abuse it and delete all my data.
So what's the safest way for users and me to delete information without getting all crazy and hard? I am only a beginner :)
I'm not sure if I can use POSTs because there is no forms and the data isn't changing.
Is sessions good? Or would there be too many with postings, user information, comments, etc.
Ex: James wants to delete one of his postings(it is posting_id=5). So he clicks the remove link and that takes him to remove.php?action=post&posting_id=5.
EDIT: Alright, so now I am a little confused. While I can't be 100% secure, how do I do this with $_POSTs?
SOO I should use GETs to get all the data to remove.php, THEN have a confirmation submit button and when users click on it, it put all the data into POSTs and delete from the dbc?
Deleting records is a kind of a scary practice. If you or someone makes a mistake there's no real recourse to resolve the issue. Expunged records are very hard to resurrect.
Instead of deleting records, you could add an "active" bit (e.g. Boolean) column that is toggled off when users "delete" records. Essentially your users would be suspending records by toggling them off and the records would be saved in case mistakes or abuse but appear "deleted" to the user. To make this work with your other queries, just add a where clause of active = 1.
You could then have a utility script that's run at some specific date interval that would clean out deprecated, past dated records. You'd also need some type of timestamp for this type of maintenance.
Just a thought. Take if for what it's worth.
I'll echo gurun8 in preferring to 'mark' records as deleted, instead of actually removing data. And then obviously, you'll need to check that the authenticated user has permission to delete the post.
However, it seems very important to mention that $_GET is not safe even with authentication because of cross-site request forgery.
Imagine if Amazon adding things to your cart based on a GET request. All I'd have to do is put an image on my page with that URL, and everyone who visited that page and logged into Amazon will have products added automatically.
To match your example, I don't like Jame's post, so i put an image on my site like this:
<img src='http://example.com/remove.php?action=post&posting_id=5'>
And I send him a link to my page, and ask him to check it out, hoping that at the time he's logged in to your site. Because, of course, he clicked that little 'keep me logged in' button.
So you are right to be concerned about using GET. If you don't want to litter pages with forms, then confirm the action by POST.
Well you have to start by authenticating the users with a login script.
If you want the simplest solution possible, then I'd suggest protecting the directory in which you have remove.php with a simple .htaccess username and password.
If different users have different rights for deleting database entries, then you probably should create a PHP login script and use PHP session.
Bonk me if I'm stupid, but I searched for quite some time for a simple PHP login tutorial that could be placed on a real site (doesn't use session_register(), uses mysql_real_escape_string(), htmlspecialchars() etc) and I simply couldn't find one!
Probably this one comes the closest, you just have to replace session_register() variables with $_SESSION ones for it to work without register_globals (default in PHP5).
Related
so I've hit a potential problem in my site....it's a post-based system, with the posts being in text files. Uses some Javascript and a lot of PHP.
When you make a submission on the form on the homepage, you are sent to a page where data is posted and processed, but you don't see it because you get redirected back. Then the homepage is changed based on what the post you made says. All that was working fine.
But now I'm trying to add a new feature that modifies the post you made, based on a button you hit which submits a hidden form using javascript, and sends to another process and redirect page you don't see, and it works fine until the block that I realized today. I don't know how to specify that the post being altered is the right one.
I anticipate a good amount of users of this site, so my concern is what if user X makes a post while user Y is making a post, and the post of user X becomes the top post, so user Y's options actually change user X's post.....
I was thinking of adding to the main processing page (the one that happens when you first submit) a COOKIE or something that would make note of the number of the line that post will become, by counting the number of the lines in that file at the time and adding 1 to it. Then checking it against the user's number (each user has a number) to see if it's that user's most recent post....but the problem is I don't know how I would pass that value around to be read in the next page.
Setting a COOKIE is out I think because the page both redirects, AND reads and writes to files. The only output to the page though are currently var_dumps.
POST/GET is out because to my knowledge the user would have to do SOMETHING to submit it, and the user's not even going to see the page.
Writing to a file would be messy if lots of users are trying to get their own data.
I think what I may be looking for is SESSION variables...but I don't know anything about those except that they're used to login to pages, and this site has no login.
To make things more fun, when a user posts the same content within a minute of another user, the first user's post is replaced and it gets a little +1 next to it...which makes it harder to check it against the user's number....
AND in the end I'm trying to use AJAX (which I dont know yet) to make the updates in real-time...now THAT is going to suck. But for now I'm worried about my static little site.
Baby steps.
Any ideas how to go about this??
Use Session variables, just as you have alluded. They aren't just used by login pages, they are used by everything. Sessions are the equivalent of server-side cookies / server-side storage, so you don't have to worry (as much) about your users tampering with them.
If you want to make life more difficult for yourself, you can json encode your variables and store them as an object in a database or even flat text file. But really, read up on sessions.
All you need to know is session_start(); before anything else then $_SESSION['var']=$yourvar; to save data and $_SESSION['yourvar'] to retrieve it later (such as on another page).
I have a classifieds website, where anyone (no need for login currently) can post a classified. It is PHP based.
The procedure for posting is currently like this:
click on "New Classified" --->
fill in a form of all information and hit "View classified before publishing it" --->
the form submits to a "verify classifieds" page, where users verify their inputs --->
If everything is okay in the "verify" page, then the user hits OK and the classified is published.
The above procedure isn't exactly optimized. The first page (new_classified) where the form is, is pretty good, but the second page (verify) uses x number of hidden inputs in another form, used to contain the previous pages form inputs.
Now you know how it works on my site.
The issue today is that alot of companies want to publish their classifieds, and alot of classifieds at the same time. This means they have to fill out the form again and again currently.
I am thinking about creating a login, for companies only, so that their information is automatically inputted into the form, so all they would have to do is fill out the specific classified details like "headline" and "description" etc.
How should I do this in my case? Sessions?
This means I will have to create a new MySql table (I use MySql mainly) and store company-profiles there.
So do you think converting to sessions is alot of work? Worth it? More reliable?
I have never used sessions so I wouldn't know.
As a last note, you should know that I use a picture upload tool on the first page of "new_classified". When a user choses a file to upload, the page is automatically *refreshed*, and then the image is displayed on the same page under section "images uploaded". I hope the session wont interfere with this approach.
Thanks
I think it is worth your while to do logins, and even on a very basic level it will help you to identify who is using your site etc.
This is probably a big debate around developers, what is the best way to do a good login system, whether it's basic or not doesn't matter, I think the concepts still stay the same.
In your case I would suggest session cookies along with a login table consisting of user details. This would help you to verify the user on more than one occasion during his/her visit to the site.
A login is checked against a user entry in a table and then a session cookie is created. This session you can choose to never expire also.
You can then on every step check that the user is the user that is supposed to be logged in and get the companies details by checking the username. This would make for a better query in my opinion.
Sessions aren't a lot of work and it's relatively easy to learn.
http://www.php.net/manual/en/book.session.php
http://www.9lessons.info/2010/02/php-login-script-with-encryption.html is a good example of what you can do with this. Have a look around still. There are a bunch of these great tutorials on the web.
Sort of a methods/best practices question here that I am sure has been addressed, yet I can't find a solution based on the vague search terms I enter.
I know starting off the question with "Fast and easy" will probably draw out a few sighs, so my apologies.
Here is the deal.
I have a logged in area where an ADMIN can do a whole host of POST operations to input data relating to their profile. The way I have data structured is pretty distinct and well segmented in most tables as it relates to the ID of the admin.
Now, I have a table where I dump one type of data into and differentiate this data by assigning the ADMIN's unique ID to each record. In other words, all ADMINs have this one type of data writing to this table. I just differentiate by the ADMIN ID with each record.
I was planning on letting the ADMIN remove these records by clicking on a link with a query string - obviously using GET. Obviously, the query structure is in the link so any logged in admin could then exploit the URL and delete a competitor's records.
Is the only way to safely do this through POST or should I pass through the session info that includes password and validate it against the ADMIN ID that is requesting the delete?
This is obviously much more work for me.
As they said in the auto repair biz I used to work in... there are 3 ways to do a job: Fast, Good, and Cheap. You can only have two at a time. Fast and cheap will not be good. Good and cheap will not have fast turnaround. Fast and good will NOT be cheap. haha
I guess that applies here... can never have Fast, Easy and Secure all at once ;)
Thanks in advance...
As a general rule, any operation that alters state (whether its session state, or database state) should use POST. That means the only 'safe' SQL operation you can perform with GET is SELECT. Even if you're only using a back-end admin thing, you shouldn't use get. Imagine re-opening your browser and finding that the last time you closed firefox was on your 'DELETE EVERYTHING' GET->delete page resulting in everything being deleted again.
One of the main reasons for this is preventing cross-site request forgeries. For example, if you had a page that took a GET variable such as http://example.com/account?action=logout, an attacker could post an image on your site like this:
<img src="http://example.com/account?action=logout" />
and anyone who opened a page containing that image tag would be immediately logged out, even if they were an admin. It would be very annoying to then search through your raw database for that data and remove it.
Although POST operations are 'nearly' as easy to forge, as a general rule with any web security issue, the trade-off is speed/simplicity vs. security, so you're going to have to choose one or the other.
You should have some kind of session set up.
Using POST over GET gets you nothing tangible as far as security is concerned. POSTs can be forged just like GETs.
So assuming once your admin logs in, you've got some kind of identifier in the session, you just leverage that.
Consider something roughly similar to this:
<?PHP
session_start();
if (empty ($_SESSION['admin_id'])) die("Log in, son.");
if (empty($_GET['record_id'])) die("You've got to tell me which record to delete!");
if (! is_numeric($_GET['record_id'])) die("Invalid record ID");
//just to be totally safe, even though we just enforced that it's numeric.
$record_id = mysql_real_escape_string($_GET['record_id']));
$sql = "DELETE FROM table WHERE record_id='{$record_id}' AND admin_id = {$_SESSION['admin_id']}";
mysql_query($sql);
echo "Record was deleted (assuming it was yours in the first place)";
?>
In that example, we're avoiding the "delete someone else's records" problem by leveraging the WHERE clause in the DELETE query. Of course, to be more user friendly, you'd want to first fetch the record, then compare the admin_id on the record to the admin_id in $_SESSION, and if they don't match, complain, log something, throw an error, etc.
HTH
You're saying: "What if Admin 123 access the URL of Admin 321 directly, thus deleting his stuff?" no?
If that's so then, every admin that is logged in should have at least one session with some unique identifier to that admin. If not, he shouldn't be able to be in the admin section in the first place. Can't you just compare the identifier in the URL with the identifier in the session?
If any user, not just an admin, access those 'delete me' URLs he should be identified by a session as the original 'owner' (admin) of that data.
Hey guys, im building a small product catalog for a client. I am currently trying to figure out how to go about allowing the user to sort by "popularity". I figured the easiest/simplest way to do this would be by having a "views" field in each product record.
Originally I didn't think this through (duh) and thought I would just add one to the "views" count when the function to retrieve a specific product is called. Of course the problem with this is that it doesn't account for someone refreshing the page 30,000 times.
What is the best way to go about this? Does php have any sort of way to see if a visit is unique?
I am using php/codeigniter/mysql/html/css/javascript/jquery.
You could store if the client has already visited the page in a session variable, and run the same views query. Now this won't prevent a user from closing the browser, reopening, and returning, but it should provide a decent level of protection. If that's not enough you can move to cookies, followed by user registration, or IP tracking.
Okay, the session approach. On your page you run:
session_start();
if(!isset($_SESSION['page_views']['some_unique_string'])){
$_SESSION['page_views']['some_unique_string'] = true;
// update your database
}
Note that you'll want to make sure 'some_unique_string' is unique to the page you're tracking views on.
The approach is nearly identical for cookies.
If you want to make sure the page views are unique you have to store the remote IPs of all the page views. There's really no other reliable way to know if a visitor has visited or not. Placing a cookie on their system will fail at a later date for a million different reasons, they cleared their cookies, they used a different browser, etc. You need a views table with a foreign key back to whatever you're counting views for.
You can find all of this sort of code in my free rated images script here:
http://destiney.com/php
Here's a demo:
http://ratedsite.com/
Look at the addImageRating.php script.
Lets say I have a website with links to various books on my main page.
<a href='books.php?id=1'>Book 1</a>
<a href='books.php?id=2'>Book 2</a>
<a href='books.php?id=4'>Book 3</a>
Books 1-3 are in my system, however id=3 is apart of another catelog that I'm not showing or authorizing through this section of the site. So if a user clicked on Book 3, then changed the id=4 to id=3, they could simply pull up the record (assuming I don't have proper session checking).
Is there a good way to obscure the get id that you're passing when trying to pull a specific record? it seems by passing just the id would be easy to request pages that, without proper querying and session checking, you would be able to get another result.
Is there a better way to do this?
Cheers
You need to always, always, check that user is able to access the page. That is the only way to verify that you don't show wrong data, because someone can always modify the link they are going to, even if you somehow hide it.
There is just no escaping it. You always need to verify that the record can be accessed.
You probably could hash your id or something using md5 or whatever to make it harder to manually enter, but that's really not a good idea.
What you should do is to implement server side security in your books.php script that will prevent users from unauthorized access. That's the only thing that will keep your site secure.
Just check id if it is allowable to display or not.
With get's a good practice is when you check whatever parameters you may have.
just thinking out loud:
you can make a column in your book mysql table saying "visible" ... or userlevel in your users tables.
do a php function or if statement that:
if (user is not in user_level) // user is not allowed to see everything
{
redirect to previous page;
}
else if (user is in user_level) // user is allowed to see everything
{
display all items;
}
You definitely need to check whether the user is allowed to view the page.
But, what if you separated the ids for the different catalogs? URL's could look like books.php?cat=foo&id=1. That wouldn't necessarily make things any more secure, but it would prevent people from accidentally finding the wrong pages and organize things a little better.