Luckily I kept notes on this... the answer is not very if you're snarfing stuff over the wire!
: <wingo> paroneayea: relatedly, : http://git.savannah.gnu.org/cgit/guile.git/commit/?id=e68dd5c601ef7975507d4118bcc2ad334b0450b2 : <wingo> i suppose that doc update doesn't touch security at all tho... [16:54] : <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... [16:59] : <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> https://dpaste.de/Pdor : <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 [17:01] : <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... [17:02] : <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' [17:08] : <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. [17:09] : <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 [17:17] : <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 notes.org 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> : http://stackoverflow.com/questions/640938/what-is-the-maximum-size-of-a-web-browsers-cookies-key : <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!
