邪恶八进制信息安全团队技术讨论组's Archiver

kj021320 2007-8-24 03:24

[原创]ASP也使用ORM——给ASP上所有的SQL注入画上句号

文章作者:kj021320
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

[b]注意:本文章首发[url=http://blog.csdn.net/kj021320/archive/2007/08/24/1756858.aspx]無名氏CSDNBLOG[/url],后由原创作者kj021320友情提交到邪恶八进制信息安全团队论坛。[/b]

一般写ASP PHP代码的朋友估计很多都是采用直接操作SQL的吧~
看以下的代码
[code]
<%
  dim conn,rs
  set conn=CreateObject("Adodb.Connection")
  conn.open ....
  set rs=conn.execute("select * from news");
  ...
  遍历 rs....
%>
[/code]

这样实现速度快是肯定的了,但是在结构逻辑上面1条半条语句当然不觉得怎样!语句多了问题也就来了!
参数没过滤啊,SQL存在注入啊等等~OK 现在我们来换个设计模型!
采用 3层结构 + ORM
ORM : OBJECT RELATION MAPPING
那什么是 ORM技术呢? 熟悉JAVA .NET开发的朋友一定很清楚...就是对象关系映射
把表映射为类 字段映射为属性 而记录则映射为对象...现在JAVA的ORM持久层框架N多
例如hibernate ibatis EntityBean(EJB其中一种)

那在ASP上面呢? 我们也一样可以实现.等等介绍

3层结构 : WEB展现层 中间层 持久层

以下有一个news 的表 简单一点的
[code]
create table news(
  id int,
  title varchar(200),
  contect varchar(50000)
)
[/code]
我们把他映射为类
[code]
<%
Class News
  private id,title,contect
  Sub setID(sid)
    id=Cint(sid)
  End Sub
  Function getID
    getID=id
  End Function
  Sub setTitle(stitle)
    title=mid(stitle,1,200)&#39;限制了长度
  End Sub

  ....
End Class
%>
[/code]
然后我们再设计如何操作数据库转换为对象的代码
[code]
<%
Class NewsDataAccessObject
  dim conn,rs,cmd
  &#39;查询一篇新闻
  Function getNewsByID(id)
    set conn=Applcation("connection")&#39;连接池里面获取一个连接
    set cmd=GetCmd() &#39; GETCMD函数实现 return createobject("Adodb.Command")
    selectString="select * from NEWS where id = @id"

    cmd.ActiveConnection = conn
    cmd.CommandType = adCmdText &#39; Const adCmdText=1
    cmd.CommandText = selectString
    &#39;为刚刚的的@id追加参数,常量 adInteger = 3  adParamInput=1
    cmd.Parameters.Append cmd.CreateParameter("@id", adInteger, adParamInput, , id)
    &#39;运行SQL语句 返回结果集合
    set rs=cmd.execute()
    dim anews
    set anew=new News
    if rs.eof then
    else  
      anew.setID(rs("id")&"")
      anew.setTitle(rs("title")&"")
      anew.setContect(rs("Contect")&"")
    end if  
    rs.close
    set rs=nothing
    set cmd=nothing
    set conn=nothing
    set getNewsByID=anew
  End Function
  &#39;插入一篇新闻
  Function addNews(anew)
    dim conn,cmd
    if isempty(anew) then addNews=false
    set conn=Applcation("connection")&#39;连接池里面获取一个连接
    set cmd=GetCmd() &#39; GETCMD函数实现 return createobject("Adodb.Command")
    insertString="insert into NEWS(id,title,contect) values( @id , @title , @contect )"
    cmd.ActiveConnection = conn
    cmd.CommandType = adCmdText &#39; Const adCmdText=1
    cmd.CommandText = insertString
    &#39;为刚刚的的@id @title @contect追加参数,常量 adInteger = 3  adParamInput=1 adVarWChar = 202
    cmd.Parameters.Append cmd.CreateParameter("@id", adInteger, adParamInput, , anew.getID() )
    cmd.Parameters.Append cmd.CreateParameter("@title",adVarWChar, adParamInput, 200 , anew.getTitle() )
    cmd.Parameters.Append cmd.CreateParameter("@contect",adVarWChar, adParamInput, 50000 , anew.getConect() )
   
    &#39;运行SQL语句
    cmd.execute()
    set cmd=nothing
    set conn=nothing
    addNews=true
  End Function
  Function findByTitle(stitle)
    ....
  End Function
  Function getPageNews(page,size)
    ....
  End Function
End Class
%>
[/code]
以上就是对数据库操作然后把结果封装到对象里面 或者把对象写入数据库
这样实现虽然速度上面会稍慢 但是总体逻辑结构非常明显,不需要关心变量是否已经给过滤或者多过滤
而web页面层的设计人员更多的关注于界面方面
以下为提交添加新闻代码
[code]
<%
  dim id,title,contect,anew,dao
  id=Request("id")
  title=Request.Form("title")
  contect=Request.Form("contect")
  set anew=new NEWS
  anew.setID(id)
  anew.setTitle(title)
  anew.setContect(contect)
  set dao=new NewsDataAccessObject
  if dao.addNews(anew) then
    &#39;response.write
    echo "success"
  else
    echo "error"
  end if
%>
[/code]

把新闻查出来显示
[code]
<%
  dim id,dao,anew
  id=Request("id")
  set dao=new NewsDataAccessObject
  set anew=dao.getNewsByID(id)
  if anew.getID()<>"" then
%>
标题:<%=anew.getTitle()%>
内容:<%=anew.getContect()%>

.....
[/code]

以上片段代码如有错漏谢谢指点~~~
使用这样的设计方式就根本不需要像XXXBLOG XXXBBS XXX文章系统那样
忘记Replace(SQL,"&#39;","&#39;&#39;") 而产生injection了!
对于页面的整洁性而言 也不会出现SQL语句,连接等 美工负责好自己的工作然后把对象的属性放到相应的位置就OK
而有可能有朋友会觉得 用户认证方面呢!那更省事了把用户表的用户对象放到session里面就OK
[code]
<%
  if isempty(session("user")) or session("user")="" then
    &#39;跳转
  else
    set auser=session("user")
    echo "欢迎你:" & auser.getName()
%>
[/code]

全文完

我非我 2007-8-24 14:24

ORM的确是为开发时的dao层减少了不少重复造轮子的事情。但是其实和防止注入没什么大作用,该注意那些还是需要注意那些,一步步到最底下都是一样。
如果楼主能够开发出一个asp的ORM框架或者把.net的linq移植到asp上,对开发者来说,倒是一件大大的功劳

夜冷佛 2007-8-24 17:23

吓我一跳,我还以为真的注入真的没戏的.
有点不明白
PHP比ASP安全,速度也快,为什么基本都用ASP呢??

kj021320 2007-8-24 21:01

我觉得ORM 不直接操作SQL语句!把类型都严格限制了这样数字注入是不可能成立的!
而在其他方面 配合 参数绑定的方式 这样注入是100% 杜绝了!
ASP 的ORM框架嘛! 之前有打算写!不过后来放弃了!失败-_-.... 主要是个人觉得ASP现在已经慢慢给淘汰了!

跨平台的都J2EE   而MS都推崇.net了! 新兴的RUBY ON Rails 更是后起之秀~~!ASP也会是淘汰的名单中了

页: [1]
© 1999-2008 EvilOctal Security Team