------------------------------------------------------------------------------ Also see cgi_whynot in this directory ------------------------------------------------------------------------------ Where/How can I create a CGI Executable Note this is specific to Apache and NCSA Webservers, simular methods are used on other web servers. To execute a CGI program, the Web server (httpd) must be told of the programs existance. With out this the httpd server has no real way of determining what is an executable and what isn't. Here are the two normal methods of doing this.... 1/ Place the CGI executable in a "cgi-bin". All files regardless of their suffix in a "cgi-bin" will be treated by the web server as an executable. That is ".cgi" or ".pl" or any other suffix is NOT required. The server configuration files declare what directories is a "cgi-bin". Also for security reasons "cgi-bin" directories are usally outside the normal WWW document tree and are refered to via a "path alias" (called a script alias) which declares which cgi-bin is being refered to. For example: I have a cgi-bin called "ant-bin", which points to the directory "/home/anthony/bin/cgi-bin" inside my home directory on the web server I am using. A program called "test" in that directory can be accessed with "http://www.cit.gu.edu.au/ant-bin/test", or from a web page on that server with just "/ant-bin/test". In the NCSA Httpd (and Apathe) configuration file "srm.conf" (on newer systems that file is merged into "httpd.conf"), the following configuration lines declares both the normal global "cgi-bin" of the server directory of the server and my own personal "ant-bin" cgi-bin directory. ScriptAlias /cgi-bin/ /var/www/cgi-bin ScriptAlias /ant-bin/ /home/anthony/bin/cgi-bin/ IE: the URL http://www.ict.gu.edu.au/ant-bin/test will execute my CGI script /home/anthony/bin/cgi-bin/test Other "ScriptAlias"es can be created to provide personal cgi-bins for other users. 2/ You can also use ".htaccess" to turn on the ExecCGI server option, if the webserver configuration permits (Apache Web Servers). EG: in your home directory create a .htaccess file with an options line containing `ExecCGI', to tell the server this is allowed. =======8<--------CUT HERE---------- # # Change the HTTP Servers access rights within my home pages. # # Default Server Options are :- # Indexes FollowSymLinks IncludesNoExec # # Other Options are # Indexes Generate a directory index if no index.html # FollowSymLinks Follow symbolic links as normal # SymLinksIfOwnerMatch allow symbolic link if the link and file match # ExecCGI execute .cgi files for the resulting document # Includes Full server side includes # IncludesNoExec server side includes but don't execute anything # # I do NOT want any automatic directory index files. # Options -Indexes +ExecCGI =======8<--------CUT HERE---------- When this is done any file ending in the .cgi suffix will be thought of by the httpd server as a CGI executable. WARNING: this feature may be turned off on some web servers such as those provided to students or by Internet service providers. Such web sites may insist on the use of cgi-bins to store such executables so they can be located and checked by the webmaster. The .cgi method (Options +ExecCGI) is a late addition to www servers to allow the use of CGI programs outside CGI bins but is not recommended by security manuals as: * Such scripts are located INSIDE the www document tree, which makes it possible for hackers to search for and possibly read/re-write/hack such scripts. * Web Masters can't find them easily to check for security holes and problems, as they could be anywhere in the document tree. * A .cgi suffix is not very nice anyway and makes it obvious it is a CGI script and not just a normal document. On the plus side the ".cgi" program is located in the same directory as the web forms, documentation and other html pages which are using the CGI programs. That is everything for a particular project is all located in the one place making for easier maintenance, archiving, software job control systems (eg: RCS or CVS, etc), distribution, etc. You can also run a CGI script without a .cgi extension. You simply add to the .htaccess file something like.. =======8<-------- SetHandler cgi-script =======8<-------- Alternatives.... 3/ The first Counter programs were actually a 'pretend' web server which output counter images on request. This was an overkill but can be used to provide very complex web information. A web server itself does not need to be very complex, particularly if it just wants to ignore most of the requested options. It can even be a simple UNIX "inetd" program. Such programs does not have to deal with any networks at all as "inetd" connects the programs standard input and output directly to the connecting client. A lot of complex software, such as the oracle and HP Printer Configuration servers run their own specialised web servers, generally on non-standard port numbers. This allows the configuration program to be used remotely using any Web Client, if allowed. For security the configuration web servers are usually limited to specific hosts or domains and are also usually password protected to prevent unauthorized changes to be made. More over it is now accepted practise to setup secondary web servers which perform very complex and computationally intensive document serving. For example, a mod-perl web server with a built-in, already running perl engine, or prehaps a coldfusion, tomcat, or php server. In this way simple page serving can be handled by fast cut down web server, while more complex pages can be served by the secondary larger server. Apache web servers also allow you to hide the secondary server behind the simpler primary server. The primary server will pass on the complex requests to the secondary server in such a way that client users does not see this dual setup. EG: Build your own simplified web server to execute your very special information service! ------------------------------------------------------------------------------ NOTE: the ACTION="" option of the
html tag does not need a full URL, a partical URL will be enough EG: if ant-bin is set for option 1 above then the URL will be ACTION="/ant-bin/program" if program.cgi is in the current directory ACTION="program.cgi" is enough to select the cgi program to execute. ------------------------------------------------------------------------------ Shell CGI Scripts -- Do not use. This became critical when the "Shell-Shock" bug was discovered. DON'T use a shell script!. A WWW executable is the same sort of deal as Set-UID programs are. They allow access to data and machines which a user normally does not have access to. Thus code security is vitally important. Shell Scripts have the problem that at some point a user supplied argument will appear on a command line and be parsed by the shell. Even parsing the arguments for the special shell meta-characters can be a problem. This is not to say that it is not impossible, particularly if the shell script does not require any CGI arguments. The problem does NOT have a simple solution and unless you are careful to the extreme someone somewhere could run any command on your system. The better idea is perl. All the variables are treated as strings and can contain even null characters without problems! But you retain the capability of fast and easy modification of a interperted script. Very important which you are creating, testing and experimenting with new CGI interfaces. Also perl provides some extra security such as taint checking, though you can't rely on that for total security, it does help a great deal. Please read and understand "cgi_whynot" in this same directory. ------------------------------------------------------------------------------ Secure Shell CGI decode.. In relation to CGI security above... Is this really secure? Can you spoof it to run your own command? This does not decode the urlencoding present... #=======8<------ $PREFIX='ARG_' # assign the input arguments to variables eval `echo "$PREFIX$QUERY_STRING" | sed 's/\["'\'';:\]//g; s/+/ /g" | \ awk 'BEGIN { RS="&"; FS="=" } # field seperators $1~/^[a-zA-Z][a-zA-Z0-9_]*$/ { printf "ARG_%s=%c%s%c\n", $1, 39, $2, 39 }' ` echo "$ARG_mesg" #=======8<------ Email me if you manage it! :-) ------------------------------------------------------------------------------- Decode Query String... See "info/data/urlencode.txt" perl -pe 'tr/+/ /; s/%([a-fA-F0-9][a-fA-F0-9])/chr hex $1/eg;' # Example.... # Input: %24argon2i%24v%3D19%24m%3D4096%2Ct%3D3%2Cp%3D1%24%2FFzf # Output: $argon2i$v=19$m=4096,t=3,p=1$/Fzf In shell string='%24argon2i%24v%3D19%24m%3D4096%2Ct%3D3%2Cp%3D1%24%2FFzf' partial="${string/+/ /}" printf '%b' "${partial//%/\\x}" ------------------------------------------------------------------------------ CGI scrips in perl See the info/perl/perl_www.hints file https://antofthy.gitlab.io/info/perl/perl_www.hints ------------------------------------------------------------------------------ Debuging CGI script CGI scripts like cron scripts generally have a minimal environment. They may NOT be in the correct directory, with the correct umask, or the correct environment. In particular they may not have HOME set. For this particular case however another posibility exists and this is probably the reason for the failure. CGI script are generally run by webservers as the user ``nobody'', or some other special purpose user with minimal access and permissions. As such in this case 'nobody' (or whatever) may not have a 'home directory', thus your error. I suggest you add something like... =======8<-------- #!/opt/bin/perl system("/bin/date > /tmp/t"); system("/bin/id >> /tmp/t"); system("/bin/pwd >> /tmp/t"); system("echo '====ENV===' >> /tmp/t"); system("env >> /tmp/t"); printf "Content-type: text/plain\n\n"; printf "Rest of CGI Script"; =======8<-------- To the top of your cgi script, run the cgi script via the web, then have a look at "/tmp/t" to see what the scripts configuration is! This script is quite safe as it completely ignores all arguments from the client. However it can provide information about you that you may not want made available. ------------------------------------------------------------------------------ How do I jump the user to a different URL From the CGI Script output the following header. The Body of the HTML Output is only needed for people with very old clients. -----8<----- Content-type: text/html Location: Some_URL Your Web client is old you should have jumped to Some_URL. -----8<----- Alternativeally you could add a META REFRESH tag to the output page with a time out of 0 to tell netscape complient web clients to "go to this page immediately" ------------------------------------------------------------------------------ Basics of form action like ACTION="/cgi-bin/guestbook?anthony&REV" A ? in a URL (that is not encoded with %3F inside) means that the rest of the URL are GET arguments to a CGI script. The CGI script recieves those arguments via the environment variable QUERY_STRING. The arguments are separated by & (again not encoded) and are usually of the form ARG_NAME=VALUE As the actual form itself is using the POST method the inputed items in the form are given to the CGI script via standard input and have a total character length given in the environment variable CONTENT_LENGTH. In the case you give the QUERY_STRING or GET CGI method arguments is the login name of the user's guestbook you are signing and the REV is a flag to indicate that this guest book is reversed. IE: insert the entry into anthony's guestbook, immediatedly after the first
, thus at the front of the guestbook and not the end. ------------------------------------------------------------------------------ CGI Data storage -- Problems and Solutions Typically a CGI script runs as a special user with minimal permissions. For example as the user "nobody" with the UNIX group "nogroup". However if a cgi script wants to record information into files for future use, this presents a problem. The file it writes to will generally have to be world-writable. As the file is world writable, in generally ANYONE with a local account on the machine will also be able to also write and modify that file, outside the control of the CGI script! For a simple web counters this is usually not a concern. A local user would have to be a pretty petty to bother modifying/destroying another users web counter. But for anything more important such as a database a write writable file is NOT an acceptable solution. One simple solution is to get the cgi script to create the file so the file is owned by that special user. Permissions can thus be arranged so only the special web user "nobody" can access/modify the file. The problem with this is the owner of the cgi-script also no longer has direct access to the data! Not only another user could write a CGI script to allow them to access that file (via that script) as the web user "nobody". IE: it is only limited protection. The only correct solution for CGI data storage is to make the CGI script SUID to the owner of the data. That is the CGI runs as the owner and not as "nobody". SUID conversion of CGI scripts is only a minor extra step and involves ensuring the program is also protected against all environment and direct execution by local users. EG the script must not only check all data input but also all the appropriate environment variables, and file permissions is correct. That is it must also treat the local machine as a possible hostile environment. ------------------------------------------------------------------------------