found & fixed another symlink attack
parent
2eb5893ce7
commit
62f1f9732b
|
@ -141,6 +141,22 @@ into the repo. ikiwiki uses File::Find to traverse the repo, and does not
|
||||||
tell it to follow symlinks, but it might be possible to race replacing a
|
tell it to follow symlinks, but it might be possible to race replacing a
|
||||||
directory with a symlink and trick it into following the link.
|
directory with a symlink and trick it into following the link.
|
||||||
|
|
||||||
Also, if someone checks in a symlink to /etc/passwd, ikiwiki would read and publish that, which could be used to expose files a committer otherwise wouldn't see.
|
Also, if someone checks in a symlink to /etc/passwd, ikiwiki would read and
|
||||||
|
publish that, which could be used to expose files a committer otherwise
|
||||||
|
wouldn't see.
|
||||||
|
|
||||||
To avoid this, ikiwiki will avoid reading files that are symlinks, and uses locking to prevent more than one instance running at a time. The lock prevents one ikiwiki from running a svn up at the wrong time to race another ikiwiki. So only attackers who can write to the working copy on their own can race it.
|
To avoid this, ikiwiki will skip over symlinks when scanning for pages, and
|
||||||
|
uses locking to prevent more than one instance running at a time. The lock
|
||||||
|
prevents one ikiwiki from running a svn up at the wrong time to race
|
||||||
|
another ikiwiki. So only attackers who can write to the working copy on
|
||||||
|
their own can race it.
|
||||||
|
|
||||||
|
## symlink + cgi attacks
|
||||||
|
|
||||||
|
Similarly, a svn commit of a symlink could be made, ikiwiki ignores it
|
||||||
|
because of the above, but the symlink is still there, and then you edit the
|
||||||
|
page from the web, which follows the symlink when reading the page, and
|
||||||
|
again when saving the changed page.
|
||||||
|
|
||||||
|
This was fixed by making ikiwiki refuse to read or write to files that are
|
||||||
|
symlinks, combined with the above locking.
|
||||||
|
|
10
ikiwiki
10
ikiwiki
|
@ -152,6 +152,10 @@ sub htmlpage ($) { #{{{
|
||||||
sub readfile ($) { #{{{
|
sub readfile ($) { #{{{
|
||||||
my $file=shift;
|
my $file=shift;
|
||||||
|
|
||||||
|
if (-l $file) {
|
||||||
|
error("cannot read a symlink ($file)");
|
||||||
|
}
|
||||||
|
|
||||||
local $/=undef;
|
local $/=undef;
|
||||||
open (IN, "$file") || error("failed to read $file: $!");
|
open (IN, "$file") || error("failed to read $file: $!");
|
||||||
my $ret=<IN>;
|
my $ret=<IN>;
|
||||||
|
@ -162,6 +166,10 @@ sub readfile ($) { #{{{
|
||||||
sub writefile ($$) { #{{{
|
sub writefile ($$) { #{{{
|
||||||
my $file=shift;
|
my $file=shift;
|
||||||
my $content=shift;
|
my $content=shift;
|
||||||
|
|
||||||
|
if (-l $file) {
|
||||||
|
error("cannot write to a symlink ($file)");
|
||||||
|
}
|
||||||
|
|
||||||
my $dir=dirname($file);
|
my $dir=dirname($file);
|
||||||
if (! -d $dir) {
|
if (! -d $dir) {
|
||||||
|
@ -1334,7 +1342,7 @@ sub cgi_editpage ($$) { #{{{
|
||||||
! length $form->field('content')) {
|
! length $form->field('content')) {
|
||||||
my $content="";
|
my $content="";
|
||||||
if (exists $pagesources{lc($page)}) {
|
if (exists $pagesources{lc($page)}) {
|
||||||
$content=readfile("$config{srcdir}/$pagesources{lc($page)}");
|
$content=readfile("$config{srcdir}/$pagesources{lc($page)}");
|
||||||
$content=~s/\n/\r\n/g;
|
$content=~s/\n/\r\n/g;
|
||||||
}
|
}
|
||||||
$form->field(name => "content", value => $content,
|
$form->field(name => "content", value => $content,
|
||||||
|
|
Loading…
Reference in New Issue