Training, Open Source computer languages
PerlPHPPythonMySQLApache / TomcatTclRubyJavaC and C++LinuxCSS 
Search for:
Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
Using untrusted data

Posted by BladeSabre (BladeSabre), 31 January 2006
I'm looking at Tcl safe interpreters. The manual tells me that "the most important thing in guaranteeing safety is to ensure that information passed from the slave to the master is never evaluated or substituted in the master". I understand why that is, but I'm not quite sure what I am allowed to do with it. The implication is that I can do anything that doesn't involve evaluating or substituting, but I'm not clear on what falls into that category.
Searching the Web has just given me the same phrases many times over. So I was hoping someone could explain this to me.

Posted by admin (Graham Ellis), 31 January 2006
Tcl is an unusual language in that it uses the same internal logic to handle both data and program.  Data held as a list has the same syntax as program command parameters, and so you need to take care that there's no crossover.   Beyond that (and working from memory because I'm out of the office and away from my books) there's no big problems with doing things with data passed in to safe interpretters ... "tricks" like trying to open files in directories way off the tree shouldn't work, for example.

I feel I've just written a muddy answer; would you like me to have a further look towards the end of the week when I'll be able to write something a bit more sane?

Posted by BladeSabre (BladeSabre), 31 January 2006
Hi, thanks for your quick response.

What I'm worried about is data passed out of safe interpreters. (The line I quoted from the manual refers to that.) Either passing arguments using aliases, or if the master calls functions in the slave and receives their return values- I think it has the same effect, from this point of view. Either way, I have a piece of untrusted data in the master, and I'm not sure what is and isn't OK to do with it.

Examples of things I know not to do, and why (pretending that p is a "bad thing to happen"):

Code:
proc p {} {
 puts !!!
 return true
}

set untrusted {p}

$untrusted
eval $untrusted

set untrusted {[p]}

if $untrusted {}
subst $untrusted

Apparently the top pair execute the string as a command, which I understand. The bottom pair go through the substitution process twice. That's largely what confuses me- I'm not sure if anything else will have that effect.

I think these are OK, because they only substitute once:

Code:
if {$untrusted} {}
set new_untrusted "xxx $untrusted xxx"

But I'm not sure. I really don't know how to tell what's OK and what's not.

If you have more time (and books) in a few days, I would be glad of more information.

Posted by BladeSabre (BladeSabre), 15 February 2006
Hi. I wondered if you were going to come back to this.

Posted by admin (Graham Ellis), 16 February 2006
oops - I had overlooked it.   Dashing now but it's back on my list

Posted by BladeSabre (BladeSabre), 17 April 2006
Well, it's me again. I found a website that has been very helpful (link), and I think I've got it now, though I'm not confident.

This program is a game, and "profiles.txt" contains some untrusted player-written Tcl that's supposed to follow a specific structure. It's not intended to be executable on its own, but there's a few helper procedures that the master interpreter adds. The plan is that the code inside the slave (player-written and what's given by the master) holds a set of status variables, and updates them when the master calls specific procedures. The slave is also supposed to compute and return integer values (or error strings) on request.

The idea is that what I've written here should contain all the dangerous stuff, so I can call the 4 (well, 6) procedures at the bottom, from the rest of the program, without worrying about it. However, there's still a good chance I've done something silly. If you (or anyone else here) would be willing to give me some feedback on my code, I would greatly appreciate that.

Code:
#TODO: deal with file-loading errors
set pfid [open "profiles.txt" r]
set TAINTED_all_profiles [read $pfid]
close $pfid
unset pfid

interp create -safe profile_handler

profile_handler eval set ::all_profiles "\{$TAINTED_all_profiles\}"

profile_handler eval {
 #declare some procedures and variables here
 #...
 #...
}

proc report_profile_failure {errstr catch_opts} {
set answer [tk_dialog .profile_failure "Profile failure" "$errstr" {} 0 "OK" "Debug"]
 if {$answer == 1} {
   #catch_opts might have malicious code in it somewhere, right?
   #but it's been escaped one extra time- I'm not sure what I can do with it safely
 }
}

proc report_profile_error {} {
 if {[catch {profile_handler eval get_error_string} TAINTED_error_string opts]} {
   report_profile_failure "report_profile_error failed" $opts
   return false
 }
 tk_dialog .profile_error "Profile error" "$TAINTED_error_string" {} 0 "OK"
 return true
}

proc profile_get_value {key} {
 if {[catch {profile_handler eval profile_lookup $key} TAINTED_value opts]} {
   report_profile_failure "profile_get_value failed for key $key" $opts
   return "bad"
 }
 if {[catch {incr TAINTED_value 0} value opts]} {
   report_profile_failure "profile_get_value returned non-integer" $opts
   return "bad"
 }
 return $value
 #value should be safe now?
}

#there are three more procedures, but I'll just post one because they're equivalent
proc do_evolution {vars} {
 if {[catch {profile_handler eval do_evolution [list $vars]} TAINTED_isok opts]} {
   report profile_failure "do_evolution failed" $opts
   return false
 }
 if {!$TAINTED_isok} {
   report_profile_error
   return false
 }
 return true
}




This page is a thread posted to the opentalk forum at www.opentalk.org.uk and archived here for reference. To jump to the archive index please follow this link.

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2024: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho