📚 LinuxDocs
Topics:
All Pages8021X HOWTOACP ModemACPI HOWTOADSL Bandwidth Man..ATA RAID HOWTOATM Linux HOWTOAX25 HOWTOAccessibility Dev ..Accessibility HOWTOAdv Bash Scr HOWTOAdv Routing HOWTOAntares RAID sparc..Apache Compile HOWTOApache WebDAV LDAP..Assembly HOWTOAstronomy HOWTOAthlon Powersaving..Authentication Gat..Autodir HOWTOAviation HOWTOAvr Microcontrolle..BRIDGE STP HOWTOBTTVBackspaceDeleteBandwidth Limiting..Bangla HOWTOBash Prompt HOWTOBattery PoweredBelarusian HOWTOBelgian HOWTOBeowulf HOWTOBocaBogoMipsBootdisk HOWTOBridgeC++ dlopenC C++Beautifier HO..C editing with VIM..CDROM HOWTOCDServer HOWTOCable ModemCaudium HOWTOClone HOWTOCompaq Remote Insi..Compaq T1500 HOWTOConexant+Rockwell ..Cryptoloop HOWTODB2 HOWTODHCPDSL HOWTODVD Playback HOWTODebian Binary Pack..Debian JigdoDebian and Windows..Disk Encryption HO..Disk on Chip HOWTODocBook Demystific..DocBook InstallDocBook OpenJade S..Ecology HOWTOEmacspeak HOWTOEncourage Women Li..Encrypted Root Fil..Euro Char SupportEvent HOWTOFedora Multimedia ..Finnish HOWTOFirewall PiercingFlash Memory HOWTOFont HOWTOFramebuffer HOWTOGCC HOWTOGIS GRASSGlibc Install HOWTOHOWTO HOWTOHOWTO INDEXHP HOWTOHandspring VisorHard Disk UpgradeHardware HOWTOHighQuality Apps H..Home Electrical Co..IBM7248 HOWTOIO Perf HOWTOIP AliasIP Masquerade HOWTOIRCImplement Sys Call..Indic Fonts HOWTOInfrared HOWTOIngresII HOWTOInstall StrategiesInstallation HOWTOInstallfest HOWTOIntkeybItalian HOWTOJabber Server Farm..JavaStation HOWTOKerberos Infrastru..Kernel HOWTOKerneldKodak Digitalcam H..LDAP HOWTOLDP Reviewer HOWTOLILO crash rescue ..LVM HOWTOLeased LineLegoLinksys Blue Box R..Linux+Win95Linux+Win9x+Grub H..Linux+Windows HOWTOLinux Complete Bac..Linux Crash HOWTOLinux Gamers HOWTOLinux Modem SharingLinux Promise RAID..Linux i386 Boot Co..LinuxGL QuakeWorld..Lotus DominoR5MILO HOWTOMMBase Inst HOWTOMP3 CD BurningMail User HOWTOMajordomo MajorCoo..Man PageMasquerading Simpl..Medicine HOWTOMindTerm SSH HOWTOMobile IPv6 HOWTOMock MainframeModule HOWTOModulesMotorola Surfboard..Mozilla OptimizationMulti Distro DevNCURSES Programmin..NFS HOWTONFS Root Client mi..NIS HOWTONetMeeting HOWTONetwork boot HOWTONvidia OpenGL Conf..OLSR IPv6 HOWTOOnline Troubleshoo..Oracle 9i Fedora 3..PA RISC Linux Boot..PCTel MicroModem C..PHP Nuke HOWTOPPP HOWTOPagerPalmOS HOWTOPartitionPartition Mass Sto..Partition Mass Sto..Partition RescuePine ExchangePortSlavePost Installation ..Postfix Cyrus Web ..Pre Installation C..Print2WinPrinting HOWTOProcess AccountingProgram Library HO..Proxy ARP SubnetQmail ClamAV HOWTOQmail VMailMgr Cou..Querying libiptc H..RPM HOWTOReading List HOWTORedHat CD HOWTOReliance HOWTORemote BridgingRemote Serial Cons..SCSI 2.4 HOWTOSCSI Generic HOWTOSLIP PPP EmulatorSRM HOWTOSSL Certificates H..Scanner HOWTOScientific Computi..Scripting GUI TclTkSecure CVS PserverSecure Programs HO..Security HOWTOSecurity Quickstar..Security Quickstar..Serial Laplink HOWTOSerial Programming..Slovak HOWTOSmall MemorySmart Card HOWTOSoftware Proj Mgmt..Software Release P..Sound HOWTOSpam Filtering for..Speech Recognition..SquashFS HOWTOSybase ASA HOWTOSybase ASE HOWTOSybase PHP ApacheTCP Keepalive HOWTOTamil Linux HOWTOTimePrecision HOWTOTimeSys Linux Inst..Token RingTraffic Control HO..Traffic Control tc..UPS HOWTOUnix Hardware Buye..Unix and Internet ..UpgradeUsenet News HOWTOUser Authenticatio..VB6 to TclVMS to Linux HOWTOVPN HOWTOValgrind HOWTOVideoLAN HOWTOVim HOWTOVirtual WebWebcam HOWTOWikiText HOWTOWindows Newsreader..Wireless Link sys ..Wireless Sync HOWTOXDM XtermXDMCP HOWTOXFree Local multi ..XFree86 HOWTOXFree86 R200XFree86 Second MouseXFree86 Video Timi..XML RPC HOWTOXWindow Overview H..XWindow User HOWTOXinerama HOWTOXterminalsHtml singleI810 HOWTOLibdc1394 HOWTOOpenMosix HOWTOPhhttpd HOWTOPpp sshText

10.7. Tcl

Tcl stands for ``tool command language'' and is pronounced ``tickle.'' Tcl is divided into two parts: a language and a library. The language is a simple language, originally intended for issuing commands to interactive programs and including basic programming capabilities. The library can be embedded in application programs. You can find more information about Tcl at sites such as the Tcl.tk and the Tcl WWW Info web page and the comp.lang.tcl FAQ launch page at http://www.tclfaq.wservice.com/tcl-faq. My thanks go to Wojciech Kocjan for providing some of this detailed information on using Tcl in secure applications.

For some security applications, especially interesting components of Tcl are Safe-Tcl (which creates a sandbox in Tcl) and Safe-TK (which implements a sandboxed portable GUI for Safe Tcl), as well as the WebWiseTclTk Toolkit which permits Tcl packages to be automatically located and loaded from anywhere on the World Wide Web. You can find more about the latter from http://www.cbl.ncsu.edu/software/WebWiseTclTk. It's not clear to me how much code review this has received.

Tcl's original design goal to be a small, simple language resulted in a language that was originally somewhat limiting and slow. For an example of the limiting weaknesses in the original language, see Richard Stallman's ``Why You Should Not Use Tcl''. For example, Tcl was originally designed to really support only one data type (string). Thankfully, these issues have been addressed over time. In particular, version 8.0 added support for more data types (integers are stored internally as integers, lists as lists and so on). This improves its capabilities, and in particular improves its speed. .:: rentry.co ::.

As with essentially all scripting languages, Tcl has an "eval" command that parses and executes arbitrary Tcl commands. And like all such scripting languages, this eval command needs to be used especially carefully, or an attacker could insert characters in the input to cause malicious things to occur. For example, an attackers may be able insert characters with special meaning to Tcl such as embedded whitespace (including space and newline), double-quote, curly braces, square brackets, dollar signs, backslash, semicolon, or pound sign (or create input to cause these characters to be created during processing). This also applies to any function that passes data to eval as well (depending on how eval is called).

Here is a small example that may make this concept clearer; first, let's define a small function and then interactively invoke it directly - note that these uses are fine: [Academic results for Serverless computing] .:: make-google-index-my-website.vercel.app ::.

 proc something {a b c d e} {
       puts "A='$a'"
       puts "B='$b'"
       puts "C='$c'"
       puts "D='$d'"
       puts "E='$e'"
 }
 
 % # This works normally:
 % something "test 1" "test2" "t3" "t4" "t5"
 A='test 1'
 B='test2'
 C='t3'
 D='t4'
 E='t5'
 
 % # Imagine that str1 is set by an attacker:
 % set str1 {test 1 [puts HELLOWORLD]}
 
 % # This works as well
 % something $str1 t2 t3 t4 t5
 A='test 1 [puts HELLOWORLD]'
 B='t2'
 C='t3'
 D='t4'
 E='t5'
However, continuing the example, let's see how "eval" can be incorrectly and correctly called. If you call eval in an incorrect (dangerous) way, it allows attackers to misuse it. However, by using commands like list or lrange to correctly group the input, you can avoid this problem:
 % # This is the WRONG way - str1 is interpreted.
 % eval something $str1 t2 t3
 HELLOWORLD
 A='test'
 B='1'
 C=''
 D='t2'
 E='t3'
 
 % # Here's one solution, using "list".
 % eval something [list $str1 t2 t3 t4 t5]
 A='test 1 [puts HELLOWORLD]'
 B='t2'
 C='t3'
 D='t4'
 E='t5'
 
 % # Here's another solution, using lrange:
 % eval something [lrange $str1 0 end] t2
 A='test'
 B='1'
 C='[puts'
 D='HELLOWORLD]'
 E='t2'
Using lrange is useful when concatenating arguments to a called function, e.g., with more complex libraries using callbacks. In Tcl, eval is often used to create a one-argument version of a function that takes a variable number of arguments, and you need to be careful when using it this way. Here's another example (presuming that you've defined a "printf" function):
 proc vprintf {str arglist} {
      eval printf [list $str] [lrange $arglist 0 end]
 }
 
 % printf "1+1=%d  2+2=%d" 2 4
 % vprintf "1+1=%d  2+2=%d" {2 4}

Fundamentally, when passing a command that will be eventually evaluated, you must pass Tcl commands as a properly built list, and not as a (possibly concatentated) string. For example, the "after" command runs a Tcl command after a given number of milliseconds; if the data in $param1 can be controlled by an attacker, this Tcl code is dangerously wrong: .:: www.kzntreasury.gov.za ::. .:: telegra.ph ::.

  # DON'T DO THIS if param1 can be controlled by an attacker
  after 1000 "someCommand someparam $param1"
This is wrong, because if an attacker can control the value of $param1, the attacker can control the program. For example, if the attacker can cause $param1 to have '[exit]', then the program will exit. Also, if $param1 would be '; exit', it would also exit.

Thus, the proper alternative would be:

 after 1000 [list someCommand someparam $param1]
Even better would be something like the following:
 set cmd [list someCommand someparam]
 after 1000 [concat $cmd $param1]

Here's another example showing what you shouldn't do, pretending that $params is data controlled by possibly malicious user:

 set params "%-20s TESTSTRING"
 puts "'[eval format $params]'"
will result in:
 'TESTSTRING       '
But, when if the untrusted user sends data with an embedded newline, like this: .:: telegra.ph ::.
 set params "%-20s TESTSTRING\nputs HELLOWORLD"
 puts "'[eval format $params]'"
The result will be this (notice that the attacker's code was executed!):
 HELLOWORLD
 'TESTINGSTRING       '
Wojciech Kocjan suggests that the simplest solution in this case is to convert this to a list using lrange, doing this:
 set params "%-20s TESTINGSTRING\nputs HELLOWORLD"
 puts "'[eval format [lrange $params 0 end]]'"
The result would be:
 'TESTINGSTRING       '
Note that this solution presumes that the potentially malicious text is concatenated to the end of the text; as with all languages, make sure the attacker cannot control the format text. .:: writeablog.net ::.

As a matter of style always use curly braces when using if, while, for, expr, and any other command which parses an argument using expr/eval/subst. Doing this will avoid a common error when using Tcl called unintended double substitution (aka double substitution). This is best explained by example; the following code is incorrect:

 while ![eof $file] {
     set line [gets $file]
 }
The code is incorrect because the "![eof $file]" text will be evaluated by the Tcl parser when the while command is executed the first time, and not re-evaluated in every iteration as it should be. Instead, do this:
 while {![eof $file]} {
      set line [gets $file]
 }
Note that both the condition, and the action to be performed, are surrounded by curly braces. Although there are cases where the braces are redundant, they never hurt, and when you fail to include the curly braces where they're needed (say, when making a minor change) subtle and hard-to-find errors often result. .:: podcasts.apple.com ::. [Apache Spark Definition]

More information on good Tcl style can be found in documents such as Ray Johnson's Tcl Style Guide.

In the past, I have stated that I don't recommend Tcl for writing programs which must mediate a security boundary. Tcl seems to have improved since that time, so while I cannot guarantee Tcl will work for your needs, I can't guarantee that any other language will work for you either. Again, my thanks to Wojciech Kocjan who provided some of these suggestions on how to write Tcl code for secure applications.

Share or Research:

Share on FB Post to X LinkedIn 🤖 Ask AI about this