Re: [dev] Miscellaneous sbase issues

2015-05-05 Thread Truls Becken
+1 for option 3)

Why would anybody want to trust somebody that creates malicious
archives like that?
A symlink in an archive should just be a symlink, nothing more.

-Truls



Re: [dev] Miscellaneous sbase issues

2015-05-05 Thread Dimitris Papastamos
On Mon, Apr 27, 2015 at 08:12:42PM +0100, Nick wrote:
> One thing the patch doesn't cover is an archive using a symlink to 
> somewhere like ../../ and then putting a file in symlink/newfile 
> (hence sending it to ../../newfile). I only thought of that when 
> reading the bsdtar manpage[0].
> 
> I'm not sure what the best behaviour is in that case. Some options:
> 
> 1) If a symlink creates a path ascending further up the directory 
> tree (towards /) than the current directory, replace all symlinks in 
> the path with directories and extract there.
> 
> 2) Remove the symlink and replace it with a real directory before 
> extracting the file into it (this is the behaviour of bsdtar with 
> the -U option)
> 
> 3) Refuse to create any file following a symlink (this is the 
> default behaviour of bsdtar)
> 
> 4) Issue a warning if writing a file, but follow the symlink as 
> instructed
> 
> If you're curious about how bsdtar does it, look at check_symlinks() 
> in libarchive/archive_write_disk_posix.c, but note the comment at 
> the top of the function - "TODO: Make this work."
> 
> I have a slight preference for option 1, but it doesn't feel 
> particularly clean. Anyone else have better ideas? I know it's 
> annoying, but I don't think "ignore it" is good enough, as it would 
> be far too easy to create a tarball that blatted any file the user 
> had access to using this method (and using -t to check paths 
> wouldn't help, as the ../ is in the symlink target). I'm attaching a 
> tarball that demonstrates the problem, in case I haven't explained 
> it well enough. If you used $HOME/bin/, and unpacked the tarball in 
> $HOME/tmp, it will create a file in $HOME/bin/myscript.
> 
> Nick
> 
> 0. 
> https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/bsdtar.1.html

I am not sure what the proper approach is.  Option 3) sounds pretty
safe as a starting point.

Any ideas?



Re: [dev] Miscellaneous sbase issues

2015-04-27 Thread Nick
Quoth Nick:
> Quoth Dimitris Papastamos: 
> > Some things that need to be done for tar:
> > 
> > ...
> > - Strip leading / from filenames and dangerous things like ../../ etc.
> 
> OK, attached is a patch that does that. I think it covers all the 
> bases.

One thing the patch doesn't cover is an archive using a symlink to 
somewhere like ../../ and then putting a file in symlink/newfile 
(hence sending it to ../../newfile). I only thought of that when 
reading the bsdtar manpage[0].

I'm not sure what the best behaviour is in that case. Some options:

1) If a symlink creates a path ascending further up the directory 
tree (towards /) than the current directory, replace all symlinks in 
the path with directories and extract there.

2) Remove the symlink and replace it with a real directory before 
extracting the file into it (this is the behaviour of bsdtar with 
the -U option)

3) Refuse to create any file following a symlink (this is the 
default behaviour of bsdtar)

4) Issue a warning if writing a file, but follow the symlink as 
instructed

If you're curious about how bsdtar does it, look at check_symlinks() 
in libarchive/archive_write_disk_posix.c, but note the comment at 
the top of the function - "TODO: Make this work."

I have a slight preference for option 1, but it doesn't feel 
particularly clean. Anyone else have better ideas? I know it's 
annoying, but I don't think "ignore it" is good enough, as it would 
be far too easy to create a tarball that blatted any file the user 
had access to using this method (and using -t to check paths 
wouldn't help, as the ../ is in the symlink target). I'm attaching a 
tarball that demonstrates the problem, in case I haven't explained 
it well enough. If you used $HOME/bin/, and unpacked the tarball in 
$HOME/tmp, it will create a file in $HOME/bin/myscript.

Nick

0. 
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/bsdtar.1.html


test.tar
Description: Unix tar archive


signature.asc
Description: Digital signature


Re: [dev] Miscellaneous sbase issues

2015-04-27 Thread FRIGN
On Sun, 26 Apr 2015 18:24:18 -0700
Michael Forney  wrote:

Hi Michael,

> printf
> --
> Ignores flag characters '#', '0', '-', ' ', and '+', but is labeled as
> POSIX compliant and complete, so this is presumably unintentional.
> 
> "git am" breaks without this functionality.

I fixed this in the latest commit, thanks for reporting! Stay tuned for it
to be pushed to the suckless repositories, it's still in staging.
Please let me know if "git am" works now. :)

Cheers

FRIGN

-- 
FRIGN 



Re: [dev] Miscellaneous sbase issues

2015-04-27 Thread Nick
Quoth Dimitris Papastamos: 
> Some things that need to be done for tar:
> 
> ...
> - Strip leading / from filenames and dangerous things like ../../ etc.

OK, attached is a patch that does that. I think it covers all the 
bases.
>From b5acf1e9254080c2f283c623f59e412cdb29939a Mon Sep 17 00:00:00 2001
From: Nick White 
Date: Mon, 27 Apr 2015 12:25:44 +0100
Subject: [PATCH] Strip dangerous path traversal stuff from paths

Specifically, this removes '../' from anywhere in a path, and any
number of '/' at the start of a path
---
 tar.c |   22 ++
 1 file changed, 22 insertions(+)

diff --git a/tar.c b/tar.c
index b1f3b27..0bd3fcf 100644
--- a/tar.c
+++ b/tar.c
@@ -359,6 +359,27 @@ sanitize(struct header *h)
 }
 
 static void
+sanitizepath(char *p)
+{
+	size_t l;
+	char *s;
+
+	/* Strip leading '/' characters */
+	while(*p == '/') {
+		l = strlen(p);
+		memmove(p, p+1, l - 1);
+		*(p + l - 1) = '\0';
+	}
+
+	/* Strip '../' from anywhere */
+	while((s = strstr(p, "../")) != NULL) {
+		l = strlen(s);
+		memmove(s, s + 3, l - 3);
+		*(s + l - 3) = '\0';
+	}
+}
+
+static void
 chktar(struct header *h)
 {
 	char tmp[8], *err;
@@ -407,6 +428,7 @@ xt(int argc, char *argv[], int (*fn)(char *, ssize_t, char[BLKSIZ]))
 			 (int)sizeof(h->prefix), h->prefix);
 		snprintf(fname + n, sizeof(fname) - n, "%.*s",
 		 (int)sizeof(h->name), h->name);
+		sanitizepath(fname);
 
 		if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
 			eprintf("strtol %s: invalid number\n", h->size);
-- 
1.7.10.4



Re: [dev] Miscellaneous sbase issues

2015-04-27 Thread Dimitris Papastamos
On Sun, Apr 26, 2015 at 06:24:18PM -0700, Michael Forney wrote:
> tar
> ---
> Since fb1595a69c091a6f6a9303b1fab19360b876d114, tar calls remove(3) on
> directories before extracting them. I'm not sure that it is reasonable
> for tar to do this because users may want to re-extract archives, or
> extract archives on top a directory structure that already exists.
> Additionally, it is fairly common to find tar archives containing the
> "." directory (possibly with a trailing '/'), which were constructed
> using "tar -cf foo.tar .".

Yeah that makes sense I suppose.  Some things that need to be done
for tar:

- Investigate aforementioned remove vs unlink issue.
- When we tar a file, we need to ensure to use both name/prefix if the
filename is more than 100 chars.
- Strip leading / from filenames and dangerous things like ../../ etc.

> cat, tee
> 
> These utilities read from stdin using fread(3) into a buffer of size
> BUFSIZ. However, fread will read until it fills up the entire buffer (or
> hits EOF) before returning, causing noticeable delay when the input
> comes from other programs or scripts.
> 
> To demonstrate this problem, compare the output of these commands:
> 
>   for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done
>   for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | cat
>   for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | tee
> 
> I considered fixing this by making the concat function take an fd
> instead and make a single call to read(2), but this causes problems for
> sponge, which uses a FILE * obtained from tmpfile(3) as both output and
> input for concat. We could also use mkstemp(3) to return a file
> descriptor, and use a FILE * from fdopen for writing, and the file
> descriptor for reading, but this seems unclean to me.

We should avoid mixing file stream I/O and raw I/O.
Check out '2.5.1 Interaction of File Descriptors and Standard I/O Streams'.

> Another option would be to use fgetc and fputc for the concat
> implementation, and let libc take care of the buffering. I'm not sure if
> this has any performance implications.

Sounds about right.



Re: [dev] Miscellaneous sbase issues

2015-04-27 Thread koneu
On April 27, 2015 3:24:18 AM CEST, Michael Forney  wrote:
>Hi suckless,
>
>I came across some issues in sbase whose solution wasn't immediately
>apparent:
>
>printf
>--
>Ignores flag characters '#', '0', '-', ' ', and '+', but is labeled as
>POSIX compliant and complete, so this is presumably unintentional.
>
>"git am" breaks without this functionality.
>
>tar
>---
>Since fb1595a69c091a6f6a9303b1fab19360b876d114, tar calls remove(3) on
>directories before extracting them. I'm not sure that it is reasonable
>for tar to do this because users may want to re-extract archives, or
>extract archives on top a directory structure that already exists.
>Additionally, it is fairly common to find tar archives containing the
>"." directory (possibly with a trailing '/'), which were constructed
>using "tar -cf foo.tar .".
>
>cat, tee
>
>These utilities read from stdin using fread(3) into a buffer of size
>BUFSIZ. However, fread will read until it fills up the entire buffer
>(or
>hits EOF) before returning, causing noticeable delay when the input
>comes from other programs or scripts.
>
>To demonstrate this problem, compare the output of these commands:
>
>  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done
>for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done |
>cat
>for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done |
>tee
>
>I considered fixing this by making the concat function take an fd
>instead and make a single call to read(2), but this causes problems for
>sponge, which uses a FILE * obtained from tmpfile(3) as both output and
>input for concat. We could also use mkstemp(3) to return a file
>descriptor, and use a FILE * from fdopen for writing, and the file
>descriptor for reading, but this seems unclean to me.
>
>Another option would be to use fgetc and fputc for the concat
>implementation, and let libc take care of the buffering. I'm not sure
>if
>this has any performance implications.
>
>
>Thanks everyone for their work on sbase! It really has come a long way
>in the last 6 months.

Firstly, patch..?
For cat and tee fgets might be more appropriate.



[dev] Miscellaneous sbase issues

2015-04-26 Thread Michael Forney
Hi suckless,

I came across some issues in sbase whose solution wasn't immediately
apparent:

printf
--
Ignores flag characters '#', '0', '-', ' ', and '+', but is labeled as
POSIX compliant and complete, so this is presumably unintentional.

"git am" breaks without this functionality.

tar
---
Since fb1595a69c091a6f6a9303b1fab19360b876d114, tar calls remove(3) on
directories before extracting them. I'm not sure that it is reasonable
for tar to do this because users may want to re-extract archives, or
extract archives on top a directory structure that already exists.
Additionally, it is fairly common to find tar archives containing the
"." directory (possibly with a trailing '/'), which were constructed
using "tar -cf foo.tar .".

cat, tee

These utilities read from stdin using fread(3) into a buffer of size
BUFSIZ. However, fread will read until it fills up the entire buffer (or
hits EOF) before returning, causing noticeable delay when the input
comes from other programs or scripts.

To demonstrate this problem, compare the output of these commands:

  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done
  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | cat
  for i in $(seq 500) ; do printf 0123456789abcdef ; sleep 0.005 ; done | tee

I considered fixing this by making the concat function take an fd
instead and make a single call to read(2), but this causes problems for
sponge, which uses a FILE * obtained from tmpfile(3) as both output and
input for concat. We could also use mkstemp(3) to return a file
descriptor, and use a FILE * from fdopen for writing, and the file
descriptor for reading, but this seems unclean to me.

Another option would be to use fgetc and fputc for the concat
implementation, and let libc take care of the buffering. I'm not sure if
this has any performance implications.


Thanks everyone for their work on sbase! It really has come a long way
in the last 6 months.


pgpDBGzDW2cHX.pgp
Description: PGP signature