secure _POST requests

crnogorac081

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
Web developer

thorn

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.
[url=http://nettest.thekk.de/doku.php]Projekte[/url]

Waldschwein

#3
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).

thorn

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.
[url=http://nettest.thekk.de/doku.php]Projekte[/url]

crnogorac081

#1
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
Web developer