csrf-proofing for extensions

This commit is contained in:
Shish 2010-05-28 14:26:46 +01:00
parent 6cd53fed8a
commit 18403a3fa6
24 changed files with 99 additions and 93 deletions

View File

@ -52,7 +52,7 @@ class AdminPage implements Extension {
}
if(($event instanceof PageRequestEvent) && $event->page_matches("admin_utils")) {
if($user->is_admin()) {
if($user->is_admin() && $user->check_auth_token()) {
log_info("admin", "Util: {$_POST['action']}");
set_time_limit(0);
$redirect = false;

View File

@ -17,8 +17,11 @@ class AdminPageTheme extends Themelet {
* 'purge unused tags'
*/
public function display_form(Page $page) {
global $user;
$html = "
<p><form action='".make_link("admin_utils")."' method='POST'>
".$user->get_auth_html()."
<select name='action'>
<option value='lowercase all tags'>All tags to lowercase</option>
<option value='recount tag use'>Recount tag use</option>

View File

@ -58,13 +58,13 @@ class Blotter extends SimpleExtension {
}
}
public function onPageRequest(Event $event) {
global $page, $database, $user;
if($event->page_matches("blotter")) {
switch($event->get_arg(0)) {
case "editor":
/**
* Displays the blotter editor.
*/
global $page, $database, $user;
if(!$user->is_admin()) {
$this->theme->display_permission_denied($page);
} else {
@ -76,8 +76,7 @@ class Blotter extends SimpleExtension {
/**
* Adds an entry
*/
global $page, $database, $user;
if(!$user->is_admin()) {
if(!$user->is_admin() || !$user->check_auth_token()) {
$this->theme->display_permission_denied($page);
} else {
$entry_text = $_POST['entry_text'];
@ -95,8 +94,7 @@ class Blotter extends SimpleExtension {
/**
* Removes an entry
*/
global $page, $database, $user;
if(!$user->is_admin()) {
if(!$user->is_admin() || !$user->check_auth_token()) {
$this->theme->display_permission_denied($page);
} else {
$id = int_escape($_POST['id']);
@ -111,7 +109,6 @@ class Blotter extends SimpleExtension {
/**
* Displays all blotter entries
*/
global $database, $user;
$entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC");
$this->theme->display_blotter_page($entries);
break;

View File

@ -28,6 +28,8 @@ class BlotterTheme extends Themelet {
}
private function get_html_for_blotter_editor($entries) {
global $user;
/**
* Long function name, but at least I won't confuse it with something else ^_^
*/
@ -44,6 +46,7 @@ class BlotterTheme extends Themelet {
$add_new = "
<tr class='even'>
<form action='".make_link("blotter/add")."' method='POST'>
".$user->get_auth_html()."
<td colspan='2'><textarea style='text-align:left;' name='entry_text' rows='2' /></textarea></td>
<td><input type='checkbox' name='important' /></td>
<td><input type='submit' value='Add'></td>
@ -72,6 +75,7 @@ class BlotterTheme extends Themelet {
<td>$entry_text</td>
<td>$important</td>
<td><form name='remove$id' method='post' action='".make_link("blotter/remove")."'>
".$user->get_auth_html()."
<input type='hidden' name='id' value='$id' />
<input type='submit' style='width: 100%;' value='Remove' />
</form>

View File

@ -18,9 +18,8 @@ class BulkAdd extends SimpleExtension {
public function onPageRequest($event) {
global $page, $user;
if($event->page_matches("bulk_add")) {
if($user->is_admin() && isset($_POST['dir'])) {
if($user->is_admin() && $user->check_auth_token() && isset($_POST['dir'])) {
set_time_limit(0);
$this->add_dir($_POST['dir']);
$this->theme->display_upload_results($page);
}
@ -28,8 +27,7 @@ class BulkAdd extends SimpleExtension {
}
public function onAdminBuilding($event) {
global $page;
$this->theme->display_admin_block($page);
$this->theme->display_admin_block();
}

View File

@ -20,7 +20,8 @@ class BulkAddTheme extends Themelet {
* links to bulk_add with POST[dir] set to the name of a server-side
* directory full of images
*/
public function display_admin_block(Page $page) {
public function display_admin_block() {
global $page, $user;
$html = "
Add a folder full of images; any subfolders will have their names
used as tags for the images within.
@ -28,6 +29,7 @@ class BulkAddTheme extends Themelet {
upload via FTP or something first.
<p><form action='".make_link("bulk_add")."' method='POST'>
".$user->get_auth_html()."
Directory to add: <input type='text' name='dir' size='40'>
<input type='submit' value='Add'>
</form>

View File

@ -57,7 +57,7 @@ class Favorites extends SimpleExtension {
public function onPageRequest($event) {
global $page, $user;
if($event->page_matches("change_favorite") && !$user->is_anonymous()) {
if($event->page_matches("change_favorite") && !$user->is_anonymous() && $user->check_auth_token()) {
$image_id = int_escape($_POST['image_id']);
if((($_POST['favorite_action'] == "set") || ($_POST['favorite_action'] == "unset")) && ($image_id > 0)) {
send_event(new FavoriteSetEvent($image_id, $user, ($_POST['favorite_action'] == "set")));

View File

@ -5,22 +5,15 @@ class FavoritesTheme extends Themelet {
global $page, $user;
$i_image_id = int_escape($image->id);
if(!$is_favorited) {
$html = "<form action='".make_link("change_favorite")."' method='POST'>
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='favorite_action' value='set'>
<input type='submit' value='Favorite'>
</form>
";
}
else {
$html = "<form action='".make_link("change_favorite")."' method='POST'>
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='favorite_action' value='unset'>
<input type='submit' value='Un-Favorite'>
</form>
";
}
$name = $is_favorited ? "unset" : "set";
$label = $is_favorited ? "Un-Favorite" : "Favorite";
$html = "<form action='".make_link("change_favorite")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='favorite_action' value='$name'>
<input type='submit' value='$label'>
</form>
";
return $html;
}

View File

@ -27,7 +27,7 @@ class Featured extends SimpleExtension {
public function onPageRequest($event) {
global $config, $page, $user;
if($event->page_matches("featured_image")) {
if($event->get_arg(0) == "set") {
if($event->get_arg(0) == "set" && $user->check_auth_token()) {
if($user->is_admin() && isset($_POST['image_id'])) {
$id = int_escape($_POST['image_id']);
if($id > 0) {

View File

@ -9,8 +9,10 @@ class FeaturedTheme extends Themelet {
}
public function get_buttons_html($image_id) {
global $user;
return "
<form action='".make_link("featured_image/set")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='image_id' value='$image_id'>
<input type='submit' value='Feature This'>
</form>

View File

@ -51,7 +51,7 @@ class IPBan implements Extension {
if(($event instanceof PageRequestEvent) && $event->page_matches("ip_ban")) {
if($user->is_admin()) {
if($event->get_arg(0) == "add") {
if($event->get_arg(0) == "add" && $user->check_auth_token()) {
if(isset($_POST['ip']) && isset($_POST['reason']) && isset($_POST['end'])) {
if(empty($_POST['end'])) $end = null;
else $end = $_POST['end'];
@ -61,7 +61,7 @@ class IPBan implements Extension {
$page->set_redirect(make_link("ip_ban/list"));
}
}
else if($event->get_arg(0) == "remove") {
else if($event->get_arg(0) == "remove" && $user->check_auth_token()) {
if(isset($_POST['id'])) {
send_event(new RemoveIPBanEvent($_POST['id']));
$page->set_mode("redirect");

View File

@ -28,6 +28,7 @@ class IPBanTheme extends Themelet {
<td width='15%'>{$end_human}</td>
<td width='10%'>
<form action='".make_link("ip_ban/remove")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='id' value='{$ban[$prefix.'id']}'>
<input type='submit' value='Remove'>
</form>
@ -47,6 +48,7 @@ class IPBanTheme extends Themelet {
$h_bans
<tfoot><tr>
<form action='".make_link("ip_ban/add")."' method='POST'>
".$user->get_auth_html()."
<td><input type='text' name='ip'></td>
<td><input type='text' name='reason'></td>
<td>{$user->name}</td>

View File

@ -39,7 +39,7 @@ class NumericScore implements Extension {
}
}
if(($event instanceof PageRequestEvent) && $event->page_matches("numeric_score_vote")) {
if(($event instanceof PageRequestEvent) && $event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
if(!$user->is_anonymous()) {
$image_id = int_escape($_POST['image_id']);
$char = $_POST['vote'];

View File

@ -2,6 +2,7 @@
class NumericScoreTheme extends Themelet {
public function get_voter_html(Image $image) {
global $user;
$i_image_id = int_escape($image->id);
$i_score = int_escape($image->numeric_score);
@ -9,18 +10,21 @@ class NumericScoreTheme extends Themelet {
Current Score: $i_score
<p><form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='up'>
<input type='submit' value='Vote Up'>
</form>
<form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='null'>
<input type='submit' value='Remove Vote'>
</form>
<form action='".make_link("numeric_score_vote")."' method='POST'>
".$user->get_auth_html()."
<input type='hidden' name='image_id' value='$i_image_id'>
<input type='hidden' name='vote' value='down'>
<input type='submit' value='Vote Down'>

View File

@ -107,29 +107,30 @@ class PrivMsg extends SimpleExtension {
}
break;
case "delete":
$pm_id = int_escape($event->get_arg(1));
$pm = $database->get_row("SELECT * FROM private_message WHERE id = ?", array($pm_id));
if(is_null($pm)) {
$this->theme->display_error($page, "No such PM", "There is no PM #$pm_id");
}
else if(($pm["to_id"] == $user->id) || $user->is_admin()) {
$database->execute("DELETE FROM private_message WHERE id = ?", array($pm_id));
log_info("pm", "Deleted PM #$pm_id");
$page->set_mode("redirect");
$page->set_redirect($_SERVER["HTTP_REFERER"]);
}
else {
// permission denied
if($user->check_auth_token()) {
$pm_id = int_escape($_POST["pm_id"]);
$pm = $database->get_row("SELECT * FROM private_message WHERE id = ?", array($pm_id));
if(is_null($pm)) {
$this->theme->display_error($page, "No such PM", "There is no PM #$pm_id");
}
else if(($pm["to_id"] == $user->id) || $user->is_admin()) {
$database->execute("DELETE FROM private_message WHERE id = ?", array($pm_id));
log_info("pm", "Deleted PM #$pm_id");
$page->set_mode("redirect");
$page->set_redirect($_SERVER["HTTP_REFERER"]);
}
}
break;
case "send":
$to_id = int_escape($_POST["to_id"]);
$from_id = $user->id;
$subject = $_POST["subject"];
$message = $_POST["message"];
send_event(new SendPMEvent(new PM($from_id, $_SERVER["REMOTE_ADDR"], $to_id, $subject, $message)));
$page->set_mode("redirect");
$page->set_redirect($_SERVER["HTTP_REFERER"]);
if($user->check_auth_token()) {
$to_id = int_escape($_POST["to_id"]);
$from_id = $user->id;
$subject = $_POST["subject"];
$message = $_POST["message"];
send_event(new SendPMEvent(new PM($from_id, $_SERVER["REMOTE_ADDR"], $to_id, $subject, $message)));
$page->set_mode("redirect");
$page->set_redirect($_SERVER["HTTP_REFERER"]);
}
break;
default:
$this->theme->display_error($page, "Invalid action", "That's not something you can do with a PM");

View File

@ -2,6 +2,8 @@
class PrivMsgTheme extends Themelet {
public function display_pms(Page $page, $pms) {
global $user;
$html = "
<script>
$(document).ready(function() {
@ -20,13 +22,14 @@ class PrivMsgTheme extends Themelet {
$h_from = html_escape($from_name);
$from_url = make_link("user/".url_escape($from_name));
$pm_url = make_link("pm/read/".$pm->id);
$del_url = make_link("pm/delete/".$pm->id);
$del_url = make_link("pm/delete");
$h_date = html_escape($pm->sent_date);
if($pm->is_read) $h_subject = "<b>$h_subject</b>";
$html .= "<tr class='$oe'><td><a href='$pm_url'>$h_subject</a></td>
<td><a href='$from_url'>$h_from</a></td><td>$h_date</td>
<td><form action='$del_url'>
<input type='hidden' name='q' value='/pm/delete/{$pm->id}'>
<td><form action='$del_url' method='POST'>
<input type='hidden' name='pm_id' value='{$pm->id}'>
".$user->get_auth_html()."
<input type='submit' value='Delete'>
</form></td></tr>";
}
@ -41,8 +44,10 @@ class PrivMsgTheme extends Themelet {
$post_url = make_link("pm/send");
$h_subject = html_escape($subject);
$to_id = $to->id;
$auth = $user->get_auth_html();
$html = <<<EOD
<form action="$post_url" method="POST">
$auth
<input type="hidden" name="to_id" value="$to_id">
<table style="width: 400px;">
<tr><td>Subject:</td><td><input type="text" name="subject" value="$h_subject"></td></tr>

View File

@ -36,52 +36,33 @@ class Tips extends SimpleExtension {
$this->getTip();
if($event->page_matches("tips")) {
if($event->page_matches("tips") && $user->is_admin()) {
switch($event->get_arg(0)) {
case "list":
{
if($user->is_admin()) {
$this->manageTips();
$this->getAll();
}
$this->manageTips();
$this->getAll();
break;
}
case "new":
{
break;
}
case "save":
{
if($user->is_admin()) {
if($user->check_auth_token()) {
$this->saveTip();
$page->set_mode("redirect");
$page->set_redirect(make_link("tips/list"));
}
break;
}
case "status":
{
if($user->is_admin()) {
$tipID = int_escape($event->get_arg(1));
$this->setStatus($tipID);
$page->set_mode("redirect");
$page->set_redirect(make_link("tips/list"));
}
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$this->setStatus($tipID);
$page->set_mode("redirect");
$page->set_redirect(make_link("tips/list"));
break;
}
case "delete":
{
if($user->is_admin()) {
$tipID = int_escape($event->get_arg(1));
$this->deleteTip($tipID);
$page->set_mode("redirect");
$page->set_redirect(make_link("tips/list"));
}
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$this->deleteTip($tipID);
$page->set_mode("redirect");
$page->set_redirect(make_link("tips/list"));
break;
}
}
}
}

View File

@ -1,7 +1,7 @@
<?php
class TipsTheme extends Themelet {
public function manageTips($url, $images) {
global $page;
global $page, $user;
$select = "<select name='image'><option value=''>- Select Image -</option>";
foreach($images as $image){
@ -12,6 +12,7 @@ class TipsTheme extends Themelet {
$html = "
<form action='".make_link("tips/save")."' method='POST'>
".$user->get_auth_html()."
<table>
<tr>
<td>Enable:</td>

View File

@ -91,7 +91,7 @@ class ExtManager extends SimpleExtension {
global $page, $user;
if($event->page_matches("ext_manager")) {
if($user->is_admin()) {
if($event->get_arg(0) == "set") {
if($event->get_arg(0) == "set" && $user->check_auth_token()) {
if(is_writable("ext")) {
$this->set_things($_POST);
$page->set_mode("redirect");

View File

@ -2,9 +2,11 @@
class ExtManagerTheme extends Themelet {
public function display_table(Page $page, $extensions, $editable) {
global $user;
$en = $editable ? "<th>Enabled</th>" : "";
$html = "
<form action='".make_link("ext_manager/set")."' method='POST'>
".$user->get_auth_html()."
<script>
$(document).ready(function() {
$(\"#extensions\").tablesorter();
@ -53,6 +55,7 @@ class ExtManagerTheme extends Themelet {
/*
public function display_blocks(Page $page, $extensions) {
global $user;
$n = 0;
$col_1 = "";
$col_2 = "";
@ -94,6 +97,7 @@ class ExtManagerTheme extends Themelet {
}
$html = "
<form action='".make_link("ext_manager/set")."' method='POST'>
".$user->get_auth_html()."
<table border='0'>
<tr><td width='50%'>$col_1</td><td>$col_2</td></tr>
<tr><td colspan='2'><input type='submit' value='Set Extensions'></td></tr>

View File

@ -119,7 +119,7 @@ class ImageIO extends SimpleExtension {
}
if($event->page_matches("image_admin/delete")) {
global $page, $user;
if($user->is_admin() && isset($_POST['image_id'])) {
if($user->is_admin() && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']);
if($image) {
send_event(new ImageDeletionEvent($image));

View File

@ -6,10 +6,13 @@ class ImageIOTheme {
* $image_id = the image to delete
*/
public function get_deleter_html($image_id) {
global $user;
$i_image_id = int_escape($image_id);
$html = "
<form action='".make_link("image_admin/delete")."' method='POST'>
<input type='hidden' name='image_id' value='$i_image_id'>
".$user->get_auth_html()."
<input type='submit' value='Delete'>
</form>
";

View File

@ -188,7 +188,7 @@ class Setup extends SimpleExtension {
$this->theme->display_permission_denied($page);
}
else {
if($event->get_arg(0) == "save") {
if($event->get_arg(0) == "save" && $user->check_auth_token()) {
send_event(new ConfigSaveEvent($config));
$config->save();

View File

@ -13,6 +13,8 @@ class SetupTheme extends Themelet {
* The page should wrap all the options in a form which links to setup_save
*/
public function display_page(Page $page, SetupPanel $panel) {
global $user;
$setupblock_html1 = "";
$setupblock_html2 = "";
@ -41,6 +43,7 @@ class SetupTheme extends Themelet {
$table = "
<form action='".make_link("setup/save")."' method='POST'><table>
".$user->get_auth_html()."
<tr><td>$setupblock_html1</td><td>$setupblock_html2</td></tr>
<tr><td colspan='2'><input type='submit' value='Save Settings'></td></tr>
</table></form>
@ -53,6 +56,8 @@ class SetupTheme extends Themelet {
}
public function display_advanced(Page $page, $options) {
global $user;
$rows = "";
$n = 0;
ksort($options);
@ -79,6 +84,7 @@ class SetupTheme extends Themelet {
});
</script>
<form action='".make_link("setup/save")."' method='POST'><table id='settings' class='zebra'>
".$user->get_auth_html()."
<thead><tr><th width='25%'>Name</th><th>Value</th></tr></thead>
<tbody>$rows</tbody>
<tfoot><tr><td colspan='2'><input type='submit' value='Save Settings'></td></tr></tfoot>