From 453b5b46a370e3f01f2c948ac3eddf0bcd82c741 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tobias=20H=C3=B6=C3=9Fl?= <tobias@hoessl.eu>
Date: Sun, 18 Mar 2012 15:44:33 +0000
Subject: [PATCH] CSRF-Protection in the group-related form (creating, renaming
 and dropping a group, adding/removing members from it)

---
 include/security.php |  6 ++++++
 js/main.js           |  4 ++--
 mod/group.php        | 26 +++++++++++++++++++-------
 view/group_drop.tpl  |  2 +-
 view/group_edit.tpl  |  1 +
 5 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/include/security.php b/include/security.php
index 6ea515bff..45473445a 100755
--- a/include/security.php
+++ b/include/security.php
@@ -334,3 +334,9 @@ function check_form_security_token_redirectOnErr($err_redirect, $typename = "",
 		goaway($a->get_baseurl() . $err_redirect );
 	}
 }
+function check_form_security_token_ForbiddenOnErr($typename = "", $formname = 'form_security_token') {
+	if (!check_form_security_token($typename, $formname)) {
+		header('HTTP/1.1 403 Forbidden');
+		killme();
+	}
+}
\ No newline at end of file
diff --git a/js/main.js b/js/main.js
index c20455ad1..babd2a1c3 100755
--- a/js/main.js
+++ b/js/main.js
@@ -486,9 +486,9 @@
         return a.join('');  
     }  
 
-	function groupChangeMember(gid,cid) {
+	function groupChangeMember(gid, cid, sec_token) {
 		$('body .fakelink').css('cursor', 'wait');
-		$.get('group/' + gid + '/' + cid, function(data) {
+		$.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
 				$('#group-update-wrapper').html(data);
 				$('body .fakelink').css('cursor', 'auto');				
 		});
diff --git a/mod/group.php b/mod/group.php
index 13401ef0d..a282dbccf 100755
--- a/mod/group.php
+++ b/mod/group.php
@@ -21,6 +21,8 @@ function group_post(&$a) {
 	}
 
 	if(($a->argc == 2) && ($a->argv[1] === 'new')) {
+		check_form_security_token_redirectOnErr('/group/new', 'group_edit');
+		
 		$name = notags(trim($_POST['groupname']));
 		$r = group_add(local_user(),$name);
 		if($r) {
@@ -35,6 +37,8 @@ function group_post(&$a) {
 		return; // NOTREACHED
 	}
 	if(($a->argc == 2) && (intval($a->argv[1]))) {
+		check_form_security_token_redirectOnErr('/group', 'group_edit');
+		
 		$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
 			intval($a->argv[1]),
 			intval(local_user())
@@ -62,7 +66,8 @@ function group_post(&$a) {
 }
 
 function group_content(&$a) {
-
+	$change = false;
+	
 	if(! local_user()) {
 		notice( t('Permission denied') . EOL);
 		return;
@@ -83,14 +88,17 @@ function group_content(&$a) {
 		
 		return replace_macros($tpl, $context + array(
 			'$title' => t('Create a group of contacts/friends.'),
-			'$gname' => array('groupname',t('Group Name: '),$group['name'], ''),
+			'$gname' => array('groupname',t('Group Name: '), '', ''),
 			'$gid' => 'new',
+			'$form_security_token' => get_form_security_token("group_edit"),
 		));
 
 
 	}
 
 	if(($a->argc == 3) && ($a->argv[1] === 'drop')) {
+		check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
+		
 		if(intval($a->argv[2])) {
 			$r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
 				intval($a->argv[2]),
@@ -108,6 +116,8 @@ function group_content(&$a) {
 	}
 
 	if(($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) {
+		check_form_security_token_ForbiddenOnErr('group_member_change', 't');
+		
 		$r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1",
 			intval($a->argv[2]),
 			intval(local_user())
@@ -155,7 +165,8 @@ function group_content(&$a) {
 		$drop_tpl = get_markup_template('group_drop.tpl');
 		$drop_txt = replace_macros($drop_tpl, array(
 			'$id' => $group['id'],
-			'$delete' => t('Delete')
+			'$delete' => t('Delete'),
+			'$form_security_token' => get_form_security_token("group_drop"),
 		));
 
 		$celeb = ((($a->user['page-flags'] == PAGE_SOAPBOX) || ($a->user['page-flags'] == PAGE_COMMUNITY)) ? true : false);
@@ -166,6 +177,7 @@ function group_content(&$a) {
 			'$gname' => array('groupname',t('Group Name: '),$group['name'], ''),
 			'$gid' => $group['id'],
 			'$drop' => $drop_txt,
+			'$form_security_token' => get_form_security_token('group_edit'),
 		);
 
 	}
@@ -177,14 +189,14 @@ function group_content(&$a) {
 		'label_members' => t('Members'),
 		'members' => array(),
 		'label_contacts' => t('All Contacts'),
-		'contacts' => arraY(),
+		'contacts' => array(),
 	);
 		
-
+	$sec_token = addslashes(get_form_security_token('group_member_change'));
 	$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
 	foreach($members as $member) {
 		if($member['url']) {
-			$member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . '); return true;';
+			$member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . ',\'' . $sec_token . '\'); return true;';
 			$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
 		}
 		else
@@ -199,7 +211,7 @@ function group_content(&$a) {
 		$textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
 		foreach($r as $member) {
 			if(! in_array($member['id'],$preselected)) {
-				$member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . '); return true;';
+				$member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . ',\'' . $sec_token . '\'); return true;';
 				$groupeditor['contacts'][] = micropro($member,true,'mpall', $textmode);
 			}
 		}
diff --git a/view/group_drop.tpl b/view/group_drop.tpl
index cbae1610f..2cbebbb8e 100755
--- a/view/group_drop.tpl
+++ b/view/group_drop.tpl
@@ -1,5 +1,5 @@
 <div class="group-delete-wrapper button" id="group-delete-wrapper-$id" >
-	<a href="group/drop/$id" 
+	<a href="group/drop/$id?t=$form_security_token" 
 		onclick="return confirmDelete();" 
 		id="group-delete-icon-$id" 
 		class="icon drophide group-delete-icon" 
diff --git a/view/group_edit.tpl b/view/group_edit.tpl
index 3689db753..2fa2b1a55 100755
--- a/view/group_edit.tpl
+++ b/view/group_edit.tpl
@@ -3,6 +3,7 @@
 
 <div id="group-edit-wrapper" >
 	<form action="group/$gid" id="group-edit-form" method="post" >
+		<input type='hidden' name='form_security_token' value='$form_security_token'>
 		
 		{{ inc field_input.tpl with $field=$gname }}{{ endinc }}
 		{{ if $drop }}$drop{{ endif }}