[转载]ColdFusio 安全初探
文章作者:Safer信息来源:[url]www.securityfaq.org[/url] [SecurityFaq Team]
写在前面的话
本人也是ColdFusio爱好者,不过很菜.喜欢ColdFusio的朋友可以加我们的QQ群11371512 ,能提供个CFM空间给偶用用的朋友请联系偶 QQ 7225308 [买不起,偶只要几M的空间测算就好]
简单介绍
提起ColdFusion可能很多国内得朋友都不了解,下面我们先来介绍介绍。ColdFusion是Macromedia ColdFusion MX的简称,是建立动态Web站点和通过Web访问公司资料的强有力的工具。使用强大易用的ColdFusion Markup Language(CFML),Web开发者能够使用多种后台数据库来快速建立和配置复杂的Web应用。ColdFusion同时可以跨平台(核心为java)。
现在的最新版本是ColdFusion MX,ColdFusion MX当前可以对J2EE应用服务器技术的完全支持,能帮助网络应用开发人员轻松地完成对Java平台的再度利用以及应用开发。(Macromedia已推出多跨针对不同j2ee平台的服务器)。
ColdFusion服务器在系统中地位有点像Tomcat,可以作ColdFusion语言的解释器,也可以作为web服务器。当然你也可以不用ColdFusion作为web服务器。那样的话就需要一个配置一个web服务器。[ColdFusion Markup Language = CFML]
前言
CFML因其功能强大,简单易学和对当前所以流行操作系统的支持,以及良好的JAVA扩展。而在国内越来越收到众多程序员的青睐。不过任何语言本身都没有安全性可言,如果编写程序的人本身没有安全意识,那么写出的代码自然就容易犯错。写这篇文章的主要目的是给初学CFML编程的朋友们提个醒,从一开始就要培养安全编程的意识,不要犯不该犯的错误,避免可以避免的损失。另外,我也是初学者,如有错误或其它意见请发E-mail赐教 <[email]54safer@gmail.com[/email]>。
应用程序保护
为应用程序加上安全防护,保护我们的程序不被他人非法使用(比如web程序的管理界面),这里我们举个以SESSION验证的小例子。大家也可以根据需要构建一套自己的应用程序安全防护功能。
1.密码保护:
<!--- Code By Safer --->
<cfset request.passwordadmin="safer"><!--- 设定密码为safer --->
<CFIF IsDefined("Form.Login")>
<cfif form.s_password is request.passwordadmin><!--- 判断用户输入密码是否和我们设定的一样 --->
<CFSET SESSION.Auth = StructNew()>
<CFSET SESSION.Auth.IsLoggedIn = "Yes">
</cfif>
</CFIF>
<CFIF NOT IsDefined("SESSION.Auth.IsLoggedIn")><!--- 如果没登陆返回登陆页面 --->
<form action="5.cfm" method="post"><input type="password" name="s_password">
<input type="submit" name="Login" value="Submit">
</form>
<cfelse>
<cfoutput>判断为管理员后,加入你的管理程序代码</cfoutput><!--- 登陆成功后显示的页面 --->
</CFIF>
2.限制IP登陆:
<CFIF #left(cgi.remote_addr,7)# is "192.168">
<!--- 你要显示的代码 --->
<cfelseif #left(cgi.remote_addr,7)# is not "192.168">
<CFlocation url = "[url]http://www.yahoo.com[/url]">
</cfif>
3.和数据库结合的密码保护
大家熟悉的论坛的管理程序就是基于这样的
防止跨站脚本攻击
我们所说跨站脚本是指在远程WEB页面的html代码中插入的具有恶意目的的数据,用户认为该页面是可信赖的,但是当浏览器下载该页面,嵌入其中的脚本将被解释执行,有时候跨站脚本被称为"XSS",这是因为"CSS"一般被称为分层样式表,这很容易让人困惑,如果你听某人提到CSS或者XSS安全漏洞,通常指得是跨站脚本。
目前大多数的有安全意识的web程序通常采用如下3种手段来防止XSS攻击
1.在用户输入的字符中禁止html语句
2.只允许特殊的标记,用这种标记来代替html标签产生的效果
3.从html代码中过滤掉动态脚本
在CFML中我们可以使用 HTMLCodeFormat 或 HTMLEditFormat() 函数是将HTML代码转换成安全的格式显示, 比如"<"会被换成"<",还可以使用替换的方法将跨站脚本中要用到的关键字替换掉[下面给出了小例子]。
:
text = replace(text, "<", "<", "ALL");
text = replace(text, "#chr(10)#", "<br>", "ALL");
text = replace(text, "#chr(13)#", "", "ALL");
[跨站脚本千变万化,还会以不同的进制来提交。这就需要我们的程序员仔细的过滤拉]
表单数据效验
1.基本的服务端效验
服务器端效验通常是由一组或几组<CFIF>语句来完成,它检查每个字段和数据类型。如果其中一个失败可用<CFABORT>函数终止执行,或者用<CFLOCATION>函数使得用户重定向到另一页面。
<CFIF isdefined("form.userid")><!--- 判断是否存在重From提交来的userid变量 --->
Error!
<CFELSE NOT Len(Trim("form.userid"))><!--- 判断提交上来的userid长度 --->
<CFABORT><!--- 终止执行判断 --->
<CFELSE ISNumeric("form.userid")><!--- 判断提交上来的userid类型是否为数字 --->
Go Back!
</CFIF>
2.ColdFusion 嵌入表单效验
为了增加一个效验规则,我们需要增加一个隐藏字段<input type="hidden" name="Name_required" value="错误讯息">如果用户没有填写Name字段,CFML将拒绝提交并返回错误讯息。ColdFusion 支持以下几种效验规则
_date 常用数据格式的日期 例如 MM/DD/YY MM/DD/YYYY
_eurodate 与_date相同(欧洲时间格式)
_float 数字数据,允许小数点
_integer 数字数据,不允许小数点
_range 数值的范围,必须指定最大值或最小值、在VALUE参数中作为MIN MAX
_required 必须字段,不能为空
_time 常用时间格式
3.客户端效验
将<form>替换为<CFFORM>、</form>替换为</CFFORM>即可。
4.CFINPUT效验
例如:<cfinput name="zip" type="text" validate="zipcode" size="10" message="Error">,如果是整数可以用zipcode判断。
CFINPUT的数据效验类型如下:
creditcard 删除空格和破折号,
date 验证表单中的MM/DD/YYYY
eurodate 验证表单中的DD/MM/YYYY
float 验证表单中的数字数据,允许小数点
integer 验证表单中的数字数据,不允许小数点
social_security_number 表单中的社会保险号
telephone 验证一电话号码
time 验证表单中的时间hh:mm:ss.
Zipcode 验证USA的邮编号[我们也可以那里验证是否为整数]
保护cfinclude调用的页面
下面我们谈谈如何保护cfinclude调用的页面[感觉像保存asp中的conn.asp],步骤如下:
1.将要被引用的cfm文件名改为“前面添加一个_”,如inc1.cfm改为_inc1.cfm;
2.在该目录下建立一个Application.cfm,添加下列代码:
<CFIF Left( ListLast( GetTemplatePath(), '\'), 1 ) is '_'>
<CFHTMLHEAD TEXT='<META HTTP-EQUIV="REFRESH" CONTENT="10;URL=../">'>
<SCRIPT LANGUAGE="JavaScript">
alert("Access Denied");
self.location='../';
</SCRIPT>
<CFABORT>
</CFIF>
3.这样,只有使用cfinclude或是自定义tag时,才可使用到_inc1.cfm,禁止用户直接访问该_inc1.cfm。
防范SQL注入
如果我们的CFML程序没有完善,而程序员又没将错误讯息处理好,错误讯息就会毫无保留的显示在页面上[当然其中包括许多重要的信息,比如数据库名称、版本、资料表名等等],下面就我们常用查询函数 cfquery 来举个例子。
<CFQUERY NAME="movie" DATASOURCE="ows">
SELECT * FROM Films WHERE FilmID=#URL.FilmID#
</CFQUERY>
Sql查询语句中的FilmID来源于我们重URL提交的ID号,一般情况下用户提交的都是[url]http://127.0.0.1/movie/show.cfm?FilmID=1[/url] 此时的sql查询语句是 SELECT * FROM Films WHERE FilmID=1但是如果少数用户恶意提交 [url]http://127.0.0.1/movie/show.cfm?FilmID=1;DELETE[/url] Films 此时的sql查询语句变为SELECT * FROM Films WHERE FilmID=1;DELETE Films 这里我们仅仅举例说明下危害,通过数据库本身的函数和例如union等的话.危害更大[详细的利用方法这里不多说,想知道的请到[url]www.securityfaq.org[/url]了解]。下面我们来试着对FilmID进行过滤,当不存在FilmID或FilmID不为数字的情况下都将出现我们定义的错误提示。
<CFIF IsDefined("URL.FilmID")
AND NOT IsNumeric(URL.FilmID)>
... throw an error or something ...
</CFIF>
当然我们还可以对sql语句本身做设置
<CFQUERY NAME="movie" DATASOURCE="ows">
SELECT * FROM Films WHERE FilmID=<CFQUERYPARAM VALUE="#URL.FilmID#" CFSQLTYPE="CF_SQL_INTEGER">
</CFQUERY>
上面的例子中,我们在WHERE条件里加入了 CFQUERYPARAM 的TAG,在此卷标属性中的CFSQLTYPE用来指定这个变量中的型态,如果要指定为字符串,则为CFSQLTYPE="CF_SQL_CHAR".同样CFQUERYPARAM 函数也可以运用在cfinsert,cfupdate等 与数据库操作有关的函数中[CFQUERYPARAM函数的详细说明见后门。]。在过滤中常用的函数还有 Trin() 消除任何额外的空格 Len() 判断长度 等,大家下来慢慢体会。现在我们来看看 <cfqueryparam> 得语法,它主要有两个属性.
1) 数值 (VALUE)
2) 类型 (CFSQLTYPE)
你可以重下面我们给的举例中,了解cfqueryparam的是很容易使用的
例1 SELECT * FROM Table WHERE birthday = <cfqueryparam value=”#createODBCDate(form.birthday)#” cfsqltype=”cf_sql_date”>
例2 SELECT * FROM Table WHERE username = <cfqueryparam value=”#session.username#” cfsqltype=”cf_sql_char”>
例3 SELECT * FROM Table WHERE id = <cfqueryparam value=”#URL.hits#” cfsqltype=”cf_sql_integer”>
正如你所看到的,它相当的简便。需要说明的是你也可以在数值中使用CF Functions,就像我们在第一个例子中使createODBCDate()一样。
类型: (CFSQLTYPE)的属性可以使用下面各种类型
• CF_SQL_BIGINT
• CF_SQL_BIT
• CF_SQL_CHAR
• CF_SQL_DATE
• CF_SQL_DECIMAL
• CF_SQL_DOUBLE
• CF_SQL_FLOAT
• CF_SQL_IDSTAMP
• CF_SQL_INTEGER
• CF_SQL_LONGVARCHAR
• CF_SQL_MONEY
• CF_SQL_MONEY4
• CF_SQL_NUMERIC
• CF_SQL_REAL
• CF_SQL_REFCURSOR
• CF_SQL_SMALLINT
• CF_SQL_TIME
• CF_SQL_TIMESTAMP
• CF_SQL_TINYINT
• CF_SQL_VARCHAR
上传问题
最近各种版本的上传均出现了重大的安全漏洞,很多由asp php jsp编写的WEB程序纷纷被拉下马。作为一名优秀的程序员当然要尽力保证我们程序的安全性,ColdFusion本身并无那些上传的问题,但由于程序员的疏忽还是会留下隐患,下面我们举例说明。
<cffile action="upload" filefield="file1" destination="#form.path#" nameconflict="overwrite">
<!--- 这是我们重国内某程序员编写的PubWeBlog中的上传文件内的关键代码 --->
下面我来详细说明下[考虑到像偶一样的CFML菜鸟不少 ^_^]
<cffile action="upload"
filefield="file1" 指定上传的文件名
destination="#form.path#" 指定文件的目的位置
nameconflict="overwrite"> 如果文件存在则覆盖文件
不知道现在大家看出什么问题没有?大家觉得他有过滤上传文件类型吗?根本不需要像asp上传那么麻烦直接上传我们的CFML SHELL 不就OK拉!所有用户输入的数据均是有害的,不认真过滤的话早晚要出事哦。我们来限制上传文件的类型
<cffile action="upload"
filefield="file1" 指定上传的文件名
destination="#form.path#" 指定文件的目的位置
nameconflict="overwrite"如果文件存在则覆盖文件
accept="image/gif,image/jpeg"> 限制仅为 gif jpg的文件类型才能上传
Sandbox Security
使用ColdFusion Administrator中的Sandbox Security来提升安全性。可以对下列资源进行限制
Data Sources --- 数据源
CF Tags -------- CF标签
CF Functions --- CF函数
Files/Dirs ----- 文件/目录*
Server/Ports --- IP/端口**
*[按照默认设置,一个子目录将继承父目录的Sandbox设置,如果子目录改变设置就会覆盖掉重父目录继承的Sandbox设置]
**[限制你的ColdFusion页面访问某些IP和端口,]
修改CFML默认的扩展名
大家都知道ColdFusion網頁預設的副檔名是cfm或cfc,然而因為某些因素你可能想更改副檔名,如AVC或XES等讓人看不懂的獨特副檔名,這時候你就可以找web_root\WEB-INF\web.xml來設定了。
大家都知道ColdFusion的扩展名是CFM或CFC,然如果因为某些因素想更改扩展名怎么办呢?Let’s Go![嘻嘻,偷笑几下---如果我把后缀修改为asp或者jsp呢,^_^],想改扩展名很简单。
1.找到CFusionMX\wwwroot\WEB-INF\web.xml 然后编辑它[记得做个Bak]
2.新增个servlet,示范为增加扩展为*.asp
<servlet-mapping>
<servlet-name>CfmServlet</servlet-name>
<url-pattern>*.asp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CfmServlet</servlet-name>
<url-pattern>*.asp/*</url-pattern>
</servlet-mapping>
3.保存web.xml,然后重新启动ColdFusion Server就大功告成了。
取消CFML预设的浏览URL目录档案设置
其实这个设置是一个巨大的风险,在ColdFusion网页中一般预设的默认页面格式不外忽index.cfm、default.htm等;但是如果我们web目录中某个目录找不到这些默认页面格式就会将让前URL下的目录档案全部一一列出来。所以嘛最好取消这个设置,安全第一
1.打开CFusionMX\runtime\servers\default\SERVER-INF\default-web.xml
2.查找
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>jrun.servlet.file.FileServlet</servlet-class>
<init-param>
<param-name>browseDirs</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
3.将<param-value>true</param-value>的true修改为false就可以了,记得重启。哦
设定ColdFusion的虚拟目录
ColdFusion和IIS一样也有虚拟目录的功能,例如:我要将d:\www\safer\对应到[url]http://www.securityfaq.org/safer[/url]
1.编辑CFusionMX\wwwroot\WEB-INF\jrun-web.xml
2.建立一个虚拟目录
<virtual-mapping>
<resource-path>/safer/*</resource-path>
<system-path>d:\www\safer</system-path>
</virtual-mapping>
3.保存然后重启ColdFusion Server,即刻生效。
可能有人要问为什么要设置虚拟目录呢?这样做的一大好处就是可以让使用者不知道实际的文件目录结构和路径,重另一方面来说也提高了安全性
最后添加一点,投稿的时候都给忘记了。在ColdFusion MX 7下,我们可以编辑neo-security.xml [位于WEB-INF/cfusion/lib]
对一些敏感的SQL查询语句给过虑,不过这样并不见得万无一失!入侵者可以通过转化SQL语句为16进制或其他方法来跳过验证。
<var name=";.*(select|insert|update|delete|drop|alter|create)">
<string>SQL_INJECTION_ATTEMPT</string>
</var>
想要我们的程序安全可靠,还是需要有良好的编程习惯和严谨的作风,如此而已!
行文仓促,技术有限,文章如果有误,望高手来[url]www.securityfaq.org[/url] 赐教 CFM QQ群11371512
页:
[1]