The short version: Is there any way to write an HTML form such that the $_SERVER['HTTP_REFERER'] in the PHP script will not be what it really was (ie spoofed)?
Here's why...
I've got a news archive database, and we need a way to enter the news, so I'm trying to do that through the web. In the database is a news table with a news id (which can be called up to show 1 article specifically), entrydate, title, and the HTML code for the article. It's in MySQL. We have another table called 'datesmonth' which has displayname (January, Februrary, etc), startdate (2005-01-01, 2005-02-01, etc), and givendate (jan05, feb05, etc). In the news archive we reference datesmonth (because not all months have news so rather than have ppl click on a month and have "No News" displayed, we just won't show that month) to get all the months from the database. I have another table with 2 fields, username and password. They're in MD5. Neither of the MySQL accounts have access to this table other than SELECT for the administrative script.
OK, so basically, I came up with an idea of using 1 script to:
- Enter news
- Modify existing news/delete news (first need to display all news available to edit)
- Remove months from datesmonth where they have no news
- Login to this thing
OK, so first thing I do is check to see if $_POST['username'] is set. If not, display login screen. Then it is set when they submit that form to the script.
Next, if $POST['username'] is set, and $POST['authorized'] is not set, I run a mysql query to see if md5($POST['username']) & md5($POST['password']) match up to the database. I store the number of rows returned into $authorized. If it's 1, then login success, otherwise not (redisplay login screen w/ error msg).
Then it leaves the authorization part, and jumps to a pick a thing to do part. I have <input type="hidden" name="username" value="1"> and similar for authorized value=1.
After that is submitted, then $POST['action'] is set, and $POST['authorized']==1, I have a switch($_POST['action'] and code for each of the various actions.
Now, as you may have noticed, the login verify is done once. So, you might realize there's a huge backdoor. I found it quickly and tested it to see if it does indeed have a backdoor. If one were to write an HTML page on their PC:
<form action="URL to the script" method="post">
<input type="hidden" name="username" value="1">
<input type="hidden" name="authorized" value="1">
<input type="action" name="action" value="modifyselect">
<input type="submit" value="Hack it"></form>
it does indeed work and they would be able to do anything.
I came up with this for another requirement for the IF() before the SWITCH...
'http://'.$SERVER['HTTP_HOST'].$SERVER['PHP_SELF']==$_SERVER[HTTP_REFERER']
Now, I found that the HTTP_REFERER for the backdoor page would fail here thus preventing that. Requiring that the previous page to get to the action was the script itself.
If you can spoof the REFERER, then how should I go about this, can it still be done with 1 script? (FWIW, there's 2 ppl in my department and the other one is my boss who doesn't know PHP...)