Hi,
By considering some latest issues, I was little bit concerned how to make sure that _POST request is proccessed only if is sent by some specific page.
For example if you post a Form from Page 1, and action is on Page 2, I wanted to make sure that it is not possible to proccess POST requests sent from another (remote) page/ site..
It becomes more important when I use forms for frontend editing , and JQuery post requests, so I can not include admin wrapper script.
Here is a code I would like to share:
<?php //color your live ;)
if(isset($_POST['page_id']) AND is_numeric($_POST['page_id']) ) {
$page_id = mysql_real_escape_string(strip_tags($_POST['page_id'])); } else { $page_id = '';}
// create _SELF_ link, For testing hacker attempt below !!
// Get page extension - .php
$query_main_sett = $database->query("SELECT * FROM `".TABLE_PREFIX."settings` WHERE name = 'page_extension' ");
$wb_main_sett = $query_main_sett->fetchRow();
$wb_default_page_extension = $wb_main_sett['value'];
// Get PAGES directory
$query_main_sett1 = $database->query("SELECT * FROM `".TABLE_PREFIX."settings` WHERE name = 'pages_directory' ");
$wb_main_sett1 = $query_main_sett1->fetchRow();
$wb_default_pages_folder = $wb_main_sett1['value'];
//Get page name from page_id
$query_pages = $database->query("SELECT * FROM `".TABLE_PREFIX."pages` WHERE page_id = '$page_id' ");
$this_page = $query_pages->fetchRow();
$self_link = WB_URL.$wb_default_pages_folder.$this_page['link'].$wb_default_page_extension;
// Now, for my purposes, I needed additional variable to be icluded in URL string
if(isset($_POST['com_id']) AND is_numeric($_POST['com_id']) ) {
$com_id = mysql_real_escape_string(strip_tags($_POST['com_id'])); } else { $com_id = '';}
// Prevent Hacking POST form
$caller = $_SERVER['HTTP_REFERER'];
$test = $self_link.'?'.$COMPANIES['FE_ACTION'].'='.$COMPANIES['FE_VIEW_COM'].'&'.$COMPANIES['FE_COM_NAME'].'='.$com_id;
if ($caller != $test) { $match = 'bad';} else { $match = 'OK';}
if (($com_id == '') OR ($page_id == '') OR ($match == 'bad')) {
die(header('Location: ../../index.php'));
}
In this example in my case:
<?php //color your live ;)
$test = http://127.0.0.1:4001/xo/me/companies.php?action=see-company&company=2
and this is the page from which _POST request is sent to another file, where above code is inserted to ensure that nobody can send you _POST request from remote host and alter your data..
So, consider this code while developing your addons.. :-D
All best,
Ivan
Hello,
wow, that's a very complicated method.
Maybe, a far more simpler method is to use the plain old captcha-method (without displaying a captcha, indeed).
File 1:
<?php
$ident = mt_rand();
$_SESSION['pagename_here_ident'] = $ident;
// display form
?>
<form method="post" action="...">
<input type="hidden" name="ident" value="<?php echo $ident; ?>">
...
File 2:
<?php
if(!isset($_POST['ident']) || !isset($_SESSION['pagename_here_ident']) || $_POST['ident']!=$_SESSION['pagename_here_ident']) {
// form faked
die(header("Location: ../../index.php"));
}
unset($_SESSION['pagename_here_ident']);
// rest here
thorn.
Hello!
Post is quite secure, but not very secure.
Better is using tokens for every form and link_hashes for every link.
I can't give you any code (because if I could I would have done it...), but the method is like:
Every upload, field, ... is a form. All forms have to "pass" a Control inside WebsiteBaker. I doesn't matter if such form is in frontend, backend, module or core.
Every form get's an individual token, e.g. "add_form_key('guestbook_bigtext');".Then the token gets validated via check_form_key('guestbook_bigtext');
So every post is controlled quite good.
Next one - link hashes. First every log-in in backend / frontend get's a link_hash, like "_http://www._that_your_wb_url/.....&hash=" . generate_link_hash("{$mode}_$match_id"))".
So the link to http://www.yourwb.xy/admin/index.php will look now like http://www.yourwb.xy/admin/index.php&hash=423423hchd8329rhqeuwaiweur
Ok, then we combine every token with it and reading the hash:
$token = request_var('hash', '');
check_link_hash($token, "{$mode}_$match_id")
So - every token from above first checks if the link-hash is correct. If it isn't, no form (guestbook, upload, whatever needs a _POST and more...) could be used.
It's of course a very big thing, and something WB has to handle (a module that does that is _absolutely_ useless), but it could be worth... If that would have been in WB, nobody could use the backup-exploit. Because it first would check the hash - it is quite hard I heard guessing a 20 digits token - about 10^32 : 1. :wink:
Yours Michael
Edit: Of course every hash needs to be controlled via cookie / AND destroyed after 30 minutes and that. It doesn't make sense using a hash for a week - people are easily sharing links with tokens (you know that e.g. from SMF here, that uses hashes in links).
Hello,
hm, that's far more complicated -- but is it more secure?
Quote from: Waldschwein on April 04, 2010, 01:31:09 PM
Every upload, field, ... is a form. All forms have to "pass" a Control inside WebsiteBaker. I doesn't matter if such form is in frontend, backend, module or core.
Every form get's an individual token, e.g. "add_form_key('guestbook_bigtext');".Then the token gets validated via check_form_key('guestbook_bigtext');
So every post is controlled quite good.
That's exactly what i wrote above (just replace
ident by
token) -- but it is more complicated by usage of functions/methods a user has to know.
Nevertheless, a mandatory and consistent method may be a good thing :-)
Quote
Next one - link hashes. First every log-in in backend / frontend get's a link_hash
For
logged-in users there is already a method to make links secure:
Usage of admin-class!
Quote
If that would have been in WB, nobody could use the backup-exploit
Nobody would have been able to use that exploit if the instantiating of the admin-class wasn't removed by accident before.
thorn.
Yes, you are right thorn,
Your code is much simplier and I like it.. In my code I just combined recent code for controling post form...
cheers