测试管理之Boa Web Server缺陷报告及其修正方法
白羽 2018-06-28 来源 :网络 阅读 20 评论 0

摘要:本文将带你了解测试管理之Boa Web Server缺陷报告及其修正方法,希望对大家学测试管理有所帮助。


综述

  Boa 作为一种轻巧实用的 WEB 服务器广泛应用于嵌入式设备上,

  但 Boa 对实现动态网页的 CGI  的支持上仍存在一些缺陷,

  本文描述了 Boa 对 CGI 的 Status/Location 的支持的缺陷及其修正方法.

  版本: 所有版本 (0.94.13)

  缺陷: BOA 解析 CGI 应答头时不能完整处理 Status 和 Location

  缺陷描述:

  CGI/1.1 标准规定, CGI 脚本可以通过 Status 设置 HTTP 应答状态(如, Status: 500 Internal Error) 和

  Location 进行地址重定向 (如, Location: www.xxx.com), 而不管它们在应答头中的位置.

  Boa 支持 Stauts 和 Location 两种应答头, 但它的实现仅能正确处理 Stauts 和 Location 在应答第一行的

  CGI 应答. 这将给 CGI 程序的移植带来很多不便, 进而影响 Boa 作为Web Server 的功能的发挥.

  影响功能:

  ASP/PHP/JSP/Perl/... 等的 header, redirect, ... 等都会应用到 Stauts/Location 进行设置应答状态和

  地址重定向. Boa 的该实现将影响 CGI 脚本正常功能的使用.

  缺陷功能对比(对Status/Location的支持程序):

  Apache 1.3.x/2.x         IIS 4.x/5.x/6.X        Boa 0.9x                 thttpd                 mini-httpd

  完全支持                        完全支持                * 部分支持                 完全支持               完全支持

  缺陷分析

  缺陷分析

  CGI 应用程序进行应答时, 可以 HTTP 头进行有限的控制. 如,设置客户端不缓存页面可用下面的 C 脚本,

  HTTP/1.0: printf("Pragma: no-cache\n"); 或

  HTTP/1.1: printf("Cache-Control: no-cache; no-store\n");

  如果, 同时还需要告诉浏览器进行设置 Cookie 和控制相应状态(200 OK) 或地址重定向,

  那么就必须输出多行 http 头控制语句, CGI 支持两个解析头 "Status: " 和 "Loction: ",

  即协议规定, Web 服务器支持解析头时能使用 "Status: " 进行应答状态控制, 使用 "Location: " 进行地址重定向,

  并为应答添加状态头 "HTTP/1.0 302 Moved Temporarily\n" 或 "HTTP/1.1 302 Found\n".

  而不管它们在 CGI 应答头的什么位置.

  分析 Boa Source Code:

  cgi_header.c  Line 82-136 容易发现, Boa 只解析 CGI 应答的第一行, 是否为 "Status: ", "Location: ", 如下所示

23

24         int process_cgi_header(request * req)

25         {

26             char *buf;

27             char *c;

28

29             if (req->cgi_status != CGI_DONE)

30                 req->cgi_status = CGI_BUFFER;

31

32             buf = req->header_line;

33

34             c = strstr(buf, "\n\r\n");

35             if (c == NULL) {

36                 c = strstr(buf, "\n\n");

37                 if (c == NULL) {

38                     log_error_time();

39                     fputs("cgi_header: unable to find LFLF\n", stderr);

40         #ifdef FASCIST_LOGGING

41                     log_error_time();

42                     fprintf(stderr, "\"%s\"\n", buf);

43         #endif

44                     send_r_bad_gateway(req);

45                     return 0;

46                 }

47             }

48             if (req->simple) {

49                 if (*(c + 1) == '\r')

50                     req->header_line = c + 2;

51                 else

52                     req->header_line = c + 1;

53                 return 1;

54             }

55             if (!strncasecmp(buf, "Status: ", 8)) {

56                 req->header_line--;

57                 memcpy(req->header_line, "HTTP/1.0 ", 9);

58             } else if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */

59         #ifdef FASCIST_LOGGING

60

61                 log_error_time();

62                 fprintf(stderr, "%s:%d - found Location header \"%s\"\n",

63                         __FILE__, __LINE__, buf + 10);

64         #endif

65

66

67                 if (buf[10] == '/') {   /* virtual path */

68                     log_error_time();

69                     fprintf(stderr,

70                             "server does not support internal redirection: " \

71                             "\"%s\"\n", buf + 10);

72                     send_r_bad_request(req);

73

74                     /*

75                      * We (I, Jon) have declined to support absolute-path parsing

76                      * because I see it as a major security hole.

77                      * Location: /etc/passwd or Location: /etc/shadow is not funny.

78                      *

79                      * Also, the below code is borked.

80                      * request_uri could contain /cgi-bin/bob/extra_path

81                      */

82

83                     /*

84                        strcpy(req->request_uri, buf + 10);

85                        return internal_redirect(req);

86                      */

87                 } else {                /* URL */

88                     char *c2;

89                     c2 = strchr(buf + 10, '\n');

90                     /* c2 cannot ever equal NULL here because we already have found one */

91

92                     --c2;

93                     while (*c2 == '\r')

94                         --c2;

95                     ++c2;

96                     /* c2 now points to a '\r' or the '\n' */

97                     *c2++ = '\0';       /* end header */

98

99                     /* first next header, or is at req->header_end */

100                    while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end)

101                        ++c2;

102                    if (c2 == req->header_end)

103                        send_r_moved_temp(req, buf + 10, "");

104                    else

105                        send_r_moved_temp(req, buf + 10, c2);

106                }

107                req->status = DONE;

108                return 1;

109            } else {                    /* not location and not status */

110                char *dest;

111                int howmuch;

112                send_r_request_ok(req); /* does not terminate */

113                /* got to do special things because

114                   a) we have a single buffer divided into 2 pieces

115                   b) we need to merge those pieces

116                   Easiest way is to memmove the cgi data backward until

117                   it touches the buffered data, then reset the cgi data pointers

118                 */

119                dest = req->buffer + req->buffer_end;

120                if (req->method == M_HEAD) {

121                    if (*(c + 1) == '\r')

122                        req->header_end = c + 2;

123                    else

124                        req->header_end = c + 1;

125                    req->cgi_status = CGI_DONE;

126                }

127                howmuch = req->header_end - req->header_line;

128

129                if (dest + howmuch > req->buffer + BUFFER_SIZE) {

130                    /* big problem */

131                    log_error_time();

130             fprintf(stderr, "Too much data to move! Aborting! %s %d\n",

131                    __FILE__, __LINE__);

132              /* reset buffer pointers because we already called

133                 send_r_request_ok... */

134              req->buffer_start = req->buffer_end = 0;

135              send_r_error(req);

136              return 0;

137          }

138          memmove(dest, req->header_line, howmuch);

139          req->buffer_end += howmuch;

140          req->header_line = req->buffer + req->buffer_end;

141          req->header_end = req->header_line;

142          req_flush(req);

143          if (req->method == M_HEAD)

144              return 0;

145      }

146      return 1;

147  }

148

149

   

 


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标软件测试之测试管理频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
加入IT交流圈
JAVA工程师交流群 +加入
大数据架构师交流群 +加入
人工智能Python交流群 +加入
WEB/H5前端交流群 +加入
大数据岗位高薪定向就业名额  提前锁定高薪职位
软件测试直通车

  • 资料索取

  • 答疑解惑

  • 技术交流

  • 职业测评

  • 面试技巧

  • 高薪秘籍
海同名师推荐 更多>>
张军 联系TA
10年项目开发经验,精通pc、mobile平台软件开发主流技术和框架
杨成江 联系TA
青春为马 不负韶华
翟健 联系TA
熟悉系大型项目开发业务流程,精通C、Java语言
黄骈 联系TA
认证System Analyst,System Architect
程光淼 联系TA
精通C、C++等语言、智能芯片开发
热门就业培训班 更多>>
【零基础】人工智能+Python全栈开发课程
登顶技术风口浪潮巅峰 年薪百万不是梦
【零基础】JavaEE高级开发工程师课程
小白0基础入学 8000起薪轻松进名企
【零基础】大数据与分布式架构师课程
掌握大数据分布式架构 冲击年薪50W+
测试管理30天热搜词 更多>>
X
免费获取海同IT培训资料
验证码手机号,获得海同独家IT培训资料
获取验证码
提交

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号