[REBOL] Re: load and mold/all security issue
From: nitsch-lists:netcologne at: 25-Sep-2003 19:22
Am Donnerstag, 25. September 2003 15:17 schrieb Romano Paolo Tenca:
> Hi Volker,
>
> i'm not sure you are right, wgen you say:
> > someone sends you data. you load it. you expect something like
> > o: context [ a: 1 b: 2]
> > you code "do-something-with o/a"
> > somebody sends you
> > o: context[ a: 1 b: func[][ take-over-system ] ]
>
> Doing a loaded program cannot be sure. The same can happen with
>
> > somebody sends you
>
> o: [ take-over-system]
>
> if you do it in a way or in another:
>
no, i don't do the block. i only access fields.
!>> data: load mold/all reduce[context[x: 1 y: 2] context[x: 2 y: 3]]
== [
make object! [
x: 1
y: 2
]
make object! [
x: 2
y: 3
]]
i like this. i get data from a client, i can access
!>> data/1/x
== 1
!>> data/2/x
== 2
I can even have nested objects.
i don't want to execute code of course.
so if someone sends
!>> data: load mold/all reduce[context[x: func[][print "Yup"] y: 2] context[x:
2 y: 3]]
== [
make object! [
x: func [][print "Yup"]
y: 2
]
make object! [
x: 2
y: 3
]]
>> data/1/x
** Script Error: print word has no context
** Where: x
** Near: print "Yup"
see? no do, only field-access. but the function gets executed.
if it would be bound to global context, it would say "Yup".
And could contain more malicious code than a print.
If you use this for communication betwen /view-client and cgi
and i edit the client, my server.
So i could not use save/all with messages i get.
i can because no words are bound.
without mold/all binding to global is ok.
because you cannot create "hot" code.
you can only send the function in pieces.
[ func [] [print "Yup"] ]
which is not the function, only the words to create one.
(that is, with newer rebols. the released /core is save, the /view-beta too.
with old but official /view 1.2.1 there are some tricks based on
hot
values and executable headers.
use load/all for headers there and access values always with
:value
instead of "value" so it will not be executed.)
I may be a bit paranoid in this security array,
seeing the verify-level of "worlds most dominant best os".
Has the drawback some things are blocked, like mold/all and functions,
or file-access sometimes.
but its so cool not to think much about data-encoding..
and a "secure[file quit %save-dir/ allow %readonly-dir/ [allow read]]"
in cgi-scripts protects against filename-exploits.
> do o
> context o
> do does o
>
> What you say would be true only if no word would be binded to the global
> context, but this happens only with functions and object.
>
never 'do untrusted data. if you don't do, words are not executable.
but functions are.
Assign them to a variable and use it,
access them by a path..
but they can not contain working code, only give errors.
> I understand that a word cannot be serialized in every situaltion, but i
> think that it should be or binded to a serialized upper level context o to
> the global context.
>
> Until yesterday i thought that mold/all was a more general version of mold,
> but now i am convinced hat it is a different tool, which can be used only
> to serialize a speficic kind of Rebol data (no words).
>
mold/all is meant for data.
without /all, some values are encoded by words and need execution.
!>> type? none
== none!
in a script its no problem, none gets executed, "make object[..]"
gets executed. but in data send by someone, i don't like execution.
but
!>> type? load mold none
== word!
;wrong, so
!>> type? do load mold none
== none!
;right, but do this only with trusted data.
now we use
!>> type? load mold/all none
== none!
;right :)
also string-series are safer encoded.
!>> load mold to-email "space inside"
** Syntax Error: Invalid word -- space inside
** Near: (line 1) space inside
!>> load probe mold to-email "space inside"
space inside
** Syntax Error: Invalid word -- space inside
** Near: (line 1) space inside
!>> load probe mold/all to-email "space inside"
{#[email! "space inside"]}
== space inside
!>> type? load mold/all to-email "space inside"
== email!
> I also ask why to serialize a function which cannot be used like a
> function. If only security is the target, mold/all should not serialize any
> function at all.
>
> I also ask why words in blocks are binded and not word in objects or
> functions.
>
Confuses me too. I guess:
the words can not be executed automatically. so it does not matter.
but one can put a function-pack in the data.
!>> a: mold/all [ [context[f: func[][print "yup"]] ]]
== {[[context [f: func [] [print "yup"]]]]}
!>> b: load a
== [[context [f: func [] [print "yup"]]]]
!>> c: do first b
!>> c/f
yup
So one can put a password or something in the data, load, verify password
and execute code.
!>> a: mold/all [ password "grttldp" code [func[][print "yup"]] ]
== {[password "grttldp" code [func [] [print "yup"]]]}
!>> b: load a
== [password "grttldp" code [func [] [print "yup"]]]
!>> if "grttldp" = b/password[f: do b/code f]
yup
and under attack:
>> a: mold/all reduce[ 'password func[][print "got you!"] 'code []]
== {[password #[function! [][print "got you!"]] code []]}
>> b: load a
== [password func [][print "got you!"] code []]
>> if "grttldp" = b/password[f: do b/code f]
** Script Error: print word has no context
** Where: password
** Near: print "got you!"
:-)
isn't that subtle? ;)
(Now if loading it would be more stable. Gabriele noted problems)
> ---
> Ciao
> Romano
(Hope its readable)
Ciao
-Volker