Go Back   vb.org Archive > vBulletin Article Depository > Read An Article > Programming Articles
FAQ Community Calendar Today's Posts Search

Reply
 
Thread Tools
Implementing CSRF Protection in modifications
Marco van Herwaarden
Join Date: Jul 2004
Posts: 25,415

 

Show Printable Version Email this Page Subscription
Marco van Herwaarden Marco van Herwaarden is offline 04-23-2008, 10:00 PM

With the new version released today for vBulletin 3.6.10 and 3.7.0 RC4, a new protection against Cross Site Request Forgery (CSRF) has been introduced. This new protection might influence the coding in modifications.

Scott MacVicar took the time to compile a short explanation on this new protection for the coders on vBulletin.org:

Changes for CSRF protection with third party modifications

Cross Site Request Forgery (CSRF) involves taking advantage of the stateless nature of HTTP, there are no ways to ensure the exact origin of a request, its also not possible to detect what was actually initiated by a user and what was forced by a third party script. A token was added to the latest version of each of the vBulletin products, with the release of 3.6.10 and 3.7.0 RC4 it is no longer possible to submit a POST request directly without passing in the known token.

The addition of a security token for each POST request removes the ability for a remote page to force a user to submit an action. At the moment this protection will only apply to vBulletin files and third party files will need to opt into this protection and add the appropriate hidden field. This was done to preserve backwards compatibility.

Adding Protection to your own files

To opt your entire file into CSRF protection the following should be added to the top of the file under the define for THIS_SCRIPT.

PHP Code:
define('CSRF_PROTECTION'true); 
With this change all POST requests to this file will check for the presence of the securitytoken field and compare it to the value for the user, if its wrong an error message will be shown and execution with halt.

If this value is set to false then all CSRF protection is removed for the file, this is appropriate for something that intentionally accepts remote POST requests.

You should always add this to your file, even if you don't think the script is ever going to receive POST requests.

An absence of this defined constant within your files will result in the old style referrer checking being performed.

Template Changes

The following should be added to all of the forms which POST back to vBulletin or a vBulletin script. This will automatically be filled out with a 40 character hash that is unique to the user.

Code:
<input type="hidden" name="securitytoken" value="$bbuserinfo[securitytoken]" />
Again it is worthwhile adding this to your templates even if it is currently not using the CSRF protection.

Exempting Certain Actions

It may be appropriate to exempt a particular action from the CSRF protection, in this case you can add the following to the file.

PHP Code:
define('CSRF_SKIP_LIST''action_one,action_two'); 
The above example would exempt both example.php?do=action_one and example.php?do=action_two from the CSRF protection, if the CSRF_SKIP_LIST constant is defined with no value then it will exempt the default action.

If the skip list needs to be changed at runtime is it available within the registry object, using the init_startup hook the following code would be used to exempt 'example.php?do=action_three'.

PHP Code:
if (THIS_SCRIPT == 'example')
{
        
$vbulletin->csrf_skip_list[] = 'action_three';

Reply With Quote
  #62  
Old 05-05-2008, 08:17 PM
PaulSonny PaulSonny is offline
 
Join Date: Dec 2006
Location: Middlesbrough, UK
Posts: 433
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Can anyone help me with this problem,

Details of the reported exploit are as follows;

Multiple CSRF Vulnerabilities
=============================

Example
------------------
if ($_REQUEST['do'] == 'deletereply'){
------------------

Because the "delete" command can be executed via a GET request (ie. URL in a signature), if a user with permission clicks a link that is specifically crafted, it can delete something. CSRF.

This is in my HelpCenter modification. I thought I had covered all CSRF issues but its seems I may have missed something but I dont know how to correct as ive covered everything from this thread.

Thanks, Paul.
Reply With Quote
  #63  
Old 05-06-2008, 09:34 AM
Milad's Avatar
Milad Milad is offline
 
Join Date: Apr 2005
Location: Syro
Posts: 663
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by PaulSonny View Post
Can anyone help me with this problem,

Details of the reported exploit are as follows;

Multiple CSRF Vulnerabilities
=============================

Example
------------------
if ($_REQUEST['do'] == 'deletereply'){
------------------

Because the "delete" command can be executed via a GET request (ie. URL in a signature), if a user with permission clicks a link that is specifically crafted, it can delete something. CSRF.

This is in my HelpCenter modification. I thought I had covered all CSRF issues but its seems I may have missed something but I dont know how to correct as ive covered everything from this thread.

Thanks, Paul.
make it via post request and use the security token!
Reply With Quote
  #64  
Old 05-06-2008, 03:32 PM
dancue dancue is offline
 
Join Date: Feb 2008
Posts: 569
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

I'm trying to add the security token to a mod that is giving me an error message. The mod is very important and I'm not getting any answers from the author.

The mod uses AJAX, which is what is not working. When someone uses quickreply and posts their reply it's supposed to automatically reveal the hidden content. Instead it gives the security token issue.

Here are the templates. Must there be a change to the xml file also?

Code:
				<!--hide-addon-->
		<if condition="$vboptions[disable_ajax] != 2">
			<script type="text/javascript"><!--
			var hpostid = 0;
			var hmax = 0;
			function findposts(obj,call){
				ruf = call;
				var laenge = obj.innerHTML.length;
				if (hmax == '0'){
					hmax = laenge;
				} else if (hmax < laenge){
					hmax = laenge;
					Rufen(ruf);
				}
			}
			var hide_aktiv = null;
			var unhide = null;
			var zahl = 0;
			var old;
			var postid
			function Rufen(posting){
				if (window.XMLHttpRequest) {
					unhide = new XMLHttpRequest();
				} else if (window.ActiveXObject) {
					unhide = new ActiveXObject("Microsoft.XMLHTTP");
				}
				old = posting
				var postids = posting.split(",");
				if ( zahl < postids.length){
					postid = postids[zahl];
					unhide.open("POST", "showthread.php", true);
					unhide.onreadystatechange = ausgeben;
					unhide.setRequestHeader(
						"Content-Type",
						"application/x-www-form-urlencoded");
					unhide.send("do=whatever&p="+postid+"&all="+old);
				} else zahl = 0;
			}

			function ausgeben() {
				if (unhide.readyState == 4) {
					if (unhide.responseText != 'sid_hide_still_active'){
						document.getElementById("post_message_"+postid).innerHTML =
							unhide.responseText;
						zahl++;
						Rufen(old);
					} else {
						zahl++;
						Rufen(old);
					}
				} 
				else setTimeout('ausgeben()', 200);
			}
			//-->
			</script>
		</if>
Code:
		<if condition="$vboptions[disable_ajax] != 2 AND $vboptions[sid_hide_ajax_on] == 1">
		<script type="text/javascript">
			if (hide_aktiv) window.clearInterval(hide_aktiv);
			var hide_aktiv = window.setInterval("findposts(fetch_object('posts'),'$hide_call')", 3000);
		</script>
		</if>
		<div id="hide_fieldset"><fieldset>
			<legend><span class="highlight">$vbphrase[sid_hide_post_hide]</span></legend>
			$hide_img
		</fieldset></div>
I understand it's the author's duty to solve the issue, but the author seems to have abandoned the mod.

I am not asking for the solution, but guidance.
Reply With Quote
  #65  
Old 05-07-2008, 06:30 PM
ikki29 ikki29 is offline
 
Join Date: Aug 2007
Posts: 19
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by dancue View Post
I'm trying to add the security token to a mod that is giving me an error message. The mod is very important and I'm not getting any answers from the author.

The mod uses AJAX, which is what is not working. When someone uses quickreply and posts their reply it's supposed to automatically reveal the hidden content. Instead it gives the security token issue.

Here are the templates. Must there be a change to the xml file also?

Code:
				<!--hide-addon-->
		<if condition="$vboptions[disable_ajax] != 2">
			<script type="text/javascript"><!--
			var hpostid = 0;
			var hmax = 0;
			function findposts(obj,call){
				ruf = call;
				var laenge = obj.innerHTML.length;
				if (hmax == '0'){
					hmax = laenge;
				} else if (hmax < laenge){
					hmax = laenge;
					Rufen(ruf);
				}
			}
			var hide_aktiv = null;
			var unhide = null;
			var zahl = 0;
			var old;
			var postid
			function Rufen(posting){
				if (window.XMLHttpRequest) {
					unhide = new XMLHttpRequest();
				} else if (window.ActiveXObject) {
					unhide = new ActiveXObject("Microsoft.XMLHTTP");
				}
				old = posting
				var postids = posting.split(",");
				if ( zahl < postids.length){
					postid = postids[zahl];
					unhide.open("POST", "showthread.php", true);
					unhide.onreadystatechange = ausgeben;
					unhide.setRequestHeader(
						"Content-Type",
						"application/x-www-form-urlencoded");
					unhide.send("do=whatever&p="+postid+"&all="+old);
				} else zahl = 0;
			}

			function ausgeben() {
				if (unhide.readyState == 4) {
					if (unhide.responseText != 'sid_hide_still_active'){
						document.getElementById("post_message_"+postid).innerHTML =
							unhide.responseText;
						zahl++;
						Rufen(old);
					} else {
						zahl++;
						Rufen(old);
					}
				} 
				else setTimeout('ausgeben()', 200);
			}
			//-->
			</script>
		</if>
Code:
		<if condition="$vboptions[disable_ajax] != 2 AND $vboptions[sid_hide_ajax_on] == 1">
		<script type="text/javascript">
			if (hide_aktiv) window.clearInterval(hide_aktiv);
			var hide_aktiv = window.setInterval("findposts(fetch_object('posts'),'$hide_call')", 3000);
		</script>
		</if>
		<div id="hide_fieldset"><fieldset>
			<legend><span class="highlight">$vbphrase[sid_hide_post_hide]</span></legend>
			$hide_img
		</fieldset></div>
I understand it's the author's duty to solve the issue, but the author seems to have abandoned the mod.

I am not asking for the solution, but guidance.


I agree completely with the companion, I use this modification and tb I have these problems, it is a product very used in the forum and I cannot allow me the luxury of removing it, ask them please that they should help us in this topic, graces(thanks) Pd: since always I ask for excuses for my English one, for which I use one I translate of Spanish to groins, sie
Reply With Quote
  #66  
Old 05-07-2008, 06:45 PM
scan-pa scan-pa is offline
 
Join Date: May 2006
Location: Lebanon Co. Pa. USA
Posts: 189
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Yes BIG Thank You to every one who got this needed info to us. This fixed all my mods that went down after the move to vB 3.7.0 Gold.........................

Now the mods I have been running for over 2.5 years are all back online...
Reply With Quote
  #67  
Old 05-08-2008, 04:45 PM
dancue dancue is offline
 
Join Date: Feb 2008
Posts: 569
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Dismounted View Post
Also, you need to add the security token to AJAX requests using POST. This can be simply added using the variable "SECURITYTOKEN". An example is below.
Code:
YAHOO.util.Connect.asyncRequest('POST', scriptpath + '?do=ajax', {
	success: this.handle_ajax_response,
	failure: this.handle_ajax_error,
	timeout: vB_Default_Timeout,
	scope: this
}, SESSIONURL + 'securitytoken=' + SECURITYTOKEN + '&foo=' + foo);
Could someone please explain this further?

What did this look like before the edit? What are you editing? Is it a template, a plug-in?
Reply With Quote
  #68  
Old 05-08-2008, 11:37 PM
juan71287 juan71287 is offline
 
Join Date: Dec 2003
Location: New York
Posts: 194
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Hi guys, I don't really understand this, what I want to do is make it so this does not show anymore.



Please help me take that off. Thanks.
Reply With Quote
  #69  
Old 05-09-2008, 09:00 AM
Flep Flep is offline
 
Join Date: Jul 2007
Location: Cesenatico
Posts: 61
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

wow ! This is a precious thread !

thank you
Reply With Quote
  #70  
Old 05-09-2008, 01:30 PM
dssart dssart is offline
 
Join Date: May 2002
Posts: 70
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Greetings all,

Well, you guys are my last hope. I had a mod written for me last year, my forum members love it and at the moment it's running but when I upgrade I don't expect it to survive..so I'm trying to get a handle on this so that I can do it myself. The coder has long since disappeared so help is appreciated.

The beginning of this thread says that:

"To opt your entire file into CSRF protection the following should be added to the top of the file under the define for THIS_SCRIPT."

I have this line at the beginning of my mods .php file:

define('THIS_SCRIPT', 'dataawards_awards');

Do I add this:

define('CSRF_PROTECTION', true);

Directly below that line? will that solve the entire security token issue or do I need to hunt for form/posts? Talking about form/posts...is this one?:

$awarddisplay.= '<form action="' . htmlentities($_SERVER['PHP_SELF']) . '?addawards=' . $_REQUEST['addawards'] . '&amp;type=' . $type . '" method="POST">';

If I understand this correctly I need to find all form/posts (since you are posting and not requesting, thus the need for the security token):

<input type="hidden" name="securitytoken" value="$bbuserinfo[securitytoken]" />


Thanks, I hope I can work through this on my own, but if anyone wants to make some money, I'd rather pay to have it done..PM if interested.
Reply With Quote
  #71  
Old 05-10-2008, 07:22 PM
Behzad Varedi Behzad Varedi is offline
 
Join Date: Nov 2007
Location: Iran, Mashhad
Posts: 32
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Wayne Luke View Post
Forms are not equal to templates but some templates have forms in them.

A form is anywhere your users can submit data. If you have modifications that submit data and cannot update their templates then you need to post for support in the modification thread.

It isn't hard to find out where this needs to go.

In your Admin CP under Styles & Template select Search In Templates...

Search for: value="$session[sessionhash]"


In every template this occurs in add this line directly after the line containing the above, if it doesn't exist already:
<input type="hidden" name="securitytoken" value="$bbuserinfo[securitytoken]" />

Save the template.
Thanks alot,

I do what you said and my problem is solved now...
thanks again
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 01:04 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.08823 seconds
  • Memory Usage 2,358KB
  • Queries Executed 26 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (6)bbcode_code
  • (3)bbcode_php
  • (4)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_article
  • (1)navbar
  • (4)navbar_link
  • (120)option
  • (1)pagenav
  • (1)pagenav_curpage
  • (4)pagenav_pagelink
  • (1)pagenav_pagelinkrel
  • (11)post_thanks_box
  • (1)post_thanks_box_bit
  • (11)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (1)post_thanks_postbit
  • (11)post_thanks_postbit_info
  • (10)postbit
  • (11)postbit_onlinestatus
  • (11)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • fetch_musername
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • post_thanks_function_fetch_thanks_bit_start
  • post_thanks_function_show_thanks_date_start
  • post_thanks_function_show_thanks_date_end
  • post_thanks_function_fetch_thanks_bit_end
  • post_thanks_function_fetch_post_thanks_template_start
  • post_thanks_function_fetch_post_thanks_template_end
  • postbit_imicons
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • pagenav_page
  • pagenav_complete
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete