aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>2006-03-29 18:50:36 +0000
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>2006-03-29 18:50:36 +0000
commitefe91335c65b96f3eb8b32d8c58c9cce68db47b4 (patch)
tree252c7b1a8af828b09e34c4d549975b71ca41831d
parent2a16e15122574cca9c5b52ccfc46a022a71e25dc (diff)
downloadikiwiki-efe91335c65b96f3eb8b32d8c58c9cce68db47b4.tar
ikiwiki-efe91335c65b96f3eb8b32d8c58c9cce68db47b4.tar.gz
improve fix for symlink attacks to check subdirectories for symlinks too
before writing
-rw-r--r--IkiWiki/CGI.pm2
-rw-r--r--IkiWiki/Render.pm6
-rw-r--r--doc/security.mdwn3
-rwxr-xr-xikiwiki17
4 files changed, 17 insertions, 11 deletions
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index b47c8e803..f360b6778 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -425,7 +425,7 @@ sub cgi_editpage ($$) { #{{{
my $content=$form->field('content');
$content=~s/\r\n/\n/g;
$content=~s/\r/\n/g;
- writefile("$config{srcdir}/$file", $content);
+ writefile($file, $config{srcdir}, $content);
my $message="web commit ";
if (length $session->param("name")) {
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 3d827d341..9e340c26e 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -349,7 +349,7 @@ sub render ($) { #{{{
$content=htmlize($type, $content);
check_overwrite("$config{destdir}/".htmlpage($page), $page);
- writefile("$config{destdir}/".htmlpage($page),
+ writefile(htmlpage($page), $config{destdir},
genpage($content, $page, mtime($srcfile)));
$oldpagemtime{$page}=time;
$renderedfiles{$page}=htmlpage($page);
@@ -358,14 +358,14 @@ sub render ($) { #{{{
# check_overwrite, as above, but currently renderedfiles
# only supports listing one file per page.
if ($config{rss} && exists $inlinepages{$page}) {
- writefile("$config{destdir}/".rsspage($page),
+ writefile(rsspage($page), $config{destdir},
genrss($content, $page, mtime($srcfile)));
}
}
else {
$links{$file}=[];
check_overwrite("$config{destdir}/$file", $file);
- writefile("$config{destdir}/$file", $content);
+ writefile($file, $config{destdir}, $content);
$oldpagemtime{$file}=time;
$renderedfiles{$file}=$file;
}
diff --git a/doc/security.mdwn b/doc/security.mdwn
index 0f8861d0d..3743adea1 100644
--- a/doc/security.mdwn
+++ b/doc/security.mdwn
@@ -161,7 +161,8 @@ 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.
+symlinks, or that are in subdirectories that are symlinks, combined with
+the above locking.
## underlaydir override attacks
diff --git a/ikiwiki b/ikiwiki
index 4ef6ceba3..b1bc9984f 100755
--- a/ikiwiki
+++ b/ikiwiki
@@ -202,15 +202,20 @@ sub readfile ($) { #{{{
return $ret;
} #}}}
-sub writefile ($$) { #{{{
- my $file=shift;
+sub writefile ($$$) { #{{{
+ my $file=shift; # can include subdirs
+ my $destdir=shift; # directory to put file in
my $content=shift;
- if (-l $file) {
- error("cannot write to a symlink ($file)");
+ my $test=$file;
+ while (length $test) {
+ if (-l "$destdir/$test") {
+ error("cannot write to a symlink ($test)");
+ }
+ $test=dirname($test);
}
- my $dir=dirname($file);
+ my $dir=dirname("$destdir/$file");
if (! -d $dir) {
my $d="";
foreach my $s (split(m!/+!, $dir)) {
@@ -221,7 +226,7 @@ sub writefile ($$) { #{{{
}
}
- open (OUT, ">$file") || error("failed to write $file: $!");
+ open (OUT, ">$destdir/$file") || error("failed to write $destdir/$file: $!");
print OUT $content;
close OUT;
} #}}}