mirror of
https://github.com/webmin/webmin.git
synced 2026-06-05 21:00:22 +01:00
Fix reflected XSS in Webmin status messages
* Note: Escape the /webmin/ message parameter, strip restart redirect HTML to plain text, and harden filter_javascript().
This commit is contained in:
39
t/web-lib-funcs-filter_javascript.t
Normal file
39
t/web-lib-funcs-filter_javascript.t
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/perl
|
||||
# Tests for web-lib-funcs.pl filter_javascript.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
use File::Basename qw(dirname);
|
||||
use File::Spec;
|
||||
|
||||
my $script = File::Spec->rel2abs(
|
||||
File::Spec->catfile(dirname(__FILE__), '..', 'web-lib-funcs.pl'));
|
||||
require $script;
|
||||
|
||||
is(
|
||||
main::filter_javascript('<video/onloadstart=alert(1) src=1>'),
|
||||
'<video/xonloadstart=alert(1) src=1>',
|
||||
'slash-separated HTML5 event handler is disabled',
|
||||
);
|
||||
|
||||
is(
|
||||
main::filter_javascript('<img src=x onload=alert(1)>'),
|
||||
'<img src=x xonload=alert(1)>',
|
||||
'classic event handler is disabled',
|
||||
);
|
||||
|
||||
is(
|
||||
main::filter_javascript('<div onwheel = alert(1) onpointerdown=alert(2)>'),
|
||||
'<div xonwheel = alert(1) xonpointerdown=alert(2)>',
|
||||
'multiple modern event handlers are disabled',
|
||||
);
|
||||
|
||||
is(
|
||||
main::filter_javascript(
|
||||
'<a data-onload="safe" href="javascript:alert(1)">link</a>'),
|
||||
'<a data-onload="safe" href="xjavascript:alert(1)">link</a>',
|
||||
'non-handler attributes are preserved while script URIs are disabled',
|
||||
);
|
||||
|
||||
done_testing();
|
||||
@@ -10179,10 +10179,15 @@ sub filter_javascript
|
||||
my ($rv, $type) = @_;
|
||||
if (!$type || $type eq 'html') {
|
||||
$rv =~ s/<\s*script[^>]*>([\000-\377]*?)<\s*\/script\s*>//gi;
|
||||
$rv =~ s/(on(Abort|BeforeUnload|Blur|Change|Click|ContextMenu|Copy|Cut|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|DragDrop|Drop|Error|Focus|FocusIn|FocusOut|HashChange|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|Move|Paste|PageShow|PageHide|Reset|Resize|Scroll|Search|Select|Submit|Toggle|Unload)=)/x$1/gi;
|
||||
$rv =~ s/(javascript(:|:|:|:))/x$1/gi;
|
||||
$rv =~ s/(vbscript(:|:|:|:))/x$1/gi;
|
||||
$rv =~ s/<([^>]*\s|)(on\S+=)(.*)>/<$1x$2$3>/gi;
|
||||
my $event_attr = qr/on[a-z][a-z0-9_:-]*\s*=/i;
|
||||
my $event_attrs;
|
||||
do {
|
||||
$event_attrs = 0;
|
||||
$event_attrs += $rv =~ s{(<[^>]*?)([\s/]+)($event_attr)}{$1$2x$3}g;
|
||||
$event_attrs += $rv =~ s{(<)($event_attr)}{$1x$2}g;
|
||||
} while ($event_attrs);
|
||||
}
|
||||
if ($type eq 'pdf') {
|
||||
$rv =~ s/([\n]*)<<[\n((?:.*?|\n)*?)][\w\s\/]+[\n((?:.*?|\n)*?)][\w\s\/]+JavaScript[\w\s\/]*[\n((?:.*?|\n)*?)][\w\s\/]+\s.*?>>[\n]*/$1/gmsi;
|
||||
|
||||
@@ -83,7 +83,7 @@ for(my $i=0; $i<@wlinks; $i++) {
|
||||
}
|
||||
}
|
||||
|
||||
print &ui_alert_box(&filter_javascript($in{'message'}), 'success', undef, 1,
|
||||
print &ui_alert_box(&html_escape($in{'message'}), 'success', undef, 1,
|
||||
&html_escape($in{'title'})) if ($in{'message'});
|
||||
|
||||
&icons_table(\@wlinks, \@wtitles, \@wicons);
|
||||
|
||||
@@ -1962,7 +1962,15 @@ my ($title, $msg) = @_;
|
||||
if (!$gconfig{'restart_async'}) {
|
||||
&restart_miniserv();
|
||||
my $msg_redir = "";
|
||||
$msg_redir = "?title=".&urlize($title)."&message=".&urlize($msg) if $msg;
|
||||
if ($msg) {
|
||||
$title = defined($title) ? &html_strip($title, " ") : "";
|
||||
$msg = &html_strip($msg, " ");
|
||||
$title =~ s/\s+/ /g;
|
||||
$title =~ s/^\s+|\s+$//g;
|
||||
$msg =~ s/\s+/ /g;
|
||||
$msg =~ s/^\s+|\s+$//g;
|
||||
$msg_redir = "?title=".&urlize($title)."&message=".&urlize($msg);
|
||||
}
|
||||
&redirect($msg_redir);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user