阅读内容 

CGI教学:CGI安全问题(五)

[日期:2005-04-12] 来源:中国站长学院  作者:郁郁小蝎 [字体: ]
2.7 处理文件名

文件名是提交给CGI脚本的简单数据,但如果不小心的话,却能导致许多麻烦。如果用户输入的名字中包含路径因素,如目录斜杠和双点,尽管期望的是输入一个简单的文件名--例如file.txt--但结果却可能是/file.txt或../../../file.txt。根据Web服务器的安装以及对提交的文件名做什么操作,系统中的所有文件就有可能都暴露给了一个聪明的黑客。

进一步,如果用户输入了一个已有文件的名字或者一个对系统的运行很重要的文件名,怎么办?对如果输入的名字是/etc/passwd或C:\WINNT\SYSTEM32\KRNL32.DLL怎么办?根据在CGI脚本中对这些文件进行什么操作,它们有可能被发送给用户或者被垃圾覆盖了。在Windows 95和Windows NT下,如果不检查反斜杠字符(\),可能会允许Web 浏览器通过UNC文件名访问甚至不在该Web机器上的文件。

如果用户在文件名中输入了不合法的字符怎么办?在UNIX下,任何以句点(.)开头的文件名都是不可见的。在Windows下斜杠(/)和反斜杠(\)都是目录分隔符。很可能不小心写了一个Perl程序,当文件名以管(pipe)(|)开头时,尽管自己以为仅仅是打开了一个文件,实际上却是执行了一个外部程序。如果用户知道怎么办的话,甚至可以把控制字符(例如Escape键或Return键)作为文件名的一部分送给脚本。

更坏的情况是,在shell脚本中,分号用于结束一条命令并开始另一条命令。如果脚本设计目的是cat用户输入的文件,用户可能输入file.txt;rm-rf/作为文件名,导致返回fi1e.txt,然后清除整个硬盘而不经任何确认。

2.8 输入合理,输出却不合理

为了避免所有这些问题,关闭由它们打开的所有安全缝隙,检查用户输入的每个文件名。必须确保输入正是程序预期的输入。

这样做的最好办法是将输入的文件名的每个字符与可接收字符的清单进行比较,如果不匹配就返回一个错误。这比维持一个所有合法字符的清单并比较它们要安全得多——要想让什么字符溜掉太容易了。

以下程序清单是用Perl如何完成这种比较的例子。它允许任何字符字母(大写或小写调)、任何数字、下划线和句点。它还进行检查以确保文件名不以句点开头。这样,该段代码就不允许可以改变目录的斜杠,不允许可以将多条命令放在一行的分号,或者破坏Perl的Open()调用的Pipes了。

程序清单 保证所有字符都是合法的

if (($file_Name =~ /[^a-zA-Z_\.]/) || ($file_Name =~ /^\./)) {
#File name contains an illegal characgter or starts with a period
}

警告

尽管上述程序清单中的代码清除了大部分不合法的文件名,但操作系可能还有一些限制,而该代码没有覆盖到。例如,文件名可以用数字开头吗?或者以下划线开头?如果文件中包含多个句点或者句点后多于三个字符怎么办?整个文件名足够短得能满足文件系统的限制吗?

必须不断向自己提出这种问题。在写CGI脚本时最危险的事是认为用户会遵守指令。其实用户是不会的。保证用户不犯错误是编程者自己的事。

2.9 处理HTML

另外一种看起来无害的但却能导致很大麻烦的输入是在请求用户输入文本信息时得到的HTML。以下的程序清单是一个Perl程序片段;它向任何在$user_Name变量中输入了一个名字的人,例如John Smith,发出问候信息。

程序清单 发出定制的问候脚本

print ("Greetings!<TITLE><BODY>\n"); <BR>print ("Hello,$user_Name! It's good to see you!\n"); <BR>print ("</BODY><HTL>\n"); <BR><BR>想像一下,如果用户不是仅仅输入一个名字,而是输入了<HR><H1><P ALIGN="CENTER">John Smith</P><H1><HR>或想像一下当脚本希望得到用户名时,黑客输入了<IMG SRC=http://www.blue1000.com/article/"/secret/cutekid.gif">,结果是公开了本该保密的信息。允许输入<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>可能很危险。 <BR><BR>比输入简单的<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>修改页面或访问画面更危险的是恶意的黑客可能输入一条<a href="http://www.blue1000.com/bkhtml/c68" title="服务器教程">服务器</a>端的include指令。如果<a href="http://www.blue1000.com/bkhtml/c70/" title="Web服务器教程">Web服务器</a>设置为服从服务器端include,用户就可以输入 <BR><BR><!--#include file="/secret/project/p1an.txt"--> <BR><BR>而不是他的名字,以便看到秘密计划的全部文本,或者用户可以输入<!--#inc1ude fi1e-"/etc/passwd"-->来获取机器的口令文件。可能最坏的情况是黑客可能输入<!--#exec cmd="rm-rf/"-->而不是他的名字。这样上述程序清单中的代码会删掉硬盘上几乎所有内容。 <BR><BR>警告 <BR><BR>由于经常被恶意地使用,<a href="http://www.blue1000.com/bkhtml/c68" title="服务器教程">服务器</a>端的include经常被禁止使用以保护站点免受侵害。现在假定这些都没问题。即使关闭了服务器端的include并且不介意用户能看到自己硬盘上的任何图片或者改变页面显示的外观,也仍然有问题--不仅是针对编程者的,而且针对其他用户。 <BR><BR><a href="http://www.blue1000.com/bkhtml/c20/" title="CGI教程">CGI</a>脚本的一个通常用途是留名册(guestbook):访问站点的顾客可能签个名,让别人知道他们已经在那儿了。一般情况下用户简单地输入他的名字,该名字会在访问者清单中出现。但是,如果将The last signee!<FORM><SELECT>作为用户名输入怎么办?<SELECT>标记将导致Web浏览器忽略位于<SELECT>和一个不存在的</SELECT>之间的所有内容,包括以后清单中加入的任何名字。即使有10个人签了名,仅有前3个会显示出来,因为第三个名字包含一个<FORM>和一个<SELECT>标记。因为第三个签名者在他的名字中使用了<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>标记,他后面的任何名字都不会显示出来。 <BR><BR>对于用户输入<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>而不是普通的文本的情况有两种解决办法: <BR><BR>1)快速但比较粗糙的办法是不允许小于号(<)和大于号(>),因为所有<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>标记必须包含在这两个字符中,所以清除它们(或者如果碰到它们就返回一个错误)是一种防止HTML被提交并返回的简单的办法。下面一行Perl代码简单地清除了这两个字符:$user_Input=~s/<>//g; <BR><BR>2)更精细一点的办法是将这两个字符转换成它们的<a href="http://www.blue1000.com/bkhtml/c22/" title="HTML/JavaScript教程">HTML</a>换码--—种特殊的代码,用于表示每个字符而不使用该字符本身。下面的代码通过全部用<替换了小于符号,用>替换了大于符号,从而完成了转换: <BR><BR>$user_Input=~s/</&1t;/g; <BR>$user_Input=~s/>/>/g; <BR> </div> <div><script type="text/javascript" src="../../bkad/undercontent.js"></script></div> </div> <div style="padding-right:20px;text-align:right;clear:both"> 阅读:<span id="news_hits"></span> 次<br/> 录入:<br/><br/> 【 <a href="../../mail.aspx?ID=6701" target="_blank">推荐</a> 】 【 <a href="javascript:doPrint()">打印</a> 】 </div> <div style="padding-left:20px;clear:both"> 上一篇:<a href="../../bkhtml/2005-04/6700.htm">CGI教学:CGI安全问题(四)</a><br/> 下一篇:<a href="../../bkhtml/2005-04/6702.htm">CGI教学:CGI安全问题(六)</a><br/> <script type="text/javascript" src="../../bkad/underpreandnext.js"></script> </div> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="mframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">相关新闻</span>       </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="mframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">本文评论</span>       <a href="../../remark.aspx?id=6701" target="_blank" style="cursor:hand">全部评论</a> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="mframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">发表评论</span> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> <form id="remarkForm" action="../../remark.aspx?id=6701" method="post" onsubmit="return checkRemark();" style="padding:5px"> <div style="width:220px;float:right;height:140px;overflow:auto"> <ul style="list-style-type:square;;margin-left:1em;line-height:150%"> <li>尊重网上道德,遵守中华人民共和国的各项有关法律法规</li> <li>承担一切因您的行为而直接或间接导致的民事或刑事法律责任</li> <li>本站管理人员有权保留或删除其管辖留言中的任意内容</li> <li>本站有权在网站内转载或引用您的评论</li> <li>参与本评论即表明您已经阅读并接受上述条款</li> </ul> </div> <script type="text/javascript" language="javascript"> function checkRemark() { var form=document.getElementById("remarkForm"); var remarkSize = 200; if (form.body.value=="") { alert("请填写评论内容"); form.body.focus(); return false; } if (form.username.value=="") { alert("请填写姓名"); form.username.focus(); return false; } if (form.body.value.length>remarkSize) { form.body.value = form.body.value.substr(0,remarkSize); showLen(form.body); form.body.focus(); alert("评论内容不可以超过"+remarkSize+"字,已帮你删除多余部分"); return false; } if (form.username.value.length>10) { alert("姓名不可以超过10个字"); form.username.focus(); return false; } form.submit.disabled=true; form.vcode.value = VCode("CGI教学:CGI安全问题(五)"); return true; } function showLen(obj) { document.getElementById("bodyLen").value=obj.value.length; } </script> <input type="radio" name="face" value="1" checked="checked"/><img src="../../pic/face1.gif" alt=""/><input type="radio" name="face" value="2"/><img src="../../pic/face2.gif" alt=""/><input type="radio" name="face" value="3"/><img src="../../pic/face3.gif" alt=""/><input type="radio" name="face" value="4"/><img src="../../pic/face4.gif" alt=""/><input type="radio" name="face" value="5"/><img src="../../pic/face5.gif" alt=""/><input type="radio" name="face" value="6"/><img src="../../pic/face6.gif" alt=""/><input type="radio" name="face" value="7"/><img src="../../pic/face7.gif" alt=""/><input type="radio" name="face" value="8"/><img src="../../pic/face8.gif" alt=""/><input type="radio" name="face" value="9"/><img src="../../pic/face9.gif" alt=""/><br/> <input type="radio" name="face" value="10"/><img src="../../pic/face10.gif" alt=""/><input type="radio" name="face" value="11"/><img src="../../pic/face11.gif" alt=""/><input type="radio" name="face" value="12"/><img src="../../pic/face12.gif" alt=""/><input type="radio" name="face" value="13"/><img src="../../pic/face13.gif" alt=""/><input type="radio" name="face" value="14"/><img src="../../pic/face14.gif" alt=""/><input type="radio" name="face" value="15"/><img src="../../pic/face15.gif" alt=""/><input type="radio" name="face" value="16"/><img src="../../pic/face16.gif" alt=""/><input type="radio" name="face" value="17"/><img src="../../pic/face17.gif" alt=""/><input type="radio" name="face" value="18"/><img src="../../pic/face18.gif" alt=""/><br/> <div style="padding-top:5px"> 点评: <textarea name="body" cols="36" rows="4" onkeydown="showLen(this)" onkeyup="showLen(this)"></textarea> 字数<input type="text" id="bodyLen" size="3" readonly="readonly" style="border-width:0;background:transparent;"/> </div> <div style="padding-top:5px"> 姓名: <input type="text" id="i_username" name="username" value="" maxlength="15" size="10"/> <input type="submit" name="submit" id="i_submit" value=" 发 表 "/> </div> <script type="text/javascript"> var remarkmember = false; var allowremark = true; if (remarkmember){ document.getElementById("i_username").readonly=true; document.write("(限会员登录后发表评论)"); } if (!allowremark){ document.getElementById("i_submit").disabled=true; } </script> <script type="text/javascript" src="../../inc/clientDate.js"></script> <input type="hidden" name="vcode" value=""/> </form> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <iframe src="../../frm_hit.aspx?id=6701&disp=1" style="visibility:hidden;height:0;width:0"></iframe> </td><td width="230" style="padding-left:5px" valign="top"> <div class="lframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">Advertisement</span> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> <script type="text/javascript" src="../../bkad/contentrighttop.js"></script> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="lframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">内容查询</span> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm" style="text-align:center; padding:10px;"> <form method="get" action="../../search.aspx" name="frmSearch" style="display:inline;"> <input type="text" name="keyword" class="inputbg" size="20" style="margin-bottom:5px"/><br/> <select name="where"> <option value="title">标题</option> <option value="content">内容</option> <option value="writer">作者</option> </select> <script type="text/javascript" src="../../inc/clientDate.js"></script> <input type="submit" value="搜索"/><br/> </form> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="lframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">Advertisement</span> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> <script type="text/javascript" src="../../bkad/contentrightmid.js"></script> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> <div class="lframe"> <div class="tl"></div> <div class="tr"></div> <div class="tm"> <span class="tt">本周热门内容</span> </div> <div class="wrapper"> <div class="ml"></div> <div class="mr"></div> <div class="mm"> <ul class="nl"> <li><a href="../../bkhtml/2005-04/6831.htm" target="_blank" title="利用Perl开发Internet/Intranet应用之一">利用Perl开发Internet/Intranet应</a></li> <li><a href="../../bkhtml/2005-04/6829.htm" target="_blank">本地调试PERL CGI程序之一</a></li> <li><a href="../../bkhtml/2005-04/6836.htm" target="_blank" title="利用Perl开发Internet/Intranet应用之二(5)">利用Perl开发Internet/Intranet应</a></li> <li><a href="../../bkhtml/2005-04/6832.htm" target="_blank" title="利用Perl开发Internet/Intranet应用之二(1)">利用Perl开发Internet/Intranet应</a></li> <li><a href="../../bkhtml/2005-04/6830.htm" target="_blank">本地调试PERL CGI程序之二</a></li> <li><a href="../../bkhtml/2005-04/6813.htm" target="_blank">用Perl制作留言本实例之一</a></li> <li><a href="../../bkhtml/2005-04/6833.htm" target="_blank" title="利用Perl开发Internet/Intranet应用之二(2)">利用Perl开发Internet/Intranet应</a></li> <li><a href="../../bkhtml/2005-04/6834.htm" target="_blank" title="利用Perl开发Internet/Intranet应用之二(3)">利用Perl开发Internet/Intranet应</a></li> <li><a href="../../bkhtml/2005-04/6814.htm" target="_blank">用Perl制作留言本实例之二</a></li> <li><a href="../../bkhtml/2005-04/6710.htm" target="_blank" title="CGI教程(7)解码数据发送给CGI脚本之一">CGI教程(7)解码数据发送给CGI脚本</a></li> </ul> </div> </div> <div class="bl"></div> <div class="br"></div> <div class="bm"></div> </div> </td></tr> </tbody> </table> <div id="footer"> <br /><font color="#005c96"><strong>BK网络学院</strong>主要内容:<strong>平面设计教程,网站开发在线教程,网页制作教程,服务器教程,网络编程,数据库教程</strong>等。<br />产业部:</font><a href="http://www.miibeian.gov.cn/"><font color="#0000ff">沪ICP备05019380号 陇ICP备05004709号</font></a><font color="#0000ff"> 公安局:GR6201030003<br />Copyright © </font><a href="/"><font color="#0000ff">BK设计</font></a><font color="#0000ff"> Powered by <a href="/">BK网络学院</a></font> <script src="http://s15.cnzz.com/stat.php?id=54594&web_id=54594" language="JavaScript"></script> <script type="text/javascript">setTimeout("ImgLoad(document.getElementById('content'));",500);</script> <div class="menuskin" id="popmenu" onmouseover="clearhidemenu();highlightmenu(event,'on')" onmouseout="highlightmenu(event,'off');dynamichide(event)" style="Z-index:100"></div> <script type="text/javascript" src="../../inc/menu.js" charset="gb2312"></script> <script type="text/javascript"> jsdone=true; </script> </div> </div> </body> </html>