[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is there any security risk related to the use of the reader?

From: Christopher Lemmer Webber
Subject: Re: Is there any security risk related to the use of the reader?
Date: Sun, 25 Feb 2018 11:35:31 -0600
User-agent: mu4e 0.9.18; emacs 25.3.1

Luckily I kept notes on this... the answer is not very if you're
snarfing stuff over the wire!

: <wingo> paroneayea: relatedly,
: <wingo> i suppose that doc update doesn't touch security at all tho...  
: <paroneayea> wingo: ah nice
: <paroneayea> wingo: yeah... srfi-10 seems to be one way where (read) can get
:            scary                                                      [16:55]
: <paroneayea> wingo: really makes me wish I could specify a scope where I
:            *know* how read behaves
: <wingo> yeah i know what you mean                                     [16:56]
: <paroneayea> maybe (scoped-read) (scoped-write)
: <paroneayea> or even a module that provides (read) and (write), splatting over
:            the default ones unless you namespace it :)                [16:57]
: <wingo> nah, i think a port option or something is what you want
: <paroneayea> a port option would be fine
: <dsmith-work> There is also read-hash-extend (I think srfi-10 uses that)
: <paroneayea> wingo: I saw that there was some mention of being able to control
:            how read works in the port... but it looked like the *data* read
:            by read was able to change read behavior                   [16:58]
: <paroneayea> which is actually even more worrying!
: <wingo> how could the data change the behavior?  only via #.
: <wingo> which is off by default
: <paroneayea> ah
: <paroneayea> okay whew
: <wingo> no one in their right mind turns that one on :)
: <wingo> there's also #!r6rs i think...                                        
: <paroneayea> wingo: I think this paragraph is not clear to me:
: <wingo> that changes some parameters, but they are static parameters, and
:       maybe only in certain situations
: <wingo> anyway not like a danger or anything
: <paroneayea>
: <paroneayea> wingo: nothing in that section mentions how # gets turned on to
:            enable that                                                [17:00]
: <paroneayea> it sounds like *any* port that runs across #!fold-case will start
:            doing that to me..
: <paroneayea> but maybe I'm just not understandgin while reading               
: <wingo> no, that's correct
: <wingo> maybe it's a problem? dunno
: <paroneayea> it doesn't seem like those are dangerous options
: <wingo> when #!fold-case is in a file that's certainly what you want
: <wingo> if an attacker can inject #!fold-case in some thing...                
: <wingo> it's an interesting idea, i hadn't thought about that
: <wingo> mark_weaver will like that one :)
: <paroneayea> well, the question is whether (read) is "safe" when you get
:            arbitrary incoming data                                    [17:03]
: <wingo> we probably need to have a port option to disable these things i guess
: <paroneayea> in the case I'm in, a signature is checked before it ever hits
:            (read), but could read/write be as safe as json?
: <wingo> paroneayea: what does "safe" mean in this context?  threat model
:       missing :)
: <paroneayea> wingo: think "reading data off a REST style API"
: <wingo> and?                                                          [17:04]
: <davexunit> arbitrary code execution
: <paroneayea> yes
: <paroneayea> eg, you're probably at no risk parsing that data through json
: <wingo> so
: <davexunit> which I don't think is possible
: <paroneayea> every rest api in the world does that
: <wingo> arbitrary code execution is only possible via read-eval (the #. thing)
: <wingo> that should be off globally.
: <paroneayea> davexunit: what about if srfi-10 is on? :)
: <wingo> you can get some code execution via srfi-10 or read-hash-extend
: <wingo> so you have to know whether the extensions that are active in your
:       program are safe against your threat model                      [17:05]
: <wingo> for example
: <wingo> a syntax extension which turns #'foo into (syntax foo)
: <wingo> there's no danger there.
: <paroneayea> sure
: <paroneayea> though say I decided "to hell with json, my REST API is going to
:            use sexps!  Wheee!"                                        [17:06]
: <paroneayea> and then I import a module that itself imports srfi-10
: <paroneayea> and I had no idea
: <paroneayea> and bam, code execution seems possible
: <wingo> yeah, not full #. code execution but yes                      [17:07]
: <wingo> but that same argument applies if a module enables #.
: <paroneayea> wingo: right
: <wingo> so yeah, it's a property of your whole program
: <paroneayea> wingo: basically I'm saying, I don't want either of those to
:            happen
: <paroneayea> because I don't know much about my libraries, necessarily
: <wingo> what code can be run by `read'                                        
: <wingo> yeah i know what you mean.  i solve this by being an asshole and never
:       using other people's code :/  not a great solution
: <dsmith-work> paroneayea: You could purge srfi-10 from systems you control?
: <dsmith-work> If some module needs it, too bad.                               
: <wingo> if you want to control the property globally, yeah like dsmith-work
:       says we can add global kill switches
: <davexunit> how about a dumb-read procedure?
: <davexunit> no reader macros allowed :)
: <wingo> we could also add per-port kill switches but that's less convenient in
:       some ways
: <wingo> heh, at that point just write your own `read' :)
: <wingo> there's also some memory dangers                              [17:10]
: <wingo> e.g. reading 10e10000
: <wingo> rather #e10e1000
: <wingo> anyway
: <davexunit> I don't know read is implemented, so I don't know how feasible it
:           would be to say "don't use any reader macros for this read call"
: <dsmith-work> What about malformed sexpr?
: <dsmith-work> Like reading "(((foo"                                   [17:11]
: <wingo> read is implemented in c right now.  for options it's better to attach
:       them to the port.
: <paroneayea> wingo: wow #e10e1000 is interesting
: <paroneayea> I would have never thought of that.                      [17:12]
: <wingo> irritating isn't it :)
: <paroneayea> so, this conversation is making me feel like: don't use read for
:            any data that comes over the wire that you don't really trust
: <paroneayea> or use a safer one you write yourself :)                 [17:13]
: <paroneayea> so, it's still safe with the signed sessions, because an attacker
:            would need your key to get you to do something evil with read
:                                                                       [17:14]
: <paroneayea> but #e10e10000, srfi-10, and #. are all worrying possible attacks
:            against using vanilla read for much data heading over the wire
:            that you don't control                                     [17:15]
: <wingo> i think there is another attack, which is ((((((((((((((((((((((((((
:                                                                       [17:16]
: <wingo> keep on going
: <wingo> the c stack keeps recursing, eventually segfault i think
: <paroneayea> wingo: interesting                                               
: <paroneayea> wingq: I guess the json parser I'm using is also semi-vulnerable
:            to that, but it wouldn't be in C
: <paroneayea> so probably there's more safety
: <paroneayea> wouldn't segfault, anyway
: * wingo currently trying the ((((( attack
: <wingo> do you have a limit on your message size?                     [17:18]
: <paroneayea> wingo: for this particular case (sessions), the limit is 4kb, but
:            I'm not worried about that.  Probably for the json-ld stuff
:            coming over the wire... I haven't set any limit :)         [17:19]
: <wingo> lol
: <wingo> scheme@(guile-user)> (call-with-input-string (make-string 200000 #\()
:       read)
: <wingo> Segmentation fault
: <paroneayea> whee :)
: <wingo> erryting turribul                                             [17:20]
: * paroneayea saves this conversation in eir file :)
: <wingo> this is "just" a bug                                          [17:21]
: <dsmith-work> IS there a limit to cookie size?
: <dsmith-work> paroneayea: or whatever you are planning on read'ing
: <paroneayea> dsmith-work: yes, cookies are limited to 4kb             [17:22]
: <paroneayea> according to the HTTP spec
: <paroneayea> well, whether guile does that
: <paroneayea> I haven't checked yet
: <paroneayea> (or rather, headers are)
: <dsmith-work> scheme@(guile-user)> (call-with-input-string (make-string 4096
:             #\() read)
: <dsmith-work> ERROR: In procedure read:
: <dsmith-work> ERROR: In procedure scm_i_lreadparen: #<unknown port>:1:4097:
:             end of file
: <paroneayea> or if not according to the http spec, according to browser
:            conventions :)
: <paroneayea>
: <dsmith-work> So in your case, at least you won't segfault.
: <paroneayea> not sure if this is from any spec, or just convention
: <paroneayea> dsmith-work: in my particular case, for sessions, it's still not
:            risky because again, someone would need to forge the key...
:                                                                       [17:24]
: <paroneayea> but yeah
: <paroneayea> I'm still interested in understanding in general how "safe" read
:            / write are in various scenarios

Amirouche Boubekki writes:

> I have procedures like that in my program:
> (define-public (scm->string scm)
>    (call-with-output-string
>      (lambda (port)
>        (write scm port))))
> (define-public (string->scm string)
>    (call-with-input-string string read))
> Is it safe to pass to this procedures input from third parties?
> TIA!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]