Thread: security: escaping user-supplied data
I am writing a C program that will collect data from various untrusted sources, and put it in a postgresql database by PQexec'ing an INSERT INTO statement. The statements I generate are usually of the form: INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); but the 'abc' and 'def' come from an untrusted source, so if they supply a string like "def'); delete from foo; '" they can make me do this: INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); delete from foo; ''); What do I need to do to prevent this? My current plan is to prepend a backslash to every single-quote, backslash, and semicolon in the untrusted string. Are there any other special characters I should watch out for? Is it possible to do something evil despite your special characters being prepended with a backslash?
At 02:31 +0200 on 12/10/1999, Jason Uhlenkott wrote: > The statements I generate are usually of the form: > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); > but the 'abc' and 'def' come from an untrusted source, so if they supply > a string like "def'); delete from foo; '" they can make me do this: > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); delete from foo; ''); > > What do I need to do to prevent this? My current plan is to prepend a > backslash to every single-quote, backslash, and semicolon in the > untrusted string. Are there any other special characters I should watch > out for? Is it possible to do something evil despite your special > characters being prepended with a backslash? I don't see why you would want to escape a semicolon. If you escape single quotes and backslashes, the above situation won't happen - the string won't be finished until the first unescaped quote - yours - is encountered. Semicolons are not special in strings. Herouth -- Herouth Maoz, Internet developer. Open University of Israel - Telem project http://telem.openu.ac.il/~herutma
On Tue, Oct 12, 1999 at 11:53:44AM +0200, Herouth Maoz wrote: > At 02:31 +0200 on 12/10/1999, Jason Uhlenkott wrote: > > > > The statements I generate are usually of the form: > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); > > but the 'abc' and 'def' come from an untrusted source, so if they supply > > a string like "def'); delete from foo; '" they can make me do this: > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); delete from foo; ''); > > > > What do I need to do to prevent this? My current plan is to prepend a > > backslash to every single-quote, backslash, and semicolon in the > > untrusted string. Are there any other special characters I should watch > > out for? Is it possible to do something evil despite your special > > characters being prepended with a backslash? > > I don't see why you would want to escape a semicolon. If you escape single > quotes and backslashes, the above situation won't happen - the string won't > be finished until the first unescaped quote - yours - is encountered. > Semicolons are not special in strings. > > Herouth I once posted a similar question to the pgsql-novice mailing list. There, David Rugge (1 Aug 1999) told me to escape ', ", and %, even though I am not quite sure why you have to escape " and %. But now that I think of it: you also need to escape \, of course, or backslashes will either get lost or, even worse, may escape the closing quote (think of $def="\"). Thus, using Perl and Pg, you would do: use Pg; $conn = ...; $abc="abc"; $def="def"; $conn->exec("INSERT INTO foo (bar, bas) VALUES ('" . &stdstr($abc) . "', '" . &stdstr($def) . "')"; sub stdstr { local $or = $_[0]; $or =~ s /\'/\\\'/g; $or =~ s /\"/\\\"/g; $or =~ s /%/\\%/g; $or =~ s /\\/\\\\/g; return $or; } Hope that helps, Albert. -- --------------------------------------------------------------------------- Post an / Mail to / Skribu al: Albert Reiner<areiner@tph.tuwien.ac.at> ---------------------------------------------------------------------------
PHP has some function that auto-escapes a query string so it is safe. You may want to check that. > On Tue, Oct 12, 1999 at 11:53:44AM +0200, Herouth Maoz wrote: > > At 02:31 +0200 on 12/10/1999, Jason Uhlenkott wrote: > > > > > > > The statements I generate are usually of the form: > > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); > > > but the 'abc' and 'def' come from an untrusted source, so if they supply > > > a string like "def'); delete from foo; '" they can make me do this: > > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); delete from foo; ''); > > > > > > What do I need to do to prevent this? My current plan is to prepend a > > > backslash to every single-quote, backslash, and semicolon in the > > > untrusted string. Are there any other special characters I should watch > > > out for? Is it possible to do something evil despite your special > > > characters being prepended with a backslash? > > > > I don't see why you would want to escape a semicolon. If you escape single > > quotes and backslashes, the above situation won't happen - the string won't > > be finished until the first unescaped quote - yours - is encountered. > > Semicolons are not special in strings. > > > > Herouth > > I once posted a similar question to the pgsql-novice mailing > list. There, David Rugge (1 Aug 1999) told me to escape ', ", and %, > even though I am not quite sure why you have to escape " and %. But > now that I think of it: you also need to escape \, of course, or > backslashes will either get lost or, even worse, may escape the > closing quote (think of $def="\"). Thus, using Perl and Pg, you would > do: > > use Pg; > $conn = ...; > > $abc="abc"; > $def="def"; > $conn->exec("INSERT INTO foo (bar, bas) VALUES ('" . > &stdstr($abc) . "', '" . &stdstr($def) . "')"; > > sub stdstr { > local $or = $_[0]; > $or =~ s /\'/\\\'/g; > $or =~ s /\"/\\\"/g; > $or =~ s /%/\\%/g; > $or =~ s /\\/\\\\/g; > return $or; > } > > Hope that helps, > > Albert. > > -- > > --------------------------------------------------------------------------- > Post an / Mail to / Skribu al: Albert Reiner <areiner@tph.tuwien.ac.at> > --------------------------------------------------------------------------- > > ************ > > -- Bruce Momjian | http://www.op.net/~candle maillist@candle.pha.pa.us | (610) 853-3000+ If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania19026
Here's a function in perl which should work for cleaning a string which is sent in a query: # The checks for already backslashed apostrophies and backslashes # prevent tricks with these, and also allow us to run clean_text() # several times. sub clean_text { my $text = shift; return "" if (! defined $text || ! length($text)); # First change backslashed backslashes back to single backslashes. $text =~ s/\\\\/\\/g; # Find backslash single quote combinations and convert them to single quotes. # while... is theoretically not necessary. It's there just as an assurance. while ($text =~ /\\\'/) { $text =~ s/\\\'/'/g; } # Now there should be no single quotes preceded by backslashes left. # Then find all backslashes and convert them to doubles. $text =~ s/\\/\\\\/g; # Now all characters preceded by a backslash should be in their # original state, while all backslashed single quotes are # just single quotes. # Find all single quotes and backslash them. # (Note: There are no single quotes preceded by a backslash, so # it is not possible to have a backslash which would hide a # backslash preceding a single quote.) $text =~ s/\'/\\'/g; return $text; } The function could be more efficient if you made $text a reference. If you know how to use references in Perl, then the conversion is easy. Just drop the "return" from the end and change all references to $text with $$text. You should also add a check such as "! defined $text || ! ref $text ||" to the second line's if statement. If you find a way to exploit this, I would like to know. Troy > > At 02:31 +0200 on 12/10/1999, Jason Uhlenkott wrote: > > > > The statements I generate are usually of the form: > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); > > but the 'abc' and 'def' come from an untrusted source, so if they supply > > a string like "def'); delete from foo; '" they can make me do this: > > INSERT INTO foo (bar, bas) VALUES ('abc', 'def'); delete from foo; ''); > > > > What do I need to do to prevent this? My current plan is to prepend a > > backslash to every single-quote, backslash, and semicolon in the > > untrusted string. Are there any other special characters I should watch > > out for? Is it possible to do something evil despite your special > > characters being prepended with a backslash? > > I don't see why you would want to escape a semicolon. If you escape single > quotes and backslashes, the above situation won't happen - the string won't > be finished until the first unescaped quote - yours - is encountered. > Semicolons are not special in strings. > > Herouth > > -- > Herouth Maoz, Internet developer. > Open University of Israel - Telem project > http://telem.openu.ac.il/~herutma > > > > ************ > >