几种语言的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 cgi
sudo 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、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/bash
echo -e "Content-Type: text/html\n"
env
响应:
HTTP/1.1 200 OK
Date: Sun, 23 Oct 2016 13:10:01 GMT
Server: Apache/2.4.18 (Ubuntu)
X-Author: http://www.cnblogs.com/go2bed/
Vary: Accept-Encoding
Content-Length: 1180
Connection: close
Content-Type: text/html SERVER_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.7
SERVER_PORT=80
HTTP_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 ;
}
效果:
一个 say hello 的动态网页
Linux/Windows,Python ,头部需要加Python可执行文件的位置。对于Windows,则可能是 #!C:/Python27/python.exe 。
#!/usr/local/bin/python
import os
import urllib
import sys
import cgi
print '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")) > )
{
printf("<h1>Hello %s</h1><br />\n", query + );
}
printf("<form action=\"\" method=\"GET\"><input type=\"text\" name=\"name\" autofocus/><input type=\"submit\"/></form>"); return ;
}
执行任意命令的Webshell,及其过程与经验
Linux,shell script
#!/bin/bash echo -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} >&
#ping -c baidu.com
echo -e '\n</pre>\n'
效果:
由于洒家对shell这门精妙的语言不甚了解,以为在shell script中执行一个命令(字符串)直接写上即可,一开始上文加粗的字体写的命令是 ${cmd} >& 。这一个脚本在命令执行的时候有一些奇怪的地方。例如执行 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 $cmd
python -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 sh
ls: cannot access '|': No such file or directory
ls: cannot access 'grep': No such file or directory
ls: cannot access 'sh': No such file or directory
user@localhost:/usr/lib/cgi-bin$ eval ls $pipe grep sh
env_var.sh
test.sh
使用Windows batch script(批处理)写的一个功能有限的webshell
批处理,这个的坑也有点多,而且洒家也不太熟悉,只能写这么多了。
@echo off
echo Content-Type: text/html; charset=GBK
echo. 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^>
几种语言的CGI编程的更多相关文章
- (笔记)Linux下的简单CGI编程
为什么要进行CGI编程? 在HTML中,当客户填写了表单,并按下了发送(submit)按钮后,表单的内容被发送到了服务器端,一般的,这时就需要有一个服务器端脚本来对表单的内容进行一些处理,或者是把它 ...
- C语言写CGI程序
一.CGI概述 CGI(公用网关接口)规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准.Web服务器通过调用CGI程序实现和Web浏览器的交互, 也就是CGI程序接受Web浏览器发送给 ...
- Linux CGI编程基础【整理】
Linux CGI编程基础 1.为什么使用CGI? 如前面所见,任何的HTML均是静态网页,它无法实现一些复杂的功能,而CGI可以为我们实现.如:a.列出服务器上某个目录中的文件,对目录中的文件进行操 ...
- 5种语言混合编程:C++、JS、python、Lisp、汇编
/* 混合C++.JS.python.Lisp.汇编 1种语言,5种语法 */ main { //C++ vector<int> v; v.push(2); putsl(v.size()) ...
- CGI编程
1简介 .CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口,服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间 ...
- CGI编程学习
@CGI编程学习 目录(?)[+] 一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口.通过CGI接口,Web服务器就能 ...
- 雷林鹏分享:Ruby CGI 编程
Ruby CGI 编程 Ruby 是一门通用的语言,不仅仅是一门应用于WEB开发的语言,但 Ruby 在WEB应用及WEB工具中的开发是最常见的. 使用Ruby您不仅可以编写自己的SMTP服务器,FT ...
- Python3 CGI编程实现教程
一.背景说明 虽然很久以前就听说“早期的网站很多通过cgi形式实现”.“C++可通过CGI形式编写网页”,日积月累对CGI也有了一些概念,但一直没真正见过一个实际运行的CGI网站,总归还是有些底气不足 ...
- python CGI 编程实践
文章更新于:2020-03-05 注1:安装 python 参见: python 的安装使用和基本语法 注2:配置 web 环境参见: Windows&linux使用集成环境搭建 web 服务 ...
随机推荐
- 让你fork下来的项目与源项目保持同步
原文在此, 建议阅读, 我把关键步骤抽出来了, 方便概览 (也就是add remote upstream, fetch upstream, rebase, 再push) Step 1: Forking ...
- 关于EJB的理解
这一段时间一直在北京面试,很多都有关EJB的相关问题,于是上网查了各种资料.所以,EJB到底是什么? 简而言之:EJB就是将已编写的软件中的业务类.不放到客户端软件中,而将其打包放入服务器中.以C/S ...
- document.querySelector和querySelectorAll方法
querySelector和querySelectorAll是W3C提供的新的查询接口,其主要特点如下: 1.querySelector只返回匹配的第一个元素,如果没有匹配项,返回null. 2.q ...
- inputType属性
android中inputType属性在EditText输入值时启动的虚拟键盘的风格有着重要的作用.这也大大的方便的操作.有时需要虚拟键盘只为字符或只为数字.所以inputType尤为重要.<E ...
- IDA调试android so文件.init_array和JNI_OnLoad
我们知道so文件在被加载的时候会首先执行.init_array中的函数,然后再执行JNI_OnLoad()函数.JNI_Onload()函数因为有符号表所以非常容易找到,但是.init_array里的 ...
- Android 内容提供者简介
在Android应用中,我们可以使用显式意图(Explicit Intent)来直接访问其他应用的Activity,但是这仅限于Activity的范畴:如果需要使用其他应用的数据,还需要用到另外一种组 ...
- ios 颜色转图片
- (UIImage *)imageWithColor:(UIColor*) color{ CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); ...
- 【读书笔记】iOS-使用Web Service-基于客户端服务器结构的网络通信(一)
Web Service技术是一种通过Web协议提供服务,保证不同平台的应用服务可以互操作,为客户端程序提供不同的服务. 目前3种主流的Web Service实现方案用:REST,SOAP和XML-RP ...
- C#反序化json字符串,不用区分大小写
最近在做第三方对接的项目,接口返回的数据是json格式,并且每个字段都是小写的,而我们程序类中的属性是要求大写的:刚开始想到的是用JavaScriptSerializer,但是这个并不满足需求 就换了 ...
- Windows 编程中的字符串(2)
(1)windows写日志系统 void writeDebugEventLog(TCHAR* pszMessage, WORD wType) { //#ifdef _DEBUG HANDLE hEve ...