Welcome, Guest. Please login or register.
Did you miss your activation email?
May 26, 2012, 10:47:28 AM

Login with username, password and session length
Search:     Advanced search
Wollen Sie dem WebsiteBaker Team beitreten?
Nähere Informationen finden Sie unter hier und auf unserer neuen Webseite.
155538 Posts in 21715 Topics by 7737 Members
Latest Member: chris85
* Home Help Search Login Register
Pages: [1]   Go Down
Print
Author Topic: secure _POST requests  (Read 1453 times)
crnogorac081
AddOn Development
*
Offline Offline

Posts: 1706



« on: April 04, 2010, 10:05:25 AM »

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:

Code:
<?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:
Code:
<?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.. grin

All best,
Ivan
« Last Edit: April 06, 2010, 07:50:51 AM by mr-fan » Logged

Wow, I coded something myself: PM Messanger Modul ,Searchbox with suggestions
thorn

Offline Offline

Posts: 980


WWW
« Reply #1 on: April 04, 2010, 12:04:49 PM »

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:
Code:
<?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:
Code:
<?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.
Logged

Waldschwein
Guest
« Reply #2 on: April 04, 2010, 12:31:09 PM »

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).
« Last Edit: April 04, 2010, 12:36:11 PM by Waldschwein » Logged
thorn

Offline Offline

Posts: 980


WWW
« Reply #3 on: April 04, 2010, 02:08:19 PM »

Hello,

hm, that's far more complicated -- but is it more secure?

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 smiley

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.
Logged

crnogorac081
AddOn Development
*
Offline Offline

Posts: 1706



« Reply #4 on: April 04, 2010, 08:17:26 PM »

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
Logged

Wow, I coded something myself: PM Messanger Modul ,Searchbox with suggestions
Pages: [1]   Go Up
Print
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.16 | SMF © 2011, Simple Machines Valid XHTML 1.0! Valid CSS!