samuraictf / gatekeeper

GATEKEEPER: Inline and on-target defense
119 stars 15 forks source link

Unbuffered programs seem to behave badly under gatekeeper #26

Closed ghost closed 9 years ago

ghost commented 9 years ago

gatekeeper -l stdio -r stdio:test/test_echo gatekeeper -l stdio -r stdio:$(which python)

I think this has to do with buffering.. still exploring.

ghost commented 9 years ago

socat supports this mode

socat -,icanon=0 EXEC:test/test_echo,pty,ctty
zachriggle commented 9 years ago

The interactive programs only “break” in the sense that, by default, {e,}glibc buffers stdout by default if stdout is not a TTY and fflush or setvbuf are not used. Direct calls to send() and write() avoid this.

Separately, things like Python and sh behave differently when stdin is not a TTY. In particular, they buffer all input until the pipe closes, and then it is evaluated. Generally, these programs provide a command-line option to not do this. An easy example is:

cat | python

vs.

cat | python -i
ghost commented 9 years ago

The python breaking example happened to be from another bug, #27 , which is fixed now. test_echo still behaves differently through gatekeeper...

~/gatekeeper$ test/test_echo 
{START}: -1
Disabling echo
(61)(62)(63)(64)
~/gatekeeper$ ./gatekeeper -l stdio -r stdio:test/test_echo
abcd

^C
~/Downloads/gatekeeper$ 

It seems like a buffering/ icanon issue. But, I tried about every combo of tcsetattr on every file descriptor and it still doesn't work. (See https://github.com/samuraictf/gatekeeper/blob/nonbuffering/gatekeeper.c#L54 ) It did fail to tcsetattr() on the remote_fd_r/w, which are the ones I'm interested in, so I'm going down that path.

zachriggle commented 9 years ago

See the unbuffer program in my branch which handles all of this.

ghost commented 9 years ago

Yeah.. it seems to work with unbuffer.. I thought I had tried this before

ghost commented 9 years ago

Spoke to early.. Kelson noticed this-

bash@scrimmage-0:/tmp/skynet$ echo ls | /home/bash/bash
expr
regex

bash@scrimmage-0:/tmp/skynet$ echo ls | /tmp/skynet/unbuffer /home/bash/bash
bash@scrimmage-0:/tmp/skynet$ 
zachriggle commented 9 years ago

not sure what you're trying to demo there

ghost commented 9 years ago

I abbreviated the output, but basically the first case behaves normally (you see the ls output), where the 2nd case doesn't. I had 2 files expr, and regex in that dir.

zachriggle commented 9 years ago

That's a bash-ism. Reproduce on something that doesn't forcibly re-open TTYs.

ghost commented 9 years ago

Could a legit ctf service not forcibly re-open TTYs? Is there anything we can do about it?

ghost commented 9 years ago

Well, socat doesn't handle bash well either. (The c:> prompt is a joke, but to differentiate from a subshell)...

c:\> echo ls | socat - EXEC:bash,pty,ctty
ls
bash: no job control in this shell
bash-3.2$ ls
Applications    Documents   Library     Music       Public
Desktop     Downloads   Movies      Pictures
bash-3.2$ exit
c:\> echo ls | socat -,icanon=0 EXEC:bash,pty,ctty
2015/07/12 18:36:01 socat[1703] E tcgetattr(0, 0x7fff523532d0): Inappropriate ioctl for device
c:\> echo ls | socat -,raw EXEC:bash,pty,ctty
2015/07/12 18:36:05 socat[1705] E tcgetattr(0, 0x7fff5b65c410): Inappropriate ioctl for device
c:\>