看板FB_security
标 题Re: ctags(1) command execution vulnerability
发信站NCTU CSIE FreeBSD Server (Tue May 4 06:17:21 2004)
转信站ptt!FreeBSD.csie.NCTU!not-for-mail
--3607uds81ZQvwCD0
Content-Type: text/plain; charset=windows-1251
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Tue, May 04, 2004 at 09:49:09AM +0400, Roman Bogorodskiy wrote:
> Hello,
>=20
> ctags(1) uses external application sort(1) for sorting the tags file.
> It calls it via system(3) function.=20
[snip]
> This code will be executed when "-u" arg was given. So, if we'll execute=
=20
> ctags in a such way:
>=20
> ctags -u -f ';echo hi' *.c
[snip]
> - "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS",
> + "mv '%s' OTAGS; fgrep -v '\t%s\t' OTAGS >'%s'; rm OTAGS",
[snip]
> - (void)asprintf(&cmd, "sort -o %s %s",
> + (void)asprintf(&cmd, "sort -o '%s' '%s'",
Unfortunately, this is still not a complete solution; the following
still works, at least for me:
ctags -u -f "'; echo hi; '" *.c
Filtering the filename characters would be a better idea; possibly
something like the attached patch.
G'luck,
Peter
--=20
Peter Pentchev
[email protected] [email protected] [email protected]
PGP key:
http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint FDBA FD79 C26F 3C51 C95E DF9E ED18 B68D 1619 4553
This sentence contradicts itself - or rather - well, no, actually it doesn'=
t!
Index: src/usr.bin/ctags/ctags.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/usr.bin/ctags/ctags.c,v
retrieving revision 1.18
diff -u -r1.18 ctags.c
--- src/usr.bin/ctags/ctags.c 28 Jul 2002 15:50:38 -0000 1.18
+++ src/usr.bin/ctags/ctags.c 4 May 2004 06:27:23 -0000
@@ -46,6 +46,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/usr.bin/ctags/ctags.c,v 1.18 2002/07/28 15:50:38 d=
wmalone Exp $");
=20
+#include <ctype.h>
#include <err.h>
#include <limits.h>
#include <locale.h>
@@ -84,6 +85,7 @@
void init(void);
void find_entries(char *);
static void usage(void);
+static char *validatename(const char *);
=20
int
main(int argc, char **argv)
@@ -118,7 +120,7 @@
dflag++;
break;
case 'f':
- outfile =3D optarg;
+ outfile =3D validatename(optarg);
break;
case 't':
tflag =3D YES;
@@ -201,6 +203,25 @@
exit(1);
}
=20
+static char *
+validatename(const char *fname)
+{
+ char *n, *q;
+ const char *p, *end;
+ size_t len;
+
+ len =3D strlen(fname);
+ n =3D malloc(len + 1);
+ if (n =3D=3D NULL)
+ errx(1, "out of memory");
+ end =3D n + len;
+ for (p =3D fname, q =3D n; *p !=3D '\0' && q !=3D end; p++)
+ if (isalnum(*p) || strchr("-_./", *p) !=3D NULL)
+ *q++ =3D *p;
+ *q =3D '\0';
+ return (n);
+}
+
/*
* init --
* this routine sets up the boolean pseudo-functions which work by
--3607uds81ZQvwCD0
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)
iD8DBQFAlzks7Ri2jRYZRVMRAgQ4AJ9LEE0VNee8HhLbHAsbYYhr7+potgCfU48a
U3Zm3CwU67Chz1MsWVZMglM=
=RRar
-----END PGP SIGNATURE-----
--3607uds81ZQvwCD0--