c 语言 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 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/)。

13f91c8b88db41f17a592dc7e2dbb37e.png

坑¶

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

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

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

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

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=

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=

Apache/2.4.18 (Ubuntu) Server at 192.168.245.136 Port 80

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

int main()

{

printf("Content-Type: text/html\n\n");

printf("Hello World!\n");

return 0;

}

效果:

8cabb8ac86ac5cb0a1cfde40518e8965.png

一个 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 '

Hello,%s

' % (cgi.escape(urllib.unquote_plus(value)),)

print '''

'''

print os.environ['QUERY_STRING']

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

b95f50304bdf9eac44a8dffe2bc0ee0b.png

另一个 say hello 的动态网页¶

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

#include

#include

#include

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("

Hello %s


\n", query + 5);

}

printf("

");

return 0;

}

d00d279fc5e2b44e5bf2738748158e11.png

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

Linux,shell script

#!/bin/bash

echo -e 'Content-Type: text/html\n'

echo '

I am using cgi (shell script)

'

echo '

'

echo ''

echo ''

echo '

'

echo -e '\n

\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 '


'

eval ${cmd} 2>&1

#ping -c 2 baidu.com

echo -e '\n

\n'

效果:

eabda5f65b0db962e7b39b110befddbd.png

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

File "", line 1

'import

^

SyntaxError: EOL while scanning string literal

cd615d75f634864042788dd2b472f849.png

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

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 "", 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 ^

batch webshell^

echo ^

echo ^

echo ^

echo ^

echo ^

 
 

set ccmmdd=%QUERY_STRING:~4%

set ccmmdd=%ccmmdd:+= %

set ccmmdd=%ccmmdd:^%20= %

echo ^

%ccmmdd%

echo ^

echo ^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值