Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dangers of web apps written in Tcl

49 views
Skip to first unread message

Derek Fountain

unread,
Jul 19, 2006, 4:45:22 AM7/19/06
to
I was in a debate with someone at work the other day regarding the
suitability of certain languages for web application programming. Tcl
wasn't a player in the debate, except for one throwaway comment where
someone said he'd never use Tcl for a web application.

Putting his argument in a Tcl context, what he was basically saying is
that because of Tcl's recursive execution nature, you have to be very
careful to check all user input, regardless of what you intend to do
with it because with Tcl it might get evaluated. So, if someone
supplies, say, a name that you're just planning on writing to a file or
something, with Tcl you have to check that name data with as much
paranoia as you would if they were supplying a filename you're about to
act on.

Now, I've written enough Tcl over the years to know that if someone
gives a name of '[incr credits]' there's nothing in Tcl that will
magically execute that code and present the user with another credit on
the system. But, there is a risk here. There's /no/ chance of someone
giving a name of 'credits++' to a C/C++ based system and having that
executed. The risk for applications written in Perl and PHP also seems
less than Tcl, provided the programmer doesn't use 'eval'.

Not withstanding the fact that it's best to check everything, and some
languages have other security related issues that TCL doesn't have, what
are the potential errors peculiar to Tcl and its nature that a web
developer might walk into and leave open a security hole?

tun...@yahoo.com

unread,
Jul 19, 2006, 5:40:10 AM7/19/06
to
Derek Fountain wrote:
> I was in a debate with someone at work the other day regarding the
> suitability of certain languages for web application programming. Tcl
> wasn't a player in the debate, except for one throwaway comment where
> someone said he'd never use Tcl for a web application.
>
> Putting his argument in a Tcl context, what he was basically saying is
> that because of Tcl's recursive execution nature, you have to be very
> careful to check all user input, regardless of what you intend to do
> with it because with Tcl it might get evaluated.
> ...

> Not withstanding the fact that it's best to check everything, and some
> languages have other security related issues that TCL doesn't have, what
> are the potential errors peculiar to Tcl and its nature that a web
> developer might walk into and leave open a security hole?


Why is this limited to web apps? There are many ways/widgets in plain
Tcl/Tk that let user enter data. In your friend's logic, wouldn't the
same be true there as well, even more so?

Nevertheless, the fear is unfounded. Everything is a string unless and
until the programmer makes special sense of it. If a credit amount is
expected, it should be checked as a numeric value, otherwise, how are
you expecting to do arithmetic on strings? Common to all other
languages.

Quite contrary, this flexibility provides for more secure apps. Take
Lisp, a prime example of a "recursive execution language". Not only
complex web apps, but a number of financial, scientific and space
applications are (and continue to be) written in it. (I believe the
Hubble telescope controls are also in Lisp.)

Robert Hicks

unread,
Jul 19, 2006, 6:23:14 AM7/19/06
to

Derek Fountain wrote:
> I was in a debate with someone at work the other day regarding the
> suitability of certain languages for web application programming. Tcl
> wasn't a player in the debate, except for one throwaway comment where
> someone said he'd never use Tcl for a web application.
>
> Putting his argument in a Tcl context, what he was basically saying is
> that because of Tcl's recursive execution nature, you have to be very
> careful to check all user input, regardless of what you intend to do
> with it because with Tcl it might get evaluated. So, if someone
> supplies, say, a name that you're just planning on writing to a file or
> something, with Tcl you have to check that name data with as much
> paranoia as you would if they were supplying a filename you're about to
> act on.
>
You friend is incorrect. That isn't a "Tcl" problem that is a
"programming" problem. Whatever language you use to do you web work, if
you give the user the opportunity to type something in you better be
validating what is typed in to your own peril. You can dig up many many
articles on PHP about that very thing. Yet, sadly, PHP is used for a
whole lot of web apps.

Tcl (either in pure form, Rivet or Websh) is a great way to create web
applications.

His logic is flawed.

Robert

Neil Madden

unread,
Jul 19, 2006, 6:20:39 AM7/19/06
to
Derek Fountain wrote:
> I was in a debate with someone at work the other day regarding the
> suitability of certain languages for web application programming. Tcl
> wasn't a player in the debate, except for one throwaway comment where
> someone said he'd never use Tcl for a web application.
>
> Putting his argument in a Tcl context, what he was basically saying is
> that because of Tcl's recursive execution nature, you have to be very
> careful to check all user input, regardless of what you intend to do
> with it because with Tcl it might get evaluated. So, if someone
> supplies, say, a name that you're just planning on writing to a file or
> something, with Tcl you have to check that name data with as much
> paranoia as you would if they were supplying a filename you're about to
> act on.
>
> Now, I've written enough Tcl over the years to know that if someone
> gives a name of '[incr credits]' there's nothing in Tcl that will
> magically execute that code and present the user with another credit on
> the system. But, there is a risk here. There's /no/ chance of someone
> giving a name of 'credits++' to a C/C++ based system and having that
> executed. The risk for applications written in Perl and PHP also seems
> less than Tcl, provided the programmer doesn't use 'eval'.

This is simply not true. There are a great many buffer overrun attacks
against C/C++ code which precisely exploit the ability to inject
malicious code into a running application. Tcl is immune to this entire
class of errors. All you have to worry about with Tcl is that you don't
accidentally call [eval] on some user input -- a "problem" that pretty
much any interpreted language would have to deal with. Even Java has
such things as Runtime.exec("rm -rf /") -- so by this argument every
J2EE installation is inherently unsafe.

>
> Not withstanding the fact that it's best to check everything, and some
> languages have other security related issues that TCL doesn't have, what
> are the potential errors peculiar to Tcl and its nature that a web
> developer might walk into and leave open a security hole?

Run your web-apps in a safe interpreter and expose only APIs you really
need (e.g. expose a high-level interface to your db, rather than access
to the whole filesystem). That Tcl has safe interpreters makes it
*vastly* more secure than C or C++, and at least on a par with Java.

-- Neil

Donald Arseneau

unread,
Jul 19, 2006, 8:00:21 AM7/19/06
to
Derek Fountain <nom...@hursley.ibm.com> writes:

> because of Tcl's recursive execution nature, you have to be very careful to
> check all user input,

Recursion has nothing to do with it, but I assume he worried
about Tcl's dynamic nature.

> regardless of what you intend to do with it because
> with Tcl it might get evaluated. So, if someone supplies, say, a name that
> you're just planning on writing to a file or something, with Tcl you have to
> check that name data with as much paranoia as you would if they were
> supplying a filename you're about to act on.

This is just untrue. There are a few commands that perform
evaluation, and you have to avoid supplying them with user data,
I can think of only a few cases where the programmer may be tempted
to eval such data, but obeying a few simple standard guidelines
will protect the program.

1) using [eval command $userdata] to split an argument into many.
Never treat user data as a list -- it never is. To make a list use
[split]. (You can then [eval] the result safely.)

2) using [expr 5*$userdata]. Always put expressions in braces.
It is said over and over again, but people still fail to heed
the advice.

3) using user data as a <script> argument intentionally.
Don't ever program web applications.

Finally, Tcl provides safe interpreters, like a java sandbox,
which can protect you even if a web program is otherwise badly
written.

--
Donald Arseneau as...@triumf.ca

Gerald W. Lester

unread,
Jul 19, 2006, 8:06:14 AM7/19/06
to
tun...@yahoo.com wrote:
> Quite contrary, this flexibility provides for more secure apps. Take
> Lisp, a prime example of a "recursive execution language". Not only
> complex web apps, but a number of financial, scientific and space
> applications are (and continue to be) written in it. (I believe the
> Hubble telescope controls are also in Lisp.)

Actually the Hubble is in Tcl/Tk.

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

Gerald W. Lester

unread,
Jul 19, 2006, 8:13:42 AM7/19/06
to
Derek Fountain wrote:
> ...

> Not withstanding the fact that it's best to check everything, and some
> languages have other security related issues that TCL doesn't have, what
> are the potential errors peculiar to Tcl and its nature that a web
> developer might walk into and leave open a security hole?

As several others have already said, the simple answer is no.

Some things no one mentioned:

1)When dealing with a database always use bound variables (see
http://en.wikipedia.org/wiki/SQL_injection) -- this is true in all languages.

2) Always use [file normalize] on user supplied file names (avoids the
possibility that the name will begin with a "|") -- or better yet don't use
user file names on a web app.

Derek Fountain

unread,
Jul 19, 2006, 9:30:01 AM7/19/06
to
>> because of Tcl's recursive execution nature, you have to be very careful to
>> check all user input,
>
> Recursion has nothing to do with it, but I assume he worried
> about Tcl's dynamic nature.

"recursive execution nature", not recursion itself. But yes, the concern
is the nature of the language.

>> regardless of what you intend to do with it because
>> with Tcl it might get evaluated. So, if someone supplies, say, a name that
>> you're just planning on writing to a file or something, with Tcl you have to
>> check that name data with as much paranoia as you would if they were
>> supplying a filename you're about to act on.
>
> This is just untrue.

Most other people who responded to my post leapt in with "Tcl is safer
than C, all languages have that problem, etc." which was the debate I
was trying to avoid. But they also all said the above quote is untrue,
as did you. But then you gave a couple of examples of why I'm concerned:

> 1) using [eval command $userdata]

OK, I think we can assume that as soon as [eval] goes near user supplied
data we have to be worried with Tcl, Perl or PHP. No problem there - the
warning flag in a programmer's head should go up as soon as he types e,
v, a and l....

> 2) using [expr 5*$userdata]. Always put expressions in braces.
> It is said over and over again, but people still fail to heed
> the advice.

...but the above is a great example of what I was thinking of.

Suppose my code contains a variable the user wants to alter. For
purposes of demonstration, let's say he wants to increment this variable:

set target 0

and, as part of my application, I want to check the 'age' he gives me
with this code, from which I've missed off the braces:

set underAge [expr $inputAge < 17]

If inputAge is '21', I see this (simulated in tkcon):

(derek) 54 % set target 0
0
(derek) 55 % set inputAge 21
21
(derek) 56 % set underAge [expr $inputAge < 17]
0

Fine. Now suppose he gives me an age of '[incr target]' (without the
quotes):

(derek) 62 % set target 0
0
(derek) 63 % set inputAge {[incr target]}
[incr target]
(derek) 64 % set underAge [expr $inputAge < 17]
1
(derek) 65 % puts $target
1

That's exactly the point. I wasn't intending to evaluate his input, or
indeed do anything with it except compare it against a set value. And
yet code he has entered has been evaluated and changed the running of
the application. I don't think you can do that with Perl or PHP without
using eval.

I fully accept the argument that you should put the operands for the
expr in braces. The manual page for expr does indeed say "As discussed
below, it is usually best to enclose expressions in braces to prevent
the command parser from performing substitutions on the contents." Mind
you, 4 lines later the manual page gives this example:

expr 3.1 + $a 6.1

Not exactly practising what is preached, and besides, it only says
"usually best"...

So [expr] introduces the sort of security risk I'm talking about, and
it's not described as a risk in the documentation. Nor is it that common
knowledge, at least among the presumably very knowledgable people who
responded to my post (yourself excepted of course). [expr] is a very
commonly used command. This worries me. Where else in my Tcl code might
I find an unintended command substitution which a hacker can exploit?

Gerald W. Lester

unread,
Jul 19, 2006, 9:47:49 AM7/19/06
to
Derek Fountain wrote:
>...
> So [expr] introduces the sort of security risk I'm talking about, and
> it's not described as a risk in the documentation. Nor is it that common
> knowledge, at least among the presumably very knowledgable people who
> responded to my post (yourself excepted of course). [expr] is a very
> commonly used command. This worries me. Where else in my Tcl code might
> I find an unintended command substitution which a hacker can exploit?

The risk spots (in order of frequency) are:

1) Expr with unbraced args (or any command that implicitly uses expr (if,
while, for, ...)

2) Eval -- duh (or any command that implicitly uses expr (if, while, for,
..., e.g. if {$someCondition) then $userSuppliedCommand)

3) Exec -- duh (this is any language)

3) Open -- always use [file normalize] on user supplied file names (avoids

the possibility that the name will begin with a "|") -- or better yet don't
use user file names on a web app.

4) Database access (this is any language) -- when dealing with a database
always use bound variables (see http://en.wikipedia.org/wiki/SQL_injection).

5) Uplevel -- rarely used and anyone using it really should be knowledgeable
enough to avoid any pitfalls.

I've included #3 and #4 although they are not unique to Tcl.

Michael Schlenker

unread,
Jul 19, 2006, 10:18:59 AM7/19/06
to
Derek Fountain schrieb:

Not really understanding 'man n Tcl' is the most serious risk...

Basically a developer has a lot of pitfalls available to shoot himself
in the foot, not as many as in PHP for example, but enough. In a web app
he has the unfortunate fact that he exposes his app to a hostile
environment, so he needs to be really paranoid, which is somewhat less a
problem for in-house apps (you can always sue your contractors if
someone hacks deliberately).

Some of the other posts have already mentioned the common pitfalls of
unexpected evaluation, expr, subst, eval, uplevel etc.

If you don't check your input data for a web app in paranoia mode, you
have lost, sooner or later. BUT if your code runs in a sandbox like a
Tcl safe interpreter you may have a lot less damages.

Doing security right is hard..., Tcl makes some things much easier to
handle:

Tcl's exec for example is much nicer from a security perspective then
the 'system()' command in some other languages, as it _does not_ pass
its arguments to the system shell for expansion and substitution before
execution.

Tcl's safe interpreters allow you to strip all dangerous commands from
your interpreters if you have to let unexperienced web developers at the
code and provide clean security boundaries.

Tcl's encoding subsystem enables a web developer to worry less about
encoding troubles, no manual conversions needed in most cases and no way
to accidentially confuse byte vs. char, which can lead to buffer
overflows or other interesting things.

Tcl's excellent support for domain specific languages. Have a senior,
security aware developer create a DSL for your web app and let the less
experienced developers use the sandboxed, audited DSL for there needs.
With safe interpreters you can even force them to only use the DSL.

and so on...

Michael

Bruce Hartweg

unread,
Jul 19, 2006, 10:20:28 AM7/19/06
to

Gerald gave a nice list, but if you're talking user input and safety
you shouldn't call anything until you validate it
If the user is supposed to give you a number, use [string is] and/or
scan to make sure all you have is a number - not some injected code.

set age [scan %d $userInput]

now you can call anything you want (expr,eval,sql query, etc.) with
age and know you are safe from attack.

Bruce

tun...@yahoo.com

unread,
Jul 19, 2006, 10:43:40 AM7/19/06
to
Derek Fountain wrote:
>
> So [expr] introduces the sort of security risk I'm talking about, and
> it's not described as a risk in the documentation. Nor is it that common
> knowledge, at least among the presumably very knowledgable people who
> responded to my post (yourself excepted of course). [expr] is a very
> commonly used command. This worries me.

Derek,

You are simply wrong on assuming that people (at least the ones who
have responded here) are not familiar with intricacies of expr. For
one, as I said earlier in my first post, if you are expecting numerical
values and you are feeding them to expr, it is one of the basics of
programming that you need to make sure your input data is numerical.

Parsing numerical data from strings of various sorts (from user input,
files, databases, etc.) is commonly done in C, C++, Java, etc., and
with appropriate checks on the results before doing any arithmetic on
them. Tcl is no exception.

You mention this within the context of security risk/ hacking by users
who know both your internal variable names and Tcl. But what happens
for the majority of regular users who may type "adam" instead of 42.
Guess what, your application is going to throw an error, and good luck
if you have not accounted for it. I am just mentioning this to show
how common and fundamental a check this is.

Neil Madden

unread,
Jul 19, 2006, 11:14:33 AM7/19/06
to
Derek Fountain wrote:
[...]

>> 1) using [eval command $userdata]
>
> OK, I think we can assume that as soon as [eval] goes near user supplied
> data we have to be worried with Tcl, Perl or PHP. No problem there - the
> warning flag in a programmer's head should go up as soon as he types e,
> v, a and l....
>
>> 2) using [expr 5*$userdata]. Always put expressions in braces.
>> It is said over and over again, but people still fail to heed
>> the advice.
>
> ...but the above is a great example of what I was thinking of.
[...]

This isn't a separate type of error. [expr] is the [eval] of Tcl's
expression sub-language, just as [regexp] is the [eval] of the regular
expression language, [exec] is the [eval] of the underlying operating
system, and a db's query function is the [eval] of its query language
(e.g. SQL). You should be careful of quoting when calling any of these
sub-languages. This isn't unique to Tcl (e.g. SQL injection attacks are
common to all languages). The only thing that is unique to Tcl is that
it uses a sub-language for interpreting expressions.

-- Neil

Derek Fountain

unread,
Jul 19, 2006, 12:18:15 PM7/19/06
to
tun...@yahoo.com wrote:
> Derek Fountain wrote:
>> So [expr] introduces the sort of security risk I'm talking about, and
>> it's not described as a risk in the documentation. Nor is it that common
>> knowledge, at least among the presumably very knowledgable people who
>> responded to my post (yourself excepted of course). [expr] is a very
>> commonly used command. This worries me.
>
> Derek,
>
> You are simply wrong on assuming that people (at least the ones who
> have responded here) are not familiar with intricacies of expr.

You misunderstood my response. To clarify:

I originally suggested that there are dangers in writing web
applications in Tcl because Tcl has unique characteristics that mean a
bit of user supplied code can be executed by the application in ways
that other languages don't offer. Everyone, with the exception of Donald
Arseneau, immediately said that's not true. Donald pointed to an area
where there might be a risk, which I demonstrated with a proof of
concept, and which was further explored by Gerald Lester. It turns out
there are several places where this risk might catch the unwary - the
people who responded with "that's not true" were wrong. I wasn't
suggesting those people were not familiar with intricacies of expr, I
was suggesting they were unwary.

> one, as I said earlier in my first post, if you are expecting numerical
> values and you are feeding them to expr, it is one of the basics of
> programming that you need to make sure your input data is numerical.

In my example of numerical manipulation, yes. But as Gerald pointed out,
the problem is wider than that. It extends to anywhere where expr, if,
while and for are used, and presumably is a consideration for string
comparisons in those commands as well as numerical ones.

> Parsing numerical data from strings of various sorts (from user input,
> files, databases, etc.) is commonly done in C, C++, Java, etc., and
> with appropriate checks on the results before doing any arithmetic on
> them. Tcl is no exception.

Yes it /is/ an exception. Reread the proof of concept I posted and think
about it. In Perl and PHP there is no risk with not checking data you
just intend to compare against a value. If the user puts something bad
in there it won't get executed. With Tcl it might because expr et al
will do a command substitution with it.

That means if you want to do something basic like check the "yes"/"no"
value of a user supplied string, with Tcl you have to check it carefully
for potentially executable code (and you have to make that check without
using expr et al in case you accidentally execute the rogue code in the
process of sanitisation).

Checking user supplied values before you pass them off to SQL or the
operating system is something you do in all languages. Checking those
values before you even consider doing a value comparison in your
application code is, AFAICT, unique to Tcl.

> You mention this within the context of security risk/ hacking by users
> who know both your internal variable names and Tcl. But what happens
> for the majority of regular users who may type "adam" instead of 42.
> Guess what, your application is going to throw an error, and good luck
> if you have not accounted for it. I am just mentioning this to show
> how common and fundamental a check this is.

The above is so wrong it's almost not worth answering. But for those who
don't understand how web attackers work, including, evidentally,
yourself, I will point out that web attackers aren't "the majority of
regular users". Assuming an attacker won't be able to exploit this sort
of issue because they can't immediately see the application code, or
they might not know enough about Tcl, is just relying on security
through obscurity. It won't work.

Personally, I'm somewhat spooked by this. If I write a web application
in Tcl I'll have to carefully check every single value that the user
sends before I use it in a loop, pass it to expr or do pretty much
anything with it. I certainly wouldn't trust any library code with an
unchecked value. It's not just the SQL, eval, open and other such
function data that Tcl web developers need to worry about, it's
fundamental constructs of the language itself. That's enough of a worry
for me to conclude my work collegue was correct - I won't use Tcl for a
web application.

Don Porter

unread,
Jul 19, 2006, 12:40:20 PM7/19/06
to
Derek Fountain wrote:
> Personally, I'm somewhat spooked by this. If I write a web application
> in Tcl I'll have to carefully check every single value that the user
> sends before I use it in a loop, pass it to expr or do pretty much
> anything with it.

Um, or you could just brace your expressions.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Don Porter

unread,
Jul 19, 2006, 12:44:28 PM7/19/06
to
>> Personally, I'm somewhat spooked by this. If I write a web application
>> in Tcl I'll have to carefully check every single value that the user
>> sends before I use it in a loop, pass it to expr or do pretty much
>> anything with it.

> Um, or you could just brace your expressions.

And use a safe interpreter, so if you happen to miss any [expr]
bracing, the command substitution of potentially dangerous commands
in user input can't do any real harm.

Darren New

unread,
Jul 19, 2006, 12:57:58 PM7/19/06
to
Derek Fountain wrote:
> I don't think you can do that with Perl or PHP without using eval.

It's called a SQL Injection Attack, or a Cross-Site Scripting Attack,
depending on what it is you're breaking. You still have to watch for it
in all these languages, unless your libraries are sophisticated enough
to deal with it.

Simply check that a number is a number when input.

--
Darren New / San Diego, CA, USA (PST)
This octopus isn't tasty. Too many
tentacles, not enough chops.

tun...@yahoo.com

unread,
Jul 19, 2006, 1:32:17 PM7/19/06
to
Derek Fountain wrote:
> > Parsing numerical data from strings of various sorts (from user input,
> > files, databases, etc.) is commonly done in C, C++, Java, etc., and
> > with appropriate checks on the results before doing any arithmetic on
> > them. Tcl is no exception.
>
> Yes it /is/ an exception. Reread the proof of concept I posted and think
> about it. In Perl and PHP there is no risk with not checking data you
> just intend to compare against a value. If the user puts something bad
> in there it won't get executed. With Tcl it might because expr et al
> will do a command substitution with it.

Perhaps we are saying the same thing. There are things that are
potentially dangerous in Tcl, just like not properly releasing memory
in C/C++ or safeguarding against buffer overruns. Granted, this is not
something that a programmer should do or intends to do; but, in reality
happens quite often. So, your example of "[incr credits]" should cause
no problem. The programmer should always check that any user supplied
data is numerical before blindly giving it to expr (just like in any
language). Should this be documented in the man page for expr or in
college? Your call.


> That means if you want to do something basic like check the "yes"/"no"
> value of a user supplied string, with Tcl you have to check it carefully
> for potentially executable code

This is not true.

% package req Tk
% set user_data {[tk_messageBox -message DANGER!!!]}
% string equal $user_data "yes"
% string sompare $user_data "no"
% if {$user_data} {puts DANGER} else {puts OK}
% if {$user_data = "yes"} {puts DANGER} else {puts OK}

> Checking user supplied values before you pass them off to SQL or the
> operating system is something you do in all languages. Checking those
> values before you even consider doing a value comparison in your
> application code is, AFAICT, unique to Tcl.

See above.


>
> > You mention this within the context of security risk/ hacking by users
> > who know both your internal variable names and Tcl. But what happens
> > for the majority of regular users who may type "adam" instead of 42.
> > Guess what, your application is going to throw an error, and good luck
> > if you have not accounted for it. I am just mentioning this to show
> > how common and fundamental a check this is.
>
> The above is so wrong it's almost not worth answering.

Really? Are you suggesting that if I write a regular Tcl/Tk app, I
will not see the behavior that we are discussing? That it only occurs
in web applications? Have you heard of MVC model of development?
Have you heard of apps that are essentially the same back-end code
powering both Tk and web-enabled interfaces?

But for those who
> don't understand how web attackers work, including, evidentally,
> yourself, I will point out that web attackers aren't "the majority of
> regular users". Assuming an attacker won't be able to exploit this sort
> of issue because they can't immediately see the application code, or
> they might not know enough about Tcl, is just relying on security
> through obscurity. It won't work.

Weird. You are making unfounded assumptions and then taking them as
facts.

Joe English

unread,
Jul 19, 2006, 2:55:04 PM7/19/06
to
Derek Fountain wrote:
>
>I was in a debate with someone at work the other day regarding the
>suitability of certain languages for web application programming. Tcl
>wasn't a player in the debate, except for one throwaway comment where
>someone said he'd never use Tcl for a web application.
>
>Putting his argument in a Tcl context, what he was basically saying is
>that because of Tcl's recursive execution nature, you have to be very
>careful to check all user input, regardless of what you intend to do
>with it because with Tcl it might get evaluated. So, if someone
>supplies, say, a name that you're just planning on writing to a file or
>something, with Tcl you have to check that name data with as much
>paranoia as you would if they were supplying a filename you're about to
>act on.


It's not so much a matter of paranoia as it is making sure
that you only operate on data in ways that are consistent
with the type of the data. Treat text as text, numbers as
numbers, lists as lists, HTML as HTML, SQL scripts as SQL scripts,
Tcl code as Tcl code, and so forth. In particular: treat
user input as text, and *don't* treat text as a number,
a list, HTML, an SQL script, or Tcl code. Tcl is no different
than other languages in this regard.

Your colleague is correct in that, whereas badly-written code in
other common Web scripting languages are only susceptible to SQL
injection, cross-site scripting, and the like; badly-written Tcl
code is additionally susceptible to arbitrary execution attacks.
But the way to avoid those in Tcl is the same way you avoid
the other attacks: verify and transform user input before
operating on it.


>Not withstanding the fact that it's best to check everything, and some
>languages have other security related issues that TCL doesn't have, what
>are the potential errors peculiar to Tcl and its nature that a web
>developer might walk into and leave open a security hole?

The main ones I can think of are: [eval] (obviously!),
expr/if/while (perhaps not so obvious, but if you follow
the simple rule "Always Brace Your Exprs" you'll be OK),
and [exec] (also obvious, but Tcl's [exec] has the additional
problem that certain magic characters are unquotable).


--Joe English

Gerald W. Lester

unread,
Jul 19, 2006, 5:24:00 PM7/19/06
to
Derek Fountain wrote:
> ...

> Personally, I'm somewhat spooked by this. If I write a web application
> in Tcl I'll have to carefully check every single value that the user
> sends before I use it in a loop, pass it to expr or do pretty much
> anything with it. I certainly wouldn't trust any library code with an
> unchecked value. It's not just the SQL, eval, open and other such
> function data that Tcl web developers need to worry about, it's
> fundamental constructs of the language itself. That's enough of a worry
> for me to conclude my work collegue was correct - I won't use Tcl for a
> web application.

If this worries you then I **strongly** suggest that you do not write any
web application in ***any*** language!

All anyone said is that before using your data, check it to make sure it is
an integer, real, etc...

You do this in Java/C when you convert it from a string to an integer. If it
fails an error is raised that you should deal with in a nice way.

If you are unwilling to do the required checks and associated handling,
don't do web application programming.

BTW, at least one well know web application is done in Tcl -- it is called AOL.

Darren New

unread,
Jul 19, 2006, 7:02:56 PM7/19/06
to
Derek Fountain wrote:
> In my example of numerical manipulation, yes. But as Gerald pointed out,
> the problem is wider than that. It extends to anywhere where expr, if,
> while and for are used,

No. Only where such are used without braces.

set x {[puts hello]}
if {$x == 123} {puts yes} {puts no}
set y [expr {$x + 12}]

Note the lack of "hello" in the output.

Now if you say
if "$x == 123" {...}
then sure, it's going to parse $x. But that's what you asked for.

> and presumably is a consideration for string
> comparisons in those commands as well as numerical ones.

Um, no. Indeed, Tcl is better at this than many other languages that
will substitue value multiple times without being asked. Try sometime
to use bash to deal with a directory full of files with arbitrary
characters in the names.

> That means if you want to do something basic like check the "yes"/"no"
> value of a user supplied string, with Tcl you have to check it carefully
> for potentially executable code (and you have to make that check without
> using expr et al in case you accidentally execute the rogue code in the
> process of sanitisation).

Not at all.
if {$x == "yes"} {...}
will *not* evaluate $x in the way you fear. That's what the braces are for.

Donald Arseneau

unread,
Jul 19, 2006, 7:10:14 PM7/19/06
to
Derek Fountain <nom...@hursley.ibm.com> writes:

> about it. In Perl and PHP there is no risk with not checking data you just
> intend to compare against a value. If the user puts something bad in there it
> won't get executed.

> Checking user supplied values before you pass them off to SQL or the


> operating system is something you do in all languages. Checking those values
> before you even consider doing a value comparison in your application code
> is, AFAICT, unique to Tcl.

Not at all! Any of the typed languages (C++, Java, ...) must perform
type validation before they can perform a numerical comparison. The
various "scan" variants (sscanf..) include type specifiers, and you
have to scan-convert the data before using it in comparisons. So?
Do the same in Tcl.


> > You mention this within the context of security risk/ hacking by users
> > who know both your internal variable names and Tcl. But what happens
> > for the majority of regular users who may type "adam" instead of 42.
> > Guess what, your application is going to throw an error, and good luck
> > if you have not accounted for it. I am just mentioning this to show
> > how common and fundamental a check this is.
>
> The above is so wrong it's almost not worth answering.

You missed the point, which was not arguing security through obscurity,
but that checking input data for validity should be universal, even
if there are no attackers on the web, and even for applications that
run securely and locally.

> I'll have to carefully check every single value that the user sends before I
> use it in a loop, pass it to expr or do pretty much anything with it.

You should validate user input before using it, in any situation and
in any language.

If you can't trust yourself to follow a few good practices, run the
app in a safe interp. Poof! You're safe.

In summary, _any_one_ of these will protect you. It isn't hard to do all
three:

1) validate user input
2) brace numeric expressions (including conditionals); avoid eval.
3) run in a safe interp

1&2 are just normal good programming, so they should be habitual.

--
Donald Arseneau as...@triumf.ca

Donald Arseneau

unread,
Jul 19, 2006, 7:21:29 PM7/19/06
to
Derek Fountain <nom...@hursley.ibm.com> writes:

> Nor is it that common knowledge, at least among the presumably
> very knowledgable people who responded to my post (yourself excepted

No, it is quite common knowledge. I was just listing the two cases
where unintended eval might crop up, with what to do to avoid them.
Plus a third case (intended eval), more tongue-in-cheek.

--
Donald Arseneau as...@triumf.ca

Derek Fountain

unread,
Jul 20, 2006, 5:53:35 AM7/20/06
to
Joe English wrote:
> Your colleague is correct in that, whereas badly-written code in
> other common Web scripting languages are only susceptible to SQL
> injection, cross-site scripting, and the like; badly-written Tcl
> code is additionally susceptible to arbitrary execution attacks.

Well, thanks for acknowledging that there is a problem worth
considering, Joe. Everyone else skipped that part and went straight to
the "it's the same for any language, you just have to get it right" bit.
I was starting to wonder if I was being overly paranoid. :o)

> It's not so much a matter of paranoia as it is making sure
> that you only operate on data in ways that are consistent
> with the type of the data. Treat text as text, numbers as
> numbers, lists as lists, HTML as HTML, SQL scripts as SQL scripts,
> Tcl code as Tcl code, and so forth. In particular: treat
> user input as text,

I'm starting to feel like I'm banging my head against a wall, so, one
last go at getting my point across, this time with code. :o)

If you make the rather simple mistake of not bracing your expr
arguments, which as Donald pointed out earlier in the thread, "It is
said over and over again, but people still fail to heed the advice,"
treating user input as a string is dangerous in Tcl. Here's an example
Tcl CGI script, which I don't think is too contrived. I was going to put
it on my website for folks to play with, but having played with it
myself I daren't:

---------------------
#!/usr/bin/tclsh

puts "Content-Type: text/html\n\n<HTML><HEAD>\n"

if { [info exists env(REQUEST_METHOD)] &&
$env(REQUEST_METHOD) eq "POST" &&
[info exists env(QUERY_STRING)]} {

set query [read stdin $env(CONTENT_LENGTH)]
if { [regexp {check=(.*)} $query unused flagValue] } {

set flagOn [expr $flagValue eq "on"]
if { $flagOn } {
puts "You switched it on"
}
} else {
puts "You left it off"
}

} else {

puts {
<form action="/cgi-bin/ex.cgi" method="post">
<input type="checkbox" name="check" checked/>
<input type="submit" value="submit"/>
</form>

}
}

puts "</HEAD></HTML>"
---------------------

Copy that into your localhost CGI directory as ex.cgi and run it from
your browser - the "application" just tells you if you've left the
checkbox on or off. Apart from missing the braces on the expr, this
script looks reasonable to me. I haven't treated the input as a number
or any other data type without checking its format. I've just checked
the value of a string, as a string, to see if it's the expected string a
browser will send me.

Now fire up LiveHTTPHeaders, or whatever else you use to change POST
data, and try setting the check value to something nasty:

check=[set h [open "/etc/passwd" "r"]; while {[gets $h l] >= 0} { puts $l }]

(That's one string in case it wraps.)

There's the password file in the browser. Using a safe interpreter would
prevent that sort of OS level exploit, but it still leaves the
application wide open to having hostile code executed in its
environment. [info] works from safe interpreters, so an attacker will
have no problem exploring the application code.

So, when using Tcl for web applications, it's vital you don't forget to
brace your exprs. Including the "hidden" instances of expr. And the ones
in the library code you didn't write and haven't looked at. If you miss
one you have a remote code execution exploit.

Maybe it's still just me, but I do find that worrying.

Neil Madden

unread,
Jul 20, 2006, 7:00:08 AM7/20/06
to
Derek Fountain wrote:
[...]

>
> So, when using Tcl for web applications, it's vital you don't forget to
> brace your exprs. Including the "hidden" instances of expr. And the ones
> in the library code you didn't write and haven't looked at. If you miss
> one you have a remote code execution exploit.
>
> Maybe it's still just me, but I do find that worrying.

Well, your example would be easily prevented by use of a safe
interpreter as pointed out several times already in this thread. This is
the Principle of Least Authority (POLA)[1]: if your cgi doesn't need
access to /etc/passwd then don't give it such access. The problem you
describe is indeed real, but its costs are more than made up for by the
fact that you can nail down security in Tcl much more than in many other
languages. If you still worry about unbraced exprs then there are a
number of static checkers that will warn of exactly this problem.

[1] See http://www.erights.org/

-- Neil

Derek Fountain

unread,
Jul 20, 2006, 8:39:54 AM7/20/06
to
Neil Madden wrote:
> Derek Fountain wrote:
> [...]
>>
>> So, when using Tcl for web applications, it's vital you don't forget
>> to brace your exprs. Including the "hidden" instances of expr. And the
>> ones in the library code you didn't write and haven't looked at. If
>> you miss one you have a remote code execution exploit.
>>
>> Maybe it's still just me, but I do find that worrying.
>
> Well, your example would be easily prevented by use of a safe
> interpreter as pointed out several times already in this thread.

Yes, I know. I got that part of the message, believe me. :o) The point I
was struggling to get across is that only one of these is a potential
remote code execution vulnerability:

perl: if( $check eq "checked" ) {...
PHP: if( $check == 'checked' ) {...
Tcl: if { [expr $check eq "checked"] } {...

The fact that doing it right means there's no problem isn't in dispute.
My problem is that doing it wrong is very easy, hard to identify as a
serious vulnerability, and not an issue in other languages.

But I think I've now made my point, so I'll stop banging on about it. :o)

tun...@yahoo.com

unread,
Jul 20, 2006, 9:13:57 AM7/20/06
to

Derek Fountain wrote:
> The point I
> was struggling to get across is that only one of these is a potential
> remote code execution vulnerability:
>
> perl: if( $check eq "checked" ) {...
> PHP: if( $check == 'checked' ) {...
> Tcl: if { [expr $check eq "checked"] } {...
>


In all fairness, this is like comparing oranges and apples. Perl and
PHP examples compare two values, the Tcl one *evaluates* the arguments,
and compares them, as requested by the programmer. (This fact about
expr is one of the few rules in Tcl.) If you are comfortable with PHP
way of writing it, why would you not do the same in Tcl?

I guess I am not asking, just making an observation, because the other
languages have constructs similar to expr too that when used, would
cause the same trouble.

Kaitzschu

unread,
Jul 20, 2006, 9:23:38 AM7/20/06
to
On Thu, 20 Jul 2006, Derek Fountain wrote:

> Tcl: if { [expr $check eq "checked"] } {...

You wouldn't do this, you would do
if {$check eq "checked"} {...
because if evaluates expression. And hey, now expression is braced, so you
are safe. Your example is an example of double-evaluation.

--
-Kaitzschu
s="TCL ";while true;do echo -en "\r$s";s=${s:1:${#s}}${s:0:1};sleep .1;done

Derek Fountain

unread,
Jul 20, 2006, 10:18:53 AM7/20/06
to
Kaitzschu wrote:
> On Thu, 20 Jul 2006, Derek Fountain wrote:
>
>> Tcl: if { [expr $check eq "checked"] } {...
>
> You wouldn't do this, you would do
> if {$check eq "checked"} {...
> because if evaluates expression. And hey, now expression is braced, so
> you are safe. Your example is an example of double-evaluation.

Sigh. Those of you who just want to shoot down my intentionally simple,
somewhat contrived, demonstration and proof of concept code continue to
miss the point. Or you're deliberately avoiding seeing the point.

The point is demonstrated by the correctly coded CGI example I posted
eariler today. I note neither you nor tunity5 stepped in to shoot at
that one.

MartinLemburg@UGS

unread,
Jul 20, 2006, 10:46:18 AM7/20/06
to
Hello,

I really agree with Derek.

Such things like this ...

> >> Tcl: if { [expr $check eq "checked"] } {...

..., I've seen so often!

Tcl provides some pitfalls and there always some developers forgetting
all the tips, tricks and hints, the Do's and Don't's ... .
So a bit paranoia is good to have as developer to be sure to exclude
those pitfalls.

And validating all the user inputs for having the right type or
structure helps a lot not to go nuts with this paranoia. So working on
the one side helps the other.

Best regards,

Martin

tun...@yahoo.com

unread,
Jul 20, 2006, 11:00:56 AM7/20/06
to


I thought we did. In your CGI example, you have this statement:

set flagOn [expr $flagValue eq "on"]


And in your "intentionally simple" example, you have this, which we
covered:

if { [expr $check eq "checked"] } {...


Are you saying that these two statements are not the same? What is the
difference? Use the recommended form instead of the above statement
(which is really the equivalent of what you are doing in Perl/PHP), and
see if you have the same error. (Perhaps I assumed you knew Tcl; it
would explain a lot if that is not the case; which is fine as I mean it
in a neutral way, not to be misinterpreted.)


I don't think anybody is trying to shootdown your argument. It is just
that, the same vulnerability exists in every language from C to SQL,
and Tcl happens to have several, and arguably more advanced mechanisms
to deal with it.

Derek Fountain

unread,
Jul 20, 2006, 11:23:21 AM7/20/06
to
> I thought we did. In your CGI example, you have this statement:
>
> set flagOn [expr $flagValue eq "on"]
>
>
> And in your "intentionally simple" example, you have this, which we
> covered:
>
> if { [expr $check eq "checked"] } {...
>
>
> Are you saying that these two statements are not the same? What is the
> difference?

They are not the same. The difference is that I use the first construct
all the time[*] - storing the boolean result of an expression for later
use. The second is incorrect (dual expression evaluation) and I've
probably not used that since I was a Tcl-newbie (about 10 years ago). I
only put it in my post to make the similarity with the PHP and Perl
equvialents apparent, but as has been pointed out, other, less
experienced people /do/ do it.

[*] I like to think I put braces in there each and every time, but I
know I probably miss them occasionally.

> I don't think anybody is trying to shootdown your argument. It is just
> that, the same vulnerability exists in every language from C to SQL,
> and Tcl happens to have several, and arguably more advanced mechanisms
> to deal with it.

OK, convince me. How do you compare one user-entered string value with
another hard coded string value, in Perl or PHP, such that if there is
Perl or PHP code in the user supplied value, it gets executed? The only
way that I know of is to use the language's eval function to wrap the
user-entered string on one side of the comparison, which makes no sense
in the script, and would be completely obvious if someone were to type
it. Is there another, more subtle way that I don't know of?

tun...@yahoo.com

unread,
Jul 20, 2006, 11:48:07 AM7/20/06
to
Derek Fountain wrote:
> > I thought we did. In your CGI example, you have this statement:
> >
> > set flagOn [expr $flagValue eq "on"]
> >
> >
> > And in your "intentionally simple" example, you have this, which we
> > covered:
> >
> > if { [expr $check eq "checked"] } {...
> >
> >
> > Are you saying that these two statements are not the same? What is the
> > difference?
>
> They are not the same.

Yes they are.

Try this:

% package req Tk
% set user_data {[tk_messageBox -message DANGER!!!]}

% set flagOn [expr $user_data eq "on"]
% if {[expr $user_data eq "on"]} {puts "Did you see the message box?"}

Both cases make use of expr incorrectly and the message box pops up.

> OK, convince me. How do you compare one user-entered string value with
> another hard coded string value, in Perl or PHP,


Use "string equal", "string compare", etc., or just use straight
comparisons. Notice no pop ups:

% set flagOn [string equal $user_data "on"]

% set flagOn [string compare $user_data "on"]

% if {[string equal $user_data "on"]} {....

% if {$user_data == "on"} {....

> such that if there is
> Perl or PHP code in the user supplied value, it gets executed?

This perception means that one cannot write a code editor in Tcl; since
any code written by the user will get executed right away instead of
being treated as data (i.e., lines of user code). This is of course
not accurate. One of the first GUI editors for TK was written in
Tcl/TK more than a decade ago. (Sorry, the name escapes me now.)

Kaitzschu

unread,
Jul 20, 2006, 12:29:13 PM7/20/06
to
On Thu, 20 Jul 2006, Derek Fountain wrote:

> Kaitzschu wrote:
>> On Thu, 20 Jul 2006, Derek Fountain wrote:
>>
>>> Tcl: if { [expr $check eq "checked"] } {...
>>
>> You wouldn't do this, you would do
>> if {$check eq "checked"} {...
>> because if evaluates expression. And hey, now expression is braced, so
>> you are safe. Your example is an example of double-evaluation.
>
> Sigh. Those of you who just want to shoot down my intentionally simple,
> somewhat contrived, demonstration and proof of concept code continue to
> miss the point. Or you're deliberately avoiding seeing the point.

I see your point. Your point is "you can write bad code". Just don't write
bad code and be fine.

There is no difference between "you can write bad code" and "you can write
bad code with more commands", it still is just writing bad code. So far
your proof of concepts haven't really convinced me and I wrote my followup
simply because your two first examples used single-evaluation and Tcl one
had _asked for_ double-evaluation, so examples weren't the same.

> The point is demonstrated by the correctly coded CGI example I posted
> eariler today. I note neither you nor tunity5 stepped in to shoot at
> that one.

That had been already dealt with, apparently in vain, and I don't believe
that repeating is the key in learning (I believe repeating is the key to
boredom; coincidentally, sometimes boredom is the key to learning).

If you want deliberately write bad code and not be hurt for doing it,
write you CGI in Ada :) True paranoic doesn't use third party libraries.

Fredderic

unread,
Jul 20, 2006, 12:33:39 PM7/20/06
to
On Thu, 20 Jul 2006 16:23:21 +0100,
Derek Fountain <nom...@hursley.ibm.com> wrote:

I'm sorry, but this is getting bloody ridiculous.


> > set flagOn [expr $flagValue eq "on"]

> > if { [expr $check eq "checked"] } {...
> > Are you saying that these two statements are not the same? What is
> > the difference?
> They are not the same.

You, mate, are an idiot. But we'll ignore that for the time being.

[expr $flagValue eq "on"] vs. [expr $check eq "checked"]

Now, where's the difference? Validate the values before you use them
ALWAYS, and there's no problem. Brace the values in an [expr] ALWAYS,
and there's no problem. In an [if], [while], etc., use {}'s around the
condition, ALWAYS, and there's no problem. Don't double-evaluate your
expressions unless you know EXACTLY what you're doing, and there's no
problem. Applying ANY one of those to every one of your examples,
renders them totally inert.

set flagOn [expr {$flagValue eq "on"}]

if { [expr {$check eq "checked"}] } {...

Both of them are now safe with a simple set of braces. PLUS, they're
even faster, to boot. Two bonuses for the price of one braincell.


In the case of you and your friend; simply don't write code which goes
anywhere near untrusted input until you get a clue, and there's no
problem. End of story. This bullshit argument should have ended about
20 posts ago. I repeat, so you can understand what I'm saying here; if
you don't understand the language, get someone who does to do the
user-side work, or at least check what you've done.


> The difference is that I use the first construct all the time[*] -
> storing the boolean result of an expression for later use. The second
> is incorrect (dual expression evaluation) and I've probably not used
> that since I was a Tcl-newbie (about 10 years ago).

There's really nothing to it. If you don't know what you're doing,
then don't do it. Simple. And stop being a dickhead by persisting
with your bullshit whining. How many times do you need to be told?
Piss off and let the people who have a clue, get on with helping those
who actually want one.


> I only put it in my post to make the similarity with the PHP and Perl
> equvialents apparent, but as has been pointed out, other, less
> experienced people /do/ do it.

No, you put it in there to highlight a bogus argument. Your TCL
example was nothing at all alike the other two; even as a greenhorn
when I first started using TCL, I'd never have been that stupid as to
put an [expr] in the midst of an [if] like that. Yes, I used [expr] as
one side of an equivalence, but not as the whole expression. Anyone a
company allows anywhere near a programming language should immediately
see that SOMETHING is wrong with that, surely! And no, at first I
didn't originally know about bracing my [expr] expressions. Which is
why the people I was writing scripts for didn't let me anywhere near
the important stuff until I'd gotten recognition off a few who DID know
what they were doing.

And if you can't do that, and even if you can, have a testing plan in
place to check for stupid security fubar's. No programmer worth their
weight in your arguing skills (which is to say stuff-all) puts a
companies trust entirely in the correctness of the programming language
they're using. If it's an important piece of the system in a vulnerable
position, then you back it up with security behind it, in front of it,
within it, and around it, and when you're done doing all that, then you
test it, audit it, and test it some more. THEN, you put it online.
You only relax some if it's not critical to your lively hood, but they
you're making a judgement about just how important you consider your
security, vs. how lazy you wish to be, and you wear the consequences.

But you don't throw around garbage to make it look like your argument
is valid, when all you're doing is demonstrating a fact that everyone
already knows; that ANY tool, in ANY occupation can be misused by
someone of sufficient cluelessness. I wouldn't leave a 2 month old
child alone unattended with a bamboo skewer, in case they shove it up
their nose or poke their eye out. So don't let someone who doesn't
know how to brace their TCL expressions near your web front.


> [*] I like to think I put braces in there each and every time, but I
> know I probably miss them occasionally.

So does everyone else. Live with it. I like to think that I
check ever C character array to make sure there'll be no buffer
over-runs, but I probably miss them occasionally too. I just make damn
bloody sure that I've checked and re-checked every single one that
involves user input, and then if I'm even the slightest bit uncertain,
I'll ask a friend or co-worker to proof-read it just to be sure.

Web-fronts are a dangerous place. If you're writing one, then it's up
to you to write it in a language you are decently competent with, or
have someone else build sufficient fences around it that it doesn't
matter. Either way, someone at some point has to know what they're
doing, or your company is going to be in for a really bad day. Don't
blame the tool. If you can't handle it, don't use it.


> > I don't think anybody is trying to shootdown your argument. It is
> > just that, the same vulnerability exists in every language from C
> > to SQL, and Tcl happens to have several, and arguably more advanced
> > mechanisms to deal with it.
> OK, convince me. How do you compare one user-entered string value
> with another hard coded string value, in Perl or PHP, such that if
> there is Perl or PHP code in the user supplied value, it gets
> executed? The only way that I know of is to use the language's eval
> function to wrap the user-entered string on one side of the
> comparison, which makes no sense in the script, and would be
> completely obvious if someone were to type it. Is there another, more
> subtle way that I don't know of?

That happens to be EXACTLY what you did in your contrived "TCL is more
dangerous than PHP and Perl" examples. I handed those three examples
off to someone who didn't even know TCL existed, and they saw the
mistake!


There. That's what I've thought of this entire discussion from about
the fifth post onwards. Derek, you're an idiot. Simple as that. Come
back when you're willing to get a clue. Bye now. Ta ta! (Wonders off
ranting and raving, heard muttering into the distance something about
"some people are just .......") (Actually, that was kinda fun... Bit
of a stress relief really. No wonder flame wars go on for so long...
It really does help one's overall demeanour to just let it all out!)
Hope no one (with the obvious potential exception of the OP) was
offended by any of that. Really. Just trying to put things in
perspective. :)


Fredderic

Neil Madden

unread,
Jul 20, 2006, 1:20:33 PM7/20/06
to
Derek Fountain wrote:
> Neil Madden wrote:
>
>> Derek Fountain wrote:
>> [...]
>>
>>>
>>> So, when using Tcl for web applications, it's vital you don't forget
>>> to brace your exprs. Including the "hidden" instances of expr. And
>>> the ones in the library code you didn't write and haven't looked at.
>>> If you miss one you have a remote code execution exploit.
>>>
>>> Maybe it's still just me, but I do find that worrying.
>>
>>
>> Well, your example would be easily prevented by use of a safe
>> interpreter as pointed out several times already in this thread.
>
>
> Yes, I know. I got that part of the message, believe me. :o) The point I
> was struggling to get across is that only one of these is a potential
> remote code execution vulnerability:
>
> perl: if( $check eq "checked" ) {...
> PHP: if( $check == 'checked' ) {...
> Tcl: if { [expr $check eq "checked"] } {...

OK. I think we can agree that Tcl delegating expression evaluation to a
little-language (expr) results in one more (unexpected to the beginner)
round of evaluation than most other languages, and that this can (if you
don't remember to quote your arguments) lead to a potential exploit.
That *is* a fair point, and I'm not disputing it. The counter-point is
merely that to abandon Tcl as a language for web apps because of this
seems somewhat extreme, as Tcl has plenty of other safety features that
make up for this, and which many other languages lack.

>
> The fact that doing it right means there's no problem isn't in dispute.
> My problem is that doing it wrong is very easy, hard to identify as a
> serious vulnerability, and not an issue in other languages.

All true, alas. It's one extra thing to check (e.g., by running a static
checker). I think Tcl redeems itself by having many other things which
you don't have to check (e.g. buffer overflows). I wouldn't trust many
other languages as much as I trust Tcl. E-lang (referenced before)
possibly. Haskell might also work quite well with a RESTful app.

Cheers,

Neil

PS. Hope things are going well at Hursley. I was first introduced to Tcl
there as a PUE in 1999.

Eckhard Lehmann

unread,
Jul 20, 2006, 1:47:13 PM7/20/06
to

tun...@yahoo.com wrote:
> >
> > perl: if( $check eq "checked" ) {...
> > PHP: if( $check == 'checked' ) {...
> > Tcl: if { [expr $check eq "checked"] } {...
> >
>
>
> In all fairness, this is like comparing oranges and apples. Perl and
> PHP examples compare two values, the Tcl one *evaluates* the arguments,

I don't want to be subtle here, but you can leave [expr] out for [if]
comparisons:


if {$check eq "checked"} {...}

Perl, PHP and so on evaluate this expression into a boolean result as
well - same as with Tcl.

Eckhard

David N. Welton

unread,
Jul 20, 2006, 6:18:15 PM7/20/06
to
Derek Fountain wrote:

> Sigh. Those of you who just want to shoot down my intentionally simple,
> somewhat contrived, demonstration and proof of concept code continue to
> miss the point. Or you're deliberately avoiding seeing the point.

You can come up with similar types of contrived examples showing that
any language is a bad idea for some reason or another.

--
David N. Welton
- http://www.dedasys.com/davidw/

Linux, Open Source Consulting
- http://www.dedasys.com/

David N. Welton

unread,
Jul 20, 2006, 6:23:03 PM7/20/06
to
Neil Madden wrote:

> OK. I think we can agree that Tcl delegating expression evaluation to a
> little-language (expr) results in one more (unexpected to the beginner)
> round of evaluation than most other languages, and that this can (if you
> don't remember to quote your arguments) lead to a potential exploit.
> That *is* a fair point, and I'm not disputing it. The counter-point is
> merely that to abandon Tcl as a language for web apps because of this
> seems somewhat extreme, as Tcl has plenty of other safety features that
> make up for this, and which many other languages lack.

Exactly - people are still using PHP stuff out there where http GET
parameters are automagically created as PHP variables.

Derek Fountain

unread,
Jul 21, 2006, 2:56:59 AM7/21/06
to
> OK. I think we can agree that Tcl delegating expression evaluation to a
> little-language (expr) results in one more (unexpected to the beginner)
> round of evaluation than most other languages, and that this can (if you
> don't remember to quote your arguments) lead to a potential exploit.
> That *is* a fair point, and I'm not disputing it.

Since others are becoming offensive and starting to sling insults, I'll
back out of the thread about now. But at least one person understands
what I'm getting at. :o)

> The counter-point is
> merely that to abandon Tcl as a language for web apps because of this
> seems somewhat extreme, as Tcl has plenty of other safety features that
> make up for this, and which many other languages lack.

Well, maybe. I've spent a good part of the last 5 years working as a
penetration tester, so I think I've become a little paranoid and suspicious.

To me, this issue is a glaring hole. I think the odds are high that the
first time I have to attack a web application written in Tcl I'll be
able to use this to break into the application, and probably the server.
Complex web apps typically take hundreds to user inputs and I think it's
odds-on that a Tcl programmer, especially an inexperienced one, will
miss braces at least once.

I have plenty of attack code, some of it written in Tcl, ironically,
that enumerates web application inputs and presents them with hostile
inputs. One more string to my bow...

> PS. Hope things are going well at Hursley. I was first introduced to Tcl
> there as a PUE in 1999.

Wasn't by Paul Duffin was it? :o) Things are good. Busy as ever...

Michael Schlenker

unread,
Jul 21, 2006, 3:31:39 AM7/21/06
to
Derek Fountain schrieb:

>> OK. I think we can agree that Tcl delegating expression evaluation to
>> a little-language (expr) results in one more (unexpected to the
>> beginner) round of evaluation than most other languages, and that this
>> can (if you don't remember to quote your arguments) lead to a
>> potential exploit. That *is* a fair point, and I'm not disputing it.
>
> Since others are becoming offensive and starting to sling insults, I'll
> back out of the thread about now. But at least one person understands
> what I'm getting at. :o)

expr as a potential attack vector for remote code execution, simply a
fact, yes.

>
>> The counter-point is merely that to abandon Tcl as a language for web
>> apps because of this seems somewhat extreme, as Tcl has plenty of
>> other safety features that make up for this, and which many other
>> languages lack.
>
> Well, maybe. I've spent a good part of the last 5 years working as a
> penetration tester, so I think I've become a little paranoid and
> suspicious.

Isn't a little paranoia a job requirement for security related jobs? ;-)


>
> To me, this issue is a glaring hole. I think the odds are high that the
> first time I have to attack a web application written in Tcl I'll be
> able to use this to break into the application, and probably the server.
> Complex web apps typically take hundreds to user inputs and I think it's
> odds-on that a Tcl programmer, especially an inexperienced one, will
> miss braces at least once.

I agree that if one such hole is found and no mitigating measures like
safe interpreters are in place the effects are disastrous, especially
due to the good introspection facilities provided by Tcl.

Your right that beginning Tcl users often use the useless
if {[expr $a == $b]} {}
which is dangerous..., have seen it in enough code.

So this has to be put up high on the scale of important topics for code
review, when inspecting a web application written in Tcl. But its
actually rather easy to look for this kind of mistakes, as all the
static syntax checkers for Tcl that i know of warn if they encounter
unbraced expressions.

A rather simple fix for most of those problems for web apps would be to
use something like this in their startup code (probably in the
application namespace as overwriting expr globally could have unintended
consequences)

rename expr ::tcl::expr
proc expr {exp} {
uplevel 1 [list ::tcl::expr $exp]
}

Michael

Ralf Fassel

unread,
Jul 21, 2006, 5:38:05 AM7/21/06
to
* Fredderic <put_my_n...@optusnet.com.au>

| You, mate, are an idiot. But we'll ignore that for the time being.

Please keep that kind of 'arguments' out of c.l.t.
Thank you.

| set flagOn [expr {$flagValue eq "on"}]
| if { [expr {$check eq "checked"}] } {...
|
| Both of them are now safe with a simple set of braces. PLUS, they're
| even faster, to boot.

The most easy way in _this_ special case is not to use 'expr' etc at
all, but simply use 'flagvalue' or 'check' directly. They are
supposed to be booleans, so use them as booleans:

if {$check} {...}
if {$flagValue} {...}

If the malicious user supplies non-boolean values for a flag, he will
get told so by the TCL error mechanism.

R'

Ralf Fassel

unread,
Jul 21, 2006, 5:46:24 AM7/21/06
to
* "David N. Welton" <dav...@dedasys.com>

| > Sigh. Those of you who just want to shoot down my intentionally
| > simple, somewhat contrived, demonstration and proof of concept code
| > continue to miss the point. Or you're deliberately avoiding seeing
| > the point.
|
| You can come up with similar types of contrived examples showing
| that any language is a bad idea for some reason or another.

I've seen too many unbraced 'expr' in TCL code to deny that Derek has
a point here. Unbraced 'expr' is bad TCL code that is very (?)
widespread.

http://wiki.tcl.tk/3538
http://wiki.tcl.tk/16154

R'

Kaitzschu

unread,
Jul 21, 2006, 6:52:56 AM7/21/06
to
On Fri, 21 Jul 2006, Ralf Fassel wrote:

> I've seen too many unbraced 'expr' in TCL code to deny that Derek has a
> point here. Unbraced 'expr' is bad TCL code that is very (?)
> widespread.
>
> http://wiki.tcl.tk/3538
> http://wiki.tcl.tk/16154

And in 8.5 HEAD, in library/clock.tcl ::tcl::clock::add there is
if { [catch { expr wide($clockval) } result] } {
that is very much exploitable. The funny part here is that this kind of
code is supposed to detect these kinds of mistakes :)

But I still say this is an example of bad code, but I must admit, that it
indeed is widespread. Even my own sources have it, but, naturally, to do
calculus with variable operators.

I must apologise in case my earlier postings concerning this subject were
two of those that were of insulting nature.

David N. Welton

unread,
Jul 21, 2006, 7:09:20 AM7/21/06
to
[ You know, the real danger of writing web apps in Tcl is that Tcl is
not very popular, but that's another story. ]

The real solution to this problem, IMO, is to create something that
checks your arguments. It's pretty easy in Tcl.

proc validate_args {args} {
foreach {val type onerror} $args {
if $val is not $type, eval $onerror
... or something like that ...
}
}

There you go... that should fix most of the problems, and could be
extended to do regexps, and all kinds of other fancy things to eliminate
nasty code.

Cameron Laird

unread,
Jul 21, 2006, 8:43:56 AM7/21/06
to
In article <YmJvg.42267$sz1....@newsfe6-gui.ntli.net>,

I'm sympathetic to Derek's explanations. I think he's right
about a proposition which I'll try to express in my own words:
even moderately-experienced Tcl developers can create an appli-
cation which seems to behave as intended for common data, but
is hazardous in general. This has nothing to do with Webbish-
ness, by the way. The contrast is with, say, Java, where it's
hard enough just getting things working at all. Java's common
hazards in this sense--exec() and such--are more "discrete".

There *is* something going on with Tcl; think how often naive
users apply list commands to non-list data.

All languages possess frequently-made mistakes. Tcl is power-
ful enough that its hazards can be more dramatic than those
common in other languages. I don't think that disqualifies
Tcl; its charms and advantages are also dramatically effective.

Gerald W. Lester

unread,
Jul 21, 2006, 9:18:30 AM7/21/06
to
Derek Fountain wrote:
>...

> Well, maybe. I've spent a good part of the last 5 years working as a
> penetration tester, so I think I've become a little paranoid and
> suspicious.
>
> To me, this issue is a glaring hole. I think the odds are high that the
> first time I have to attack a web application written in Tcl I'll be
> able to use this to break into the application, and probably the server.
>...

Can I take you up on that one in the future and let you try to attack one of
mine that I'm doing?

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

Glenn Jackman

unread,
Jul 21, 2006, 9:18:57 AM7/21/06
to
At 2006-07-20 01:20PM, Neil Madden <n...@cs.nott.ac.uk> wrote:
> Derek Fountain wrote:
> > The fact that doing it right means there's no problem isn't in dispute.
> > My problem is that doing it wrong is very easy, hard to identify as a
> > serious vulnerability, and not an issue in other languages.
>
> All true, alas. It's one extra thing to check (e.g., by running a static
> checker).

In fact, the Komodo editor highlights non-braced expressions as a
warning: "use curly braces to avoid double substitution"

--
Glenn Jackman
Ulterior Designer

Derek Fountain

unread,
Jul 21, 2006, 10:03:53 AM7/21/06
to
>> To me, this issue is a glaring hole. I think the odds are high that
>> the first time I have to attack a web application written in Tcl I'll
>> be able to use this to break into the application, and probably the
>> server. ...
>
> Can I take you up on that one in the future and let you try to attack
> one of mine that I'm doing?

Yes, certainly. Google for my name to find my direct contact details.

Derek Fountain

unread,
Jul 21, 2006, 11:41:01 AM7/21/06
to
> There *is* something going on with Tcl; think how often naive
> users apply list commands to non-list data.

I still have a suspicion that there's something more going on with Tcl
web applications than is apparent at first glance. My original question
asked whether Tcl's recursive execution nature caused problems with
applications that run in a web (or other hostile) environment. The
thread rapidly wandered off to explore the behaviour of one particular
function, expr, but I can't help thinking there's a little more to worry
about.

I share concerns with David Wheeler, as discussed in his secure
programming HOWTO:

http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/tcl.html

A not-very-contrived example he uses is this:

after 1000 "someCommand someparam $param1"

where param1 is a string given by the user. I know building commands
like that is wrong (David explains in the document how to do it properly
using [list]) but we've all done it. The inexperienced amongst us
probably still haven't fully understood the implications of it and
therefore still do it.

That example, I think, sums up where Tcl's dynamic nature is my greatest
concern. Building bits of code on the fly to use as callbacks, etc., is
something we do in Tcl all the time, much more so than any other
language. Tcl's 'eval' is much more commonly used than Perl's or PHP's
because of it's useful "break up a variable" effect. You only need to
take your eye off the ball once and let a bit of unsantised user input
into such a structure...

Getting it wrong in Perl or PHP is easy - careless use of eval or not
checking values before passing them to SQL happens when you're not
paying attention. With Tcl you have those problems, plus the very much
more subtle ones presented by the language's dynamic nature. I guess
that's the succinct description of my concern.

Robert Hicks

unread,
Jul 21, 2006, 12:25:08 PM7/21/06
to

That my friend is NOT Tcl's fault. That my friend is the PROGRAMMER's
fault. It certainly doesn't mean Tcl is not good for web apps.

:Robert

Don Porter

unread,
Jul 21, 2006, 2:14:53 PM7/21/06
to
Derek Fountain wrote:
> I still have a suspicion that there's something more going on with Tcl
> web applications than is apparent at first glance. My original question
> asked whether Tcl's recursive execution nature caused problems with
> applications that run in a web (or other hostile) environment.

It seems to me you're using a high-falutin' phrase to make more out
of this particular issue than is really there.

Unless I'm missing something, "recursive execution nature" basically
means "can do an [eval] on user input". Yes, languages that offer [eval]
suffer from an additional category of possible security holes compared
with those languages that have no [eval].

If I'm not mistaken, most of the popular languages for programming
web applications offer [eval] in some form or another. The expressive
power offered by it is hard to do without once you're used to having it.
I don't see any rational reason to claim that Tcl is uniquely bad in
this regard, or that Tcl has any "recursive execution nature" not found
in all the comparable languages.

I would say there are a few concerns unique to Tcl about preventing
evaluation of attack code that are worth considering.

1) Tcl has historicaly required the use of [eval] in situations where
all that's really needed is a reparsing of word boundaries. This
means that the use (and risk) of [eval] is more common. The addition
of {expand} syntax in Tcl 8.5 is an important improvement to correct
this issue.

2) A trusted (that is, not safe) Tcl interpreter can fairly easily
be coaxed into [source]-ing any file with the right name (such
as pkgIndex.tcl, tclIndex, or en.msg) in the right place, so
it's important to guard filesystem write permissions and search
path configurations to prevent these attack vectors.

3) There's no well-maintained central point of web presence for Tcl.
So searching for Tcl code examples effectively means "Google for
something similar to what you want to do", and frankly there's a
lot of insecure examples out there to be found and copied. There's
been efforts recently to try to improve this, and they are
appreciated, but they've not been equal to the problem so far.

On the plus side, others have already mentioned the unique security
features Tcl offers that other languages do not. Only in Tcl can
you actually disable all the [eval]-powered commands that might
cause trouble. I won't repeat the rest yet again.

On to the next step, though, I think another fair comment on Tcl's
suitability for security-conscious code is that it lacks any
"second line of defense" features. Once a malicious script gets
evaluated in an interpreter, it has access to all the capabilities
of all the commands in the interpreter. Tcl has no enforced module
boundaries with private/public access distinctions. Tcl has powerful
introspection commands. Tcl offers the power to completely replace
commands. All these powerful features that are available to
make Tcl programming effective are equally available to make
malicious scripts effective.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

sleb...@gmail.com

unread,
Jul 21, 2006, 2:17:05 PM7/21/06
to
Cameron Laird wrote:
> In article <YmJvg.42267$sz1....@newsfe6-gui.ntli.net>

>
> I'm sympathetic to Derek's explanations. I think he's right
> about a proposition which I'll try to express in my own words:
> even moderately-experienced Tcl developers can create an appli-
> cation which seems to behave as intended for common data, but
> is hazardous in general. This has nothing to do with Webbish-
> ness, by the way. The contrast is with, say, Java, where it's
> hard enough just getting things working at all. Java's common
> hazards in this sense--exec() and such--are more "discrete".
>
> There *is* something going on with Tcl; think how often naive
> users apply list commands to non-list data.

I wonder how Tcl got to this point. I use to consider (and still do)
Tcl to be one of the safest languages out there in terms of security
and error handling. Tcl's string functions are renowned (among Tclers
at least) for being "written by paranoiacs". Tcl's interp, especially
safe interps is a very powerful feature that not only predates similar
features in other languages but I have yet to see anything else better
implemented. IMHO, even chroot is not as good. Not to mention that
Tcl's "exec", unlike most other languages, is designed so that it's
default use makes it hard to do code injection.

A long time ago I noticed perhaps the first step down this slippery
slope. People started using eval to split up arguments. So the well
designed, very safe exec now gets wrapped in:

eval exec /bin/command $arguments

I see this as being much more dangerous then Darek's use of expr to do
comparisons (which I personally find strange coming from C, I've never
seen anyone use expr for such things - people usully use if, while or
for). Partly because using eval like this is more common but also
because prior to 8.5 there was really no other way to do it. Of course
prople are advised to be careful with eval but when you use it so often
you're bound to slip up. With 8.5 of course, we now have {expand} to
help us out.

> All languages possess frequently-made mistakes. Tcl is power-
> ful enough that its hazards can be more dramatic than those
> common in other languages. I don't think that disqualifies
> Tcl; its charms and advantages are also dramatically effective.

Tcl: powerful enough to be dangerous? Sounds like C to me ;-)

Robert Hicks

unread,
Jul 21, 2006, 3:44:23 PM7/21/06
to

sleb...@yahoo.com wrote:
<snip>

> Tcl: powerful enough to be dangerous? Sounds like C to me ;-)

Tcl: powerful enough to be dangerous? And easier than C! :-)

Robert

Cameron Laird

unread,
Jul 21, 2006, 6:15:08 PM7/21/06
to
In article <44bfa05e$0$17964$892e...@authen.yellow.readfreenews.net>,
Derek Fountain <nom...@hursley.ibm.com> wrote:
.
.

.
>OK, convince me. How do you compare one user-entered string value with
>another hard coded string value, in Perl or PHP, such that if there is
>Perl or PHP code in the user supplied value, it gets executed? The only
>way that I know of is to use the language's eval function to wrap the
>user-entered string on one side of the comparison, which makes no sense
>in the script, and would be completely obvious if someone were to type
>it. Is there another, more subtle way that I don't know of?

Yes.

I'm going to respond in a partial way to several observations
you've made about such other languages as Perl and PHP. As
you know, *all* languages have characteristic hazards and
fault modes. I agree with you that Tcl people need to be
especially wary around [expr] (but probably also [source] and
[load] ...), although I don't understand your emphasis on Web
applications.

Perl and PHP have *big* issues with system(), autocreation of
hashes from GETted data, and, I suspect, Unicode--Unicode re-
mains, in my estimation, an under-researched security domain.
The closest I know in these languages to the [expr] problem is
habitual use of eval() to coerce a string to a number. As
strange as that sounds, it was a common habit in the '90s. I
don't know whether it still is.

I think there also are security issues with comparison that
you might also regard in this category. I'm not current
enough with PHP or Perl to generate them immediately, but I
suspect there are regular-expression-using habits that'll end
with something comparable to the [expr] hazard.

Derek Fountain

unread,
Jul 22, 2006, 6:03:02 AM7/22/06
to
Don Porter wrote:
> It seems to me you're using a high-falutin' phrase to make more out
> of this particular issue than is really there.
>
> Unless I'm missing something, "recursive execution nature" basically
> means "can do an [eval] on user input".

No, I mean that saying something like:

set var "this that [somecommand arg]"

calls the interpreter recursively. As 'man tcl' says in the "Command
substitution" section, "To do this it invokes the Tcl interpreter
recursively to process the characters following the open bracket as a
Tcl script." That is, to the best of my knowledge, a unique
characteristic of Tcl, at least among the mainstream scripting
languages. With the others you have to specifically say you want
something evaled; with Tcl it happens automatically when a '[' is found,
even if that '[' has got there through rogue input and the original
programmer knows nothing about it.

This is of course one of the unique beauties of the language. The only
point I'm trying to make in all this is that it's also a feature that's
easily abused, and is therefore something that makes me nervous.

> <snip!>

Everything else you said I agree with.

Snaury

unread,
Jul 22, 2006, 6:58:25 AM7/22/06
to
sleb...@yahoo.com wrote:
> A long time ago I noticed perhaps the first step down this slippery
> slope. People started using eval to split up arguments. So the well
> designed, very safe exec now gets wrapped in:
>
> eval exec /bin/command $arguments

But is that really so bad? I mean, I use that myself, because there
doesn't seem to be other way when $arguments is list (and it often is
list when you dynamically construct arguments). And when you know for
sure it is list, there doesn't seem to be anything bad, is there?

Other times I use eval to speed up execution (again on arrays), like
here:

proc lconcat {varname args} {
upvar $varname var
if {[llength $args] > 0} {
eval [list eval [list lappend var]] $args
}
return $var
}

(where each argument must be a list) I perfectly understand that if
someone passes string, like {[do something evil]} as an argument, it
would in fact do this something evil, callers just should know what
they are doing. And in fact, I can't see no other way for things like
this, because if one of arguments is list with million values,
iterating over it and appending values one by one is painfully slow...

Neil Madden

unread,
Jul 22, 2006, 7:14:55 AM7/22/06
to
Derek Fountain wrote:
> Don Porter wrote:
>
>> It seems to me you're using a high-falutin' phrase to make more out
>> of this particular issue than is really there.
>>
>> Unless I'm missing something, "recursive execution nature" basically
>> means "can do an [eval] on user input".
>
>
> No, I mean that saying something like:
>
> set var "this that [somecommand arg]"
>
> calls the interpreter recursively. As 'man tcl' says in the "Command
> substitution" section, "To do this it invokes the Tcl interpreter
> recursively to process the characters following the open bracket as a
> Tcl script."

I'm not sure what you mean here. Recursively calling the interpreter to
handle nested calls is not unique to Tcl by any means. Most interpreters
will do the same (except perhaps things like stackless Python). This
doesn't open up a new form of attack as each bit of code is only
evaluated *once*. e.g.:

% set userinput { puts "ATTACK!" }
puts "ATTACK!"
% proc id x { return $x }
% set a [id $userinput]
puts "ATTACK!"

So, you still need an [eval] there to cause evaluation of user code,
just as in other languages. The only possible source of attack would be
if you directly did:

% set a [$userinput]

and that would only work if $userinput happened to contain a single
command name (e.g. "exit"). But I can't see any reason why anyone would
do this -- you're clearly asking for user input to be evaluated.

The problem you've described elsewhere in this thread has to do with two
rounds of evaluation: once by Tcl and once by some other command, like
[expr]. This is *not* recursive execution -- two separate functions
perform each round. Again, this is not particularly unique to Tcl,
except that Tcl uses these "little-language" commands that do their own
interpretation more often than many other languages (and really, we're
just talking about [expr] here).

-- Neil

Uwe Klein

unread,
Jul 22, 2006, 7:25:49 AM7/22/06
to
Snaury wrote:
> sleb...@yahoo.com wrote:
>
>>A long time ago I noticed perhaps the first step down this slippery
>>slope. People started using eval to split up arguments. So the well
>>designed, very safe exec now gets wrapped in:
>>
>> eval exec /bin/command $arguments

eval [ linsert $arguments 0 exec /bin/command ]

with 8.5

exec /bin/command {expand}$arguments

uwe

Snaury

unread,
Jul 22, 2006, 7:51:30 AM7/22/06
to
sleb...@yahoo.com wrote:
> With 8.5 of course, we now have {expand} to help us out.

Hmm... good thing, but unfortunately it won't help me eliminate all of
my evals:

set var [list]
set args [list [list 1 2 3] [list 4 5 6]]
eval [list lappend var] {expand}$args

And this eval can't be removed even on 8.5a4: {expand}{expand}$args
doesn't work. So it would still have possibility for injection here...

Kaitzschu

unread,
Jul 22, 2006, 10:16:37 AM7/22/06
to

set var [concat {expand}$args]

suc...@wanadoo.fr

unread,
Jul 22, 2006, 11:27:40 AM7/22/06
to
On Fri, 21 Jul 2006 11:46:24 +0200, Ralf Fassel <ral...@gmx.de>
wrote:

Hello, you write


>I've seen too many unbraced 'expr' in TCL code to deny that Derek has
>a point here. Unbraced 'expr' is bad TCL code that is very (?)
>widespread.

is not it then the bad coding's responsability and not the language's
fault ?
If i undestand correctly what you mean then if people would code
along the rules of Tcl then it would be all right ?
i feel this observation is true for all computer languages.
Tcl/Tk is an excellent tool, very safe provided one follows the
language rules.
friendly
jerome

suc...@wanadoo.fr

unread,
Jul 22, 2006, 12:12:15 PM7/22/06
to
On Fri, 21 Jul 2006 12:43:56 +0000, cla...@lairds.us (Cameron Laird)
wrote:

Hello
you write "Tcl; its charms and advantages are also dramatically
effective." I am 100% with you.
friendly
jerome

Don Porter

unread,
Jul 22, 2006, 1:32:12 PM7/22/06
to
>> Unless I'm missing something, "recursive execution nature" basically
>> means "can do an [eval] on user input".

Derek Fountain wrote:
> No, I mean that saying something like:
>
> set var "this that [somecommand arg]"
>
> calls the interpreter recursively. As 'man tcl' says in the "Command
> substitution" section, "To do this it invokes the Tcl interpreter
> recursively to process the characters following the open bracket as a
> Tcl script." That is, to the best of my knowledge, a unique
> characteristic of Tcl, at least among the mainstream scripting
> languages.

I don't know enough scripting languages with sufficient depth
to comment on the uniqueness claim, but I can say with confidence
that the presence of command substitution in Tcl opens no security
holes due to Tcl's rule of "one round of substitution before
command evaluation". At the time of Tcl's creation, this was a
noteworthy improvement over the Unix shell languages, where Quoting
Hell has depths best only imagined, not experienced.

The only way you face any danger is when one of the [eval]-powered
commands comes into play. (Or, in Tcl 8.5, through really careless
use of the {expand} syntax. I'd hope the risk of

{expand}$input

would be self-evident.)

Snaury

unread,
Jul 22, 2006, 2:26:51 PM7/22/06
to
Kaitzschu wrote:
> > set var [list]
> > set args [list [list 1 2 3] [list 4 5 6]]
> > eval [list lappend var] {expand}$args
> > And this eval can't be removed even on 8.5a4: {expand}{expand}$args
> > doesn't work. So it would still have possibility for injection here...
> set var [concat {expand}$args]

Hmm... I was always avoiding using concat on lists (and wrote my
lconcat which used lappend) because it was looking if arguments were
ever used like strings and was returning string if so (so if you are
concating 1000 lists with 1000 elements each you will get a very long
and slow string). Nice that 8.5 doesn't behave so anymore. Thanks! :)

sleb...@gmail.com

unread,
Jul 22, 2006, 7:51:52 PM7/22/06
to
Derek Fountain wrote:
> Don Porter wrote:
> > It seems to me you're using a high-falutin' phrase to make more out
> > of this particular issue than is really there.
> >
> > Unless I'm missing something, "recursive execution nature" basically
> > means "can do an [eval] on user input".
>
> No, I mean that saying something like:
>
> set var "this that [somecommand arg]"
>
> calls the interpreter recursively. As 'man tcl' says in the "Command
> substitution" section, "To do this it invokes the Tcl interpreter
> recursively to process the characters following the open bracket as a
> Tcl script." That is, to the best of my knowledge, a unique
> characteristic of Tcl, at least among the mainstream scripting
> languages. With the others you have to specifically say you want
> something evaled; with Tcl it happens automatically when a '[' is found,
> even if that '[' has got there through rogue input and the original
> programmer knows nothing about it.

I think there is a misunderstanding here. "Recursive" in that sentence
does not mean "infinitely recursive" which is admittedly the "normal"
meaning when programmers use the word recursion. It simply means that
the interpreter is invoked to eval the contents of []. The thing to
note is that Tcl does only "one round of substitution" which prevents
the "recursion" from being "re-recursed". Rouge user data containing []
does not get evaled unless the programmer deliberately evals it. Test
it out for yourself:

% set x {[exit]}
[exit]
% puts $x
[exit]
% if {$x != ""} {puts "x is $x"}
x is [exit]

> This is of course one of the unique beauties of the language. The only
> point I'm trying to make in all this is that it's also a feature that's
> easily abused, and is therefore something that makes me nervous.

And this is not even unique among programming languages. Only they
don't use the word recursion and thus don't trigger your nervousness.
Bash for example states in its man page that backticks `` evaluates its
contents in a "subshell" which means exactly the same thing without
using the word "recursive". And it even behaves the same was as Tcl:

> echo `cat \`ls *.txt\``

or more tcl-like in bash:

> echo $(cat $(ls *.txt))

This feature is not unique among text substitution languages like sh,
bash, ash, ksh, csh, tcsh and tcl. And the original Tcl was a pure text
substitution language (we don't even handle maths natively, we use expr
for that).

I guess your beef with Tcl is that there are many ways for the
programmer to "deliberately" eval code:

- eval
- expr
- square brackets (which is just a short hand for eval anyway, like $
is a shorthand for set)
- double quotes
- being the first word where tcl expects a command (set x "exit"; $x)

Our beef with you is that you seem to think that it happens everywhere
else.

Of course Tcl's got a safe interpreter. Use it when dealing with
untrusted data. Then you have nothing to be nervous about except being
aware what extra commands you want to expose to the safe interpreter
(for the really nervous: nothing). You can even let the user write
scripts as input and you'll still be safe. Heck, you can even write web
pages that send back forms containing tcl scripts to be evaluated and
you'll still be safe!

Ralf Fassel

unread,
Jul 24, 2006, 6:00:11 AM7/24/06
to
* suc...@wanadoo.fr

| Hello, you write
| >I've seen too many unbraced 'expr' in TCL code to deny that Derek has
| >a point here. Unbraced 'expr' is bad TCL code that is very (?)
| >widespread.
| is not it then the bad coding's responsability and not the language's
| fault ?

Yes. And no. It is of course the programmer who writes the bad code.
But it is also the language which allows to write such bad code, and
how easy it is to make such errors in the language.

Eg, you generally can't malform an 'if' clause since you get a syntax
error in return:
if $foo == $bar then {
puts yes
} else {
puts no
}

will generally err out. But 'expr' or 'uplevel' or 'after' let you
run into this trap.

expr $foo == $bar
after idle some_proc $foo $bar
uplevel some_proc $foo $bar

are all perfectly legal TCL code, but undergo a second round of
substitution. If you know that and realize it and know the
consequences, you code those either with braces or with [list], resp.
But the beginner will likely miss those, since "they work, don't
they?" Do you revisit/refactor your code from five years ago to look
for such pitfalls?

Having said that, other languages make it easy to err in other calls
like 'system' or 'exec' (invoking a shell with shell
substitution/expansion on the arguments which can be desastrous too).

So there is no 'clear' disadvantage of TCL compared to those
languages. If you never use 'expr', your code can not suffer from
missing braces. If you never call 'system', shell expansion does not
affect your code.

R'

Ralf Fassel

unread,
Jul 24, 2006, 6:06:10 AM7/24/06
to
* "Snaury" <sna...@gmail.com>

| > eval exec /bin/command $arguments
|
| But is that really so bad? I mean, I use that myself, because there
| doesn't seem to be other way when $arguments is list (and it often
| is list when you dynamically construct arguments). And when you know
| for sure it is list, there doesn't seem to be anything bad, is there?

The important point here is "when you know for sure it is list".
But sometimes $arguments includes something taken from user input, and
it is very easy to simply assume that the input is a proper list, and
use it without split'ting it up first.

R'

Neil Madden

unread,
Jul 24, 2006, 7:53:23 AM7/24/06
to
suc...@wanadoo.fr wrote:
[...]

> is not it then the bad coding's responsability and not the language's
> fault ?

Well, the whole point of using higher-level languages is to make it
easier to avoid bad coding, otherwise we could all write in assembler
and just avoid writing bad code.

-- Neil

suc...@wanadoo.fr

unread,
Jul 24, 2006, 9:51:37 AM7/24/06
to
On Mon, 24 Jul 2006 12:00:11 +0200, Ralf Fassel <ral...@gmx.de>
wrote:

>* suc...@wanadoo.fr

Hello Ralf
thank you for very clear explanation. One more question, knowing
where beginners could be mis-coding maybe the knowledgeable people
could make a special wiki.tcl.tk page with something like "mis-coding
risks".
friendly
jerome

Cameron Laird

unread,
Jul 24, 2006, 10:24:32 AM7/24/06
to
In article <1sj9c2tr6s3cc0pfv...@4ax.com>,
<suc...@wanadoo.fr> wrote:
.
.
.

>thank you for very clear explanation. One more question, knowing
>where beginners could be mis-coding maybe the knowledgeable people
>could make a special wiki.tcl.tk page with something like "mis-coding
>risks".
>friendly
>jerome

http://wiki.tcl.tk/fmm

Andreas Leitgeb

unread,
Jul 24, 2006, 12:04:59 PM7/24/06
to
sleb...@yahoo.com <sleb...@gmail.com> wrote:
> - square brackets (which is just a short hand for eval anyway,

I don't think so. How would you write
set a [my command]
with eval instead of the brackets?

> like $ is a shorthand for set)

Yes, $ *IS* a shortcut for set, but [] *ISN'T* for eval.

> You can even let the user write
> scripts as input and you'll still be safe.

Safe? In a way. But even in a safe interpreter, you can usually
still write endless loops - bad enough for a webserver.
(cpu-hogs -> "DOS")

Cameron Laird

unread,
Jul 24, 2006, 12:31:25 PM7/24/06
to
In article <slrnec9rt...@gamma.logic.tuwien.ac.at>,
Andreas Leitgeb <a...@logic.at> wrote:
.
.

.
>Safe? In a way. But even in a safe interpreter, you can usually
>still write endless loops - bad enough for a webserver.
>(cpu-hogs -> "DOS")
>

Ah-ha! In the midst of our predictable but correct rounds of,
"See? Those other languages are just as bad", I entirely forget
to mention Tcl's leadership in resource introspection. In that
way, too, Tcl is safer than the others.

suc...@wanadoo.fr

unread,
Jul 24, 2006, 1:35:58 PM7/24/06
to
On Mon, 24 Jul 2006 14:24:32 +0000, cla...@lairds.us (Cameron Laird)
wrote:

>In article <1sj9c2tr6s3cc0pfv...@4ax.com>,

I should have known better ! Of course you had made it already !
Bravo
thank you
friendly
jerome

Gerald W. Lester

unread,
Jul 24, 2006, 2:10:03 PM7/24/06
to
Andreas Leitgeb wrote:

> sleb...@yahoo.com <sleb...@gmail.com> wrote:
>> You can even let the user write
>> scripts as input and you'll still be safe.
>
> Safe? In a way. But even in a safe interpreter, you can usually
> still write endless loops - bad enough for a webserver.
> (cpu-hogs -> "DOS")

With 8.5 you can put time and number of command limits on an interpreter --
so you can be safe even form endless loops.


--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

Andreas Leitgeb

unread,
Jul 24, 2006, 4:39:39 PM7/24/06
to
Gerald W. Lester <Gerald...@cox.net> wrote:
> Andreas Leitgeb wrote:
>> sleb...@yahoo.com <sleb...@gmail.com> wrote:
>>> You can even let the user write
>>> scripts as input and you'll still be safe.
>>
>> Safe? In a way. But even in a safe interpreter, you can usually
>> still write endless loops - bad enough for a webserver.
>> (cpu-hogs -> "DOS")
>
> With 8.5 you can put time and number of command limits on an interpreter --
> so you can be safe even form endless loops.

I expected this response...

Anyway, giving a limit means choosing one of these two things:
- either, the limit is small enough, such that hardly
anything useful can be done in that time (ok, this
surely depends on the real purpose of such a service)
- or by starting jobs again and again, it is still possible
to load the server more than intended. (maybe leading
to "legal" jobs therefore running into time-limit.)

Btw., my point wasn't about other languages, but only
that I wouldn't offer even a safe tcl interpreter to the
public, as was suggested by slebetman

Gerald W. Lester

unread,
Jul 24, 2006, 7:08:09 PM7/24/06
to
Andreas Leitgeb wrote:
> Gerald W. Lester <Gerald...@cox.net> wrote:
>> Andreas Leitgeb wrote:
>>> sleb...@yahoo.com <sleb...@gmail.com> wrote:
>>>> You can even let the user write
>>>> scripts as input and you'll still be safe.
>>> Safe? In a way. But even in a safe interpreter, you can usually
>>> still write endless loops - bad enough for a webserver.
>>> (cpu-hogs -> "DOS")

> Btw., my point wasn't about other languages, but only

> that I wouldn't offer even a safe tcl interpreter to the
> public, as was suggested by slebetman

Sorry missed your point completely -- one in which I completely agree.

Never, but never give public access to an interpreter -- of any kind.

Fredderic

unread,
Jul 24, 2006, 7:14:56 PM7/24/06
to
On 24 Jul 2006 20:39:39 GMT,
Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at> wrote:

> > With 8.5 you can put time and number of command limits on an
> > interpreter -- so you can be safe even form endless loops.

> Anyway, giving a limit means choosing one of these two things:
> - either, the limit is small enough, such that hardly
> anything useful can be done in that time (ok, this
> surely depends on the real purpose of such a service)
> - or by starting jobs again and again, it is still possible
> to load the server more than intended. (maybe leading
> to "legal" jobs therefore running into time-limit.)

This is a feature of some major large-scale mainframe class machines.

A relative of mine coded a database query and report to be run
later on during the late shift. He had, it turns out, made a small
error which resulted in incorrect output to the printer. Enough
incorrect output, in fact, that it cost several thousands of dollars in
lost time (tying up the computer from doing other important work) and
more so, wasted resources (several rather large industrial-sized bins of
printer paper).

As it happens he had however correctly estimated the time and output
limits of his program, and had specified all that on the job card. But
the person who actually submitted the job during the following shift
entered those limits incorrectly, allowing the job to run to completion
instead of being shut down like it should have been.

So it is worth stopping to consider the limits of a given job in such
terms, even if the limits you provide are "outrageously long"
relative to the estimated run, at least SOMETHING will likely get
through in between dud runs.


Fredderic

Dossy

unread,
Jul 30, 2006, 2:10:29 AM7/30/06
to
In article <44bdf195$0$17997$892e...@authen.yellow.readfreenews.net>,
Derek Fountain <nom...@hursley.ibm.com> wrote:
> I was in a debate with someone at work the other day regarding the
> suitability of certain languages for web application programming. Tcl
> wasn't a player in the debate, except for one throwaway comment where
> someone said he'd never use Tcl for a web application.

Hoo, boy. He obviously doesn't work at AOL, where AOLserver has been
used to build plenty of web products ... in Tcl.

Good programmers can write good code in many languages. Bad
programmers, well, they make me wish programming mistakes were lethal,
like they are for electricians and skydivers.

:-)

-- Dossy

--
Dossy Shiobara | do...@panoptic.com | http://dossy.org/
Panoptic Computer Network | http://panoptic.com/
"He realized the fastest way to change is to laugh at your own
folly -- then you can let go and quickly move on." (p. 70)

Donal K. Fellows

unread,
Aug 14, 2006, 6:40:49 AM8/14/06
to
Derek Fountain wrote:
> Not withstanding the fact that it's best to check everything, and some
> languages have other security related issues that TCL doesn't have, what
> are the potential errors peculiar to Tcl and its nature that a web
> developer might walk into and leave open a security hole?

This has been an interesting debate to read (why do these things always
happen when I'm on vacation?) and I think the real take-home messages
are this:

* Tcl doesn't stop you from shooting yourself in the foot if you insist
on doing it. It is, after all, still your foot and your gun.

* Some older "idioms" really sucked. (If you find any in the core, do
report them as a bug!) But I'm not aware of any current idiom that is
security sensitive; they are idioms precisely because they're not
plagued by that sort of problem.

* Automated code checkers help a lot.

* Tcl provides you with many tools to mitigate problems. Foremost among
these is the safe interpreter, which offers (especially when backed
up by resource limits) a degree of protection considerably beyond the
sort of thing available in other languages.

* When data passes between security domains, it should be validated.
This is true of *all* programs. When validating input, you should
always be as restrictive as possible. Tcl provides good tools for
this coincidentally ([string is] and [scan] being the most useful).

* There are whole classes of gotchas that Tcl programs are habitually
not vulnerable to. For example (and this is not the only gotcha I'm
referring to here) you could put a buffer overflow in Tcl, but you'd
need to either write a *very* strange script[*] or write a very poor
quality extension.

* High-quality extensions are similarly easy to make robust in normal
use, so much so that things like SQL injection and XSS attacks are
really actually silly script misuses. (Tcl provides good tools for
preventing these sorts of things too, especially [string map].)

Overall, my experience is that it is easy to write heavily hardened
security-exposed code in Tcl, and that such language faults as exist
(the last major one being the prevalence of [eval], which has been
addressed in 8.5 or can be tackled with some contortions in any version
previous since at least 8.0) are much easier to avoid. As I understand
it, this experience is mirrored by many others.

Bad programmers write bad code. It's a good thing that Tcl makes it easy
to be a good programmer. :-)

Donal.
[* You'd need to reinvent buffers, then index into them in the wrong way
and evaluate the bits you read out. Or something like that. I can't
think of any sane reason for writing such code as it would be hard
work and probably much easier to write in a safe way! :-) ]

0 new messages