Motivation
To guard against exploits,
HTML tags and
HTML entities need to be escaped in the user registration, as well when updating TWiki user topics.
Credit to Jesper den Boer for reporting this issue to Peter Thoeny via LinkedIn message.
Severity Level
The TWiki
SecurityTeam triaged this issue as documented in
TWikiSecurityAlertProcess and assigned the following severity level:
- Severity 3 issue: TWiki content or browser is compromised.
Description and Documentation
HTML tags and
HTML entities are escaped when handling the TWiki registration, and also when saving a TWiki user form in the Main web.
This will be fix in upcoming TWiki-6.1.1 patch release. See also hotfix below.
Tracked in
TWikibug:Item7939
Hotfix for TWiki Production Release
Apply patch
TWiki-6.1.0-reg-html.patch file -- see
HowToApplyPatch.
Alternatively, manually fix the following files based on patch -- see also
HowToApplyPatch:
Patch lib/TWiki/Form.pm
--- TWiki-6.1.0/lib/TWiki/Form.pm 2018-07-15 20:10:08.000000000 -0700
+++ TWiki-6.1.0-patch/lib/TWiki/Form.pm 2023-07-02 16:32:04.425485263 -0700
@@ -1,6 +1,6 @@
# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
#
-# Copyright (C) 2001-2018 Peter Thoeny, peter[at]thoeny.org
+# Copyright (C) 2001-2023 Peter Thoeny, peter09[at]thoeny.org
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
@@ -548,7 +548,7 @@
=cut
sub getFieldValuesFromQuery {
- my( $this, $query, $meta ) = @_;
+ my( $this, $query, $meta, $escapeHtml ) = @_;
ASSERT($meta->isa( 'TWiki::Meta')) if DEBUG;
my @missing;
my $seen = 0;
@@ -559,7 +559,7 @@
my @old = $meta->find( 'FIELD' );
$meta->remove('FIELD');
foreach my $fieldDef ( @{$this->{fields}} ) {
- my( $set, $present ) = $fieldDef->populateMetaFromQueryData( $query, $meta, \@old );
+ my( $set, $present ) = $fieldDef->populateMetaFromQueryData( $query, $meta, \@old, $escapeHtml );
if( $present ) {
$seen++;
}
Patch lib/TWiki/Form/FieldDefinition.pm
--- TWiki-6.1.0/lib/TWiki/Form/FieldDefinition.pm 2018-07-15 20:10:08.000000000 -0700
+++ TWiki-6.1.0-patch/lib/TWiki/Form/FieldDefinition.pm 2023-07-02 16:58:26.147719201 -0700
@@ -1,6 +1,6 @@
# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
#
-# Copyright (C) 2001-2018 Peter Thoeny, peter[at]thoeny.org
+# Copyright (C) 2001-2023 Peter Thoeny, peter09[at]thoeny.org
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
@@ -241,7 +241,7 @@
=cut
sub populateMetaFromQueryData {
- my( $this, $query, $meta, $old ) = @_;
+ my( $this, $query, $meta, $old, $escapeHtml ) = @_;
my $value;
my $bPresent = 0;
@@ -296,6 +296,9 @@
if( $this->isMandatory() && length( $value ) == 0) {
return (0, $bPresent);
}
+ if( $escapeHtml ) {
+ $value = _escapeHtml( $value );
+ }
# NOTE: title and name are stored in the topic so that it can be
# viewed without reading in the form definition
my $title = $this->{title};
@@ -386,4 +389,13 @@
return join( ' ', @ss );
}
+# Item7939: escape HTML (guard against XSS vulnerability)
+sub _escapeHtml {
+ my $text = shift;
+ $text =~ s/&/&/go; # escape entities
+ $text =~ s/</</go; # escape HTML
+ $text =~ s/>/>/go; # escape HTML
+ return $text;
+}
+
1;
Patch lib/TWiki/UI/Save.pm
--- TWiki-6.1.0/lib/TWiki/UI/Save.pm 2018-07-15 20:10:08.000000000 -0700
+++ TWiki-6.1.0-patch/lib/TWiki/UI/Save.pm 2023-07-02 16:57:53.773326405 -0700
@@ -1,6 +1,6 @@
# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
#
-# Copyright (C) 1999-2018 Peter Thoeny, peter[at]thoeny.org
+# Copyright (C) 1999-2023 Peter Thoeny, peter09[at]thoeny.org
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
@@ -53,7 +53,7 @@
my $revision = $query->param( 'rev' ) || undef;
my $reqmethod = $query->request_method();
- if( $reqmethod && $reqmethod !~ /^POST$/i ) {
+ if( $reqmethod && $reqmethod !~ /^POST$/i && !$session->inContext('command_line') ) {
# save can only be called via POST method or command line
throw TWiki::OopsException(
'attention',
@@ -298,8 +298,17 @@
}
if( $formDef ) {
# override with values from the query
+ my $escapeHtml = 0;
+ my $form = $newMeta->get( 'FORM' );
+ if( $form ) {
+ # Item7939: escape HTML in user form (guard against XSS vulnerability)
+ # TODO: make configurable
+ if( $webName eq $TWiki::cfg{UsersWebName} && $form->{name} =~ /User/ ) {
+ $escapeHtml = 1;
+ }
+ }
my( $seen, $missing ) =
- $formDef->getFieldValuesFromQuery( $query, $newMeta );
+ $formDef->getFieldValuesFromQuery( $query, $newMeta, $escapeHtml );
if( $seen && @$missing ) {
# chuck up if there is at least one field value defined in the
# query and a mandatory field was not defined in the
Patch lib/TWiki/UI/Register.pm
--- TWiki-6.1.0/lib/TWiki/UI/Register.pm 2018-07-15 20:10:08.000000000 -0700
+++ TWiki-6.1.0-patch/lib/TWiki/UI/Register.pm 2023-07-02 15:15:20.188213505 -0700
@@ -1,6 +1,6 @@
# Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
#
-# Copyright (C) 1999-2018 Peter Thoeny, peter[at]thoeny.org
+# Copyright (C) 1999-2023 Peter Thoeny, peter09[at]thoeny.org
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
@@ -965,7 +965,8 @@
next unless $fd->{name} eq $field->{name};
next if $SKIPKEYS{$fd->{name}};
my $item = $meta->get( 'FIELD', $fd->{name} );
- $item->{value} = $fd->{value};
+ my $value = _escapeHtml( $fd->{value} ); # Item7939
+ $item->{value} = $value;
$meta->putKeyed( 'FIELD', $item );
$inform{$fd->{name}} = 1;
last;
@@ -974,7 +975,8 @@
my $leftoverText = '';
foreach my $fd (@{$data->{form}}) {
unless( $inform{$fd->{name}} || $SKIPKEYS{$fd->{name}} ) {
- $leftoverText .= " * $fd->{name}: $fd->{value}\n";
+ my $value = _escapeHtml( $fd->{value} ); # Item7939
+ $leftoverText .= " * $fd->{name}: $value\n";
}
}
return ( $meta, $leftoverText );
@@ -988,13 +990,22 @@
next if $SKIPKEYS{$fd->{name}};
my $title = $fd->{name};
$title =~ s/([a-z0-9])([A-Z0-9])/$1 $2/go; # Spaced
- my $value = $fd->{value};
+ my $value = _escapeHtml( $fd->{value} ); # Item7939
$value =~ s/[\n\r]//go;
$text .= " * $title\: $value\n";
}
return $text;
}
+# Item7939: escape HTML (guard against XSS vulnerability)
+sub _escapeHtml {
+ my $text = shift;
+ $text =~ s/&/&/go; # escape entities
+ $text =~ s/</</go; # escape HTML
+ $text =~ s/>/>/go; # escape HTML
+ return $text;
+}
+
# Sends to both the WIKIWEBMASTER and the USER notice of the registration
# emails both the admin 'registernotifyadmin' and the user 'registernotify',
# in separate emails so they both get targeted information (and no password
Implementation
--
Contributors:
Peter Thoeny - 2023-07-09
Discussion