打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
几种语言的CGI编程

几种语言的CGI编程

为了了解PHP、JSP、ASP出现之前人们写网站的方法,洒家研究了一波CGI,使用C、Python、batch、shell script语言写了几个简单的网页。

CGI即通用网关接口,指web服务器调用编程语言编写的程序的一个接口。洒家用的是Apache的CGI,QUERY_STRING、REMOTE_ADDR、REQUEST_URI等参数是通过环境变量传递给CGI程序的,请求主体(POST数据)作为CGI程序的标准输入(stdin),而CGI程序的标准输出(stdout)作为HTTP响应的部分(注:标准错误输出stderr会出现在错误日志中)。

系统和软件环境配置

WAMP Apache 2.4.18 64位, Ubuntu Server 16.04 64位。

需要开启Apache的cgi_module。

sudo a2enmod cgisudo service apache2 restart

对于Linux,cgi-bin的目录在 /etc/apache2/conf-enabled/serve-cgi-bin.conf 中规定,使用浏览器访问这个目录的alias:/cgi-bin/。对于Windows 下的WAMP套件,对应目录默认在安装目录内(例如C:/wamp64/cgi-bin/)。

 

由于洒家对Linux不熟悉,踩到了几个坑

1. 对于Ubuntu中 shell script,开头的#!/bin/sh 和 #!/bin/bash 是不同的。Ubuntu 的 /bin/sh 是 /bin/dash (Debian Almquist shell)的链接。对于 echo -e 'Content-Type: abc\n'的执行结果不同。

2. HTTP响应头和响应主体之间要有一个换行符,否则无法分清响应主体和响应头部。

3. Linux上的程序要加可执行文件权限。否则报500错误 Permission denied: exec of '/usr/lib/cgi-bin/env_var.sh' failed: /usr/lib/cgi-bin/env_var.sh 。

4. shell script 执行字符串要用eval,否则不能把引号中带空格的字符串识别为同一个参数。

参考

通用网关接口-维基百科

C语言CGI编程入门(一)

鸟哥的Linux私房菜-Shell的变量功能

用C、Python、Shell Script、batch(批处理)写的几个小程序

编程语言Perl是一个广泛被用来编写CGI程序的语言,但CGI的一个目的是要独立于任何语言的。Web服务器无须在这个问题上对语言有任何了解。事实上,CGI程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。除Perl外,像Unix shell script, Python, Ruby, PHP, Tcl, C/C++,和Visual Basic都可以用来编写CGI程序。

洒家看到这段话的时候想,哇塞,还可以用C语言写网站!洒家顿时感到了历史的气息。

查看所有的环境变量

在Linux下可以用 env 命令,列出所有的环境变量。注意,HTTP响应头和响应主体之间要有一个换行符,否则无法分清响应主体和响应头部,报错: malformed header from script 'env_var.sh': Bad header: SERVER_SIGNATURE=<address>Apac 。

使用 shell script脚本:

#!/bin/bashecho -e "Content-Type: text/html\n"env

响应:

HTTP/1.1 200 OKDate: Sun, 23 Oct 2016 13:10:01 GMTServer: Apache/2.4.18 (Ubuntu)
X-Author: http://www.cnblogs.com/go2bed/Vary: Accept-EncodingContent-Length: 1180Connection: closeContent-Type: text/htmlSERVER_SIGNATURE=
<address>Apache/2.4.18 (Ubuntu) Server at 192.168.245.136 Port 80</address>HTTP_USER_AGENT=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.7SERVER_PORT=80HTTP_HOST=192.168.245.136
(省略)

Hello World

Linux/Windows,C语言,请求的时候要请求编译好的二进制程序。

#include <stdio.h>int main(){        printf("Content-Type: text/html\n\n");        printf("Hello World!\n");        return 0;}

效果:

 

一个 say hello 的动态网页

Linux/Windows,Python ,头部需要加Python可执行文件的位置。对于Windows,则可能是 #!C:/Python27/python.exe 。

#!/usr/local/bin/pythonimport osimport urllibimport sysimport cgiprint 'Content-Type: text/html\n'postData = sys.stdin.read()if postData != '':    items = postData.split('&')    for item in items:        key,value = urllib.splitvalue(item)        if key == 'name':            print '<h1>Hello, %s</h1>' % (cgi.escape(urllib.unquote_plus(value)),)
print '''<form action="" method="POST"><input name="name" type="text" placeholder="Your name" /><input type="submit" /></form>'''print os.environ['QUERY_STRING']

效果如下图。此程序读取POST数据(stdin),Tom未在URL中出现。

 

另一个say hello 的动态网页

Windows/Linux,C语言。此处没有做URL decode。

#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){    int i;    char * query;    query = getenv("QUERY_STRING");    printf("Content-type:text/html\n\n");    if(getenv("QUERY_STRING") != NULL && strlen(getenv("QUERY_STRING")) > 5)    {        printf("<h1>Hello %s</h1><br />\n", query + 5);    }    printf("<form action=\"\" method=\"GET\"><input type=\"text\" name=\"name\" autofocus/><input type=\"submit\"/></form>");    return 0;}

执行任意命令的Webshell,及其过程与经验

Linux,shell script

#!/bin/bashecho -e 'Content-Type: text/html\n'echo '<h1>I am using cgi (shell script)</h1>'echo '<form action="" method="GET">'echo '<input type="text" name="cmd" autofocus />'echo '<input type="submit" />'echo '</form>'echo -e '\n<pre>\n'#echo ${QUERY_STRING}cmd=${QUERY_STRING#'cmd='}#echo ${cmd}cmd=${cmd:-'ping -c 2 baidu.com'}cmd=$(echo ${cmd}| python -c 'import sys;import urllib;sys.stdout.write(urllib.unquote_plus(sys.stdin.read()))')echo ${cmd}echo '<hr />'eval ${cmd} 2>&1#ping -c 2 baidu.comecho -e '\n</pre>\n'

 效果:

 

由于洒家对shell这门精妙的语言不甚了解,以为在shell script中执行一个命令(字符串)直接写上即可,一开始上文加粗的字体写的命令是 ${cmd} 2>&1 。这一个脚本在命令执行的时候有一些奇怪的地方。例如执行  python -c 'import this' 时,会报错:

  File "", line 1    'import          ^SyntaxError: EOL while scanning string literal

 

 

这个错误输出和下面的情况的输出相同:

user@localhost:/usr/lib/cgi-bin$ cmd=python\ -c\ \'import\ this\'user@localhost:/usr/lib/cgi-bin$ echo $cmdpython -c 'import this'user@localhost:/usr/lib/cgi-bin$ $cmd  File "<string>", line 1    'import          ^SyntaxError: EOL while scanning string literal

user@localhost:/usr/lib/cgi-bin$ eval $cmd
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.

经过一番研究之后洒家恍然大悟,这个报错表示,Python收到的参数(sys.argv[2])为  'import ,单引号的作用不是命令行中参数的边界,而是直接作为参数的一部分传进了Python。也就是说,直接执行  ${cmd} 相当于Python中的

subprocess.call(["python","-c","'import","this'"])

一个字符串变量直接执行会有问题,正确的做法要用eval命令“扫描两次”,才能正确解析。使用 eval ${cmd} 使shell重新扫描命令,把 import 和 this看做同一个参数,相当于 subprocess.call(["python","-c","import this"]) 。

总而言之,这次的错误类似于这种情况:

user@localhost:/usr/lib/cgi-bin$ pipe="|"user@localhost:/usr/lib/cgi-bin$ ls $pipe grep shls: cannot access '|': No such file or directoryls: cannot access 'grep': No such file or directoryls: cannot access 'sh': No such file or directoryuser@localhost:/usr/lib/cgi-bin$ eval ls $pipe grep shenv_var.shtest.sh

 

使用Windows batch script(批处理)写的一个功能有限的webshell

批处理,这个的坑也有点多,而且洒家也不太熟悉,只能写这么多了。

@echo offecho Content-Type: text/html; charset=GBKecho.echo ^<h1^>batch webshell^</h1^>echo ^<form action="" method="GET"^>echo ^<input type="text" name="cmd" autofocus /^>echo ^<input type="submit" /^>echo ^</form^>echo ^<pre^>set ccmmdd=%QUERY_STRING:~4%set ccmmdd=%ccmmdd:+= %set ccmmdd=%ccmmdd:^%20= %echo ^<textarea style="width:100%%;height:60%%;"^>%ccmmdd%echo ^</textarea^>echo ^</pre^>


文章出处:博客园http://www.cnblogs.com/go2bed/
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
bash 漏洞解析
Lighttpd + mod_cgi + python+Perl简单配置
Shell—定时任务(crontab)
配置apache支持python的CGI
python3 创建列表
boa服务器的移植
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服