繁体   English   中英

搜索文本框的XSS脚本

[英]XSS scripting for Search textbox

我有一个文本框,用于搜索站点内的数据。 我的客户想要什么,

1)在搜索字段中输入任何文本,然后单击搜索符号。

2)使用像“Burp”这样的Web代理工具进入服务器的请求

3)使用当前脚本附加参数

test<~script>confirm(123)<~/script>

这里发生的是

advesary输入的XSS脚本会在没有任何输入的情况下反映在响应中。 请看下面的图片,你会得到一个想法: -

![在此处输入图像说明] [1]

伙计们,如果您需要更多相关信息,请与我们联系。 请帮助伙计们,任何帮助将不胜感激。 我想从服务器端停止攻击。

HTML和JS代码: -

  <asp:TextBox ID="txtSearch" runat="server" class="txtfld-search" oncopy="return false" oncut="return false" onpaste="return false"></asp:TextBox>

JS代码: -

<script type="text/javascript">
$(document).ready(function () {
    $('#ctl00_topNavigation_txtSearch').keyup(function () {
        var $th = $(this);
        $th.val($th.val().replace(/[^.%a-zA-Z0-9 ]/g,
        function (str) {
            alert('Special characters not allowed except %');
            return '';
        }));
    });
});

另见后面的代码: -

protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{
    Response.Redirect("search.aspx?tx=" + txtSearch.Text);
}

另外,请参阅搜索部分的代码: -

private void SearchResult()
{
    DataTable dt;

    if (Session["Search"] == null)
    {
        ResXResourceReader reader = new ResXResourceReader(Server.MapPath("~/App_GlobalResources/Strings.en-US.resx"));
        IDictionaryEnumerator id = reader.GetEnumerator();
        string sResourceFile = Server.MapPath("~/App_GlobalResources/Strings.en-US.resx");
        XmlDocument xmlResource = new XmlDocument();
        xmlResource.Load(sResourceFile);

        XmlNodeList elmData = xmlResource.SelectNodes("//root/data");

        dt = new DataTable();
        dt.Columns.Add(new DataColumn("ID", System.Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Title", System.Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Description", System.Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Url", System.Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Link", System.Type.GetType("System.String")));

        foreach (XmlElement element in elmData)
        {
            DataRow dr = dt.NewRow();
            dr["ID"] = element.GetAttribute("name");
            //dr["Title"] = element.GetAttribute("name");
            XmlNodeList sDescription = element.SelectNodes("value");
            dr["Title"] = sDescription.Count > 0 ? sDescription.Item(0).InnerText : string.Empty; ;
            dr["Description"] = string.Empty;
            XmlNodeList sUrl = element.SelectNodes("comment");
            if (sUrl.Count > 0)
            {
                Int32 sPgTitle = sUrl.Item(0).InnerText.LastIndexOf(".") + 1;
                if (sPgTitle > 0)
                {
                    dr["Url"] = sUrl.Item(0).InnerText;
                    //dr["Url"] = Request.Url.Host.ToLower() + "/rbank/" + sUrl.Item(0).InnerText;
                    dr["Link"] = string.Empty;
                }
                else
                {
                    dr["Link"] = sUrl.Item(0).InnerText;
                }
                dt.Rows.Add(dr);
            }
        }
        //foreach (DataRow dr in dt.Rows)
        //{
        //    DataRow[] rDesc = dt.Select("Link <> ''");
        //    for (int i = 0; i < rDesc.Length; i++)
        //    {
        //        DataRow[] rTitle = dt.Select("ID = '" + rDesc[i]["Link"] + "'");
        //        if (rTitle.Count() > 0)
        //        {
        //            rTitle[0]["Description"] = rDesc[i]["Title"];
        //        }
        //    }
        //}

        DataRow[] drDelete = dt.Select("Link <> ''");
        foreach (DataRow drCheck in drDelete)
        {
            dt.Rows.Remove(drCheck);
        }
        dt.TableName = "FilterValues";
        reader.Close();
        Session["Search"] = dt;
    }
    else
    {
        dt = Session["Search"] as DataTable;
    }
    DataView dv = new DataView();
    dv.Table = dt;
    **dv.RowFilter = "Description LIKE ('%" + Request.QueryString["tx"].Trim().ToLower() + "%') or Title LIKE ('%" + Request.QueryString["tx"].Trim().ToLower() + "%')";**
    dv.Sort = "Title ASC";

    dgrdPages.DataSource = dv;
    dgrdPages.DataBind();

    lblSearchWords.Text = Request.QueryString["tx"].Trim();
    lblFilesFound.Text = dv.Count.ToString();
}

我发现dv.RowFilter可以作为一些SQL注入给出。 我想防止这种情况。 请帮忙。

正如其他朋友所提到的,客户端代码很容易被忽略。 因此,我们可以将您使用javascript完成的工作转换为c#,这样添加了我的更多空间并将它们合并为一个:

if (Regex.IsMatch(txtSearch.Text, "[^a-zA-Z0-9 %]"))
            {
                //error
                Response.Redirect("Error.aspx?tx=It's a Shame Dude!");
            }
            else
            {
                //Remove multiple spaces
                String ClearSpaces = Regex.Replace(txtSearch.Text, @"\s+", " ");
                Response.Redirect("search?tx=" + HttpUtility.UrlEncode(ClearSpaces));
            }

不要忘记,正则表达式来自: 这个答案 用于替换多个空格的正则表达式来自这个答案

您的代码有几个问题:缺少输入验证,缺少输出编码,行过滤器注入以及缺乏对客户端\\ Javascript验证概念的理解。

让我们逐一讨论:

  1. 缺少输入验证 :我上面提到的所有攻击和问题都可以使用适当的输入验证来修复。 适当的我指的是基于白名单而不是黑名单 你永远不应该搜索撇号或LT \\ GT之类的特殊字符,总是像你在Javascript中那样查看肯定的白名单 ,并查找允许的值而不是不允许的值。 这样做是因为攻击者总是可以超越程序员并以不同的方式编码他的漏洞。 正如其他人所提到的,ValidateRequest确实执行某种级别的输入验证,但它永远不会被视为单一解决方案,因为有办法绕过它。 请不要尝试搜索不同的漏洞,例如<script其他人建议的<script ,这可以很容易地被绕过(例如: <img onmouseover=alert(1)>而不是你的有效负载)并且是一种不好的做法。
  2. 缺少输出编码 :您的代码实际上易受攻击的原因是这一行:

     lblSearchWords.Text = Request.QueryString["tx"].Trim(); 

    在将它们集成到标签之前,您需要HTMLEncode来自用户的任何值。 例如:

     lblSearchWords.Text = HttpUtility.HtmlEncode(Request.QueryString["tx"].ToString()); 

    这可确保将任何与HTML相关的字符编码为其非可执行值。

  3. 行过滤器注入 :此行实际上容易受到行过滤器注入,而不是SQL注入:

     dv.RowFilter = "Description LIKE ('%" + Request.QueryString["tx"].Trim().ToLower() + "%') or Title LIKE ('%" + Request.QueryString["tx"].Trim().ToLower() + "%')"; 

    您可能知道,语法是基于SQL的,但在这种情况下没有DB,只是容易受到注入攻击的行过滤机制。 这种注入是一个低严重性问题,因为它不允许攻击者做太多事情(不像真正的SQL注入中的命令执行),但如果你的最终用户不能看到表的所有行,这是一个安全问题。 如我所知,没有参数化查询,例如在SQL注入中防止注入的机制,但是如第1节和下一节所述强制执行彻底的输入验证,也可以解决这个问题。

  4. 缺乏对客户端概念的理解\\ Javascript验证 :任何类型的客户端验证都是很好的, 不可信任 无论是谁向你展示了这种技术,都说明了原因。 任何客户端验证可以通过任何代理实用程序(Burp,Fiddler,Paros等)轻松绕过,甚至使用浏览器调试器或插件(按F12激活调试器,Firefox的Firebug就是这样一个增强插件​​的例子)默认调试器)。 只相信cliet-side验证就像给你的房子钥匙给陌生人要求他检查是否有人怀疑是否试图闯入,或者将你的钥匙隐藏在欢迎垫下。 你不能相信这是你唯一的防守。 客户端验证的唯一实际目的是阻止服务器的往返并使您的用户体验更好。 您应该在服务器端代码中实现在JS中创建的相同的基于白名单的验证。 永远记住:服务器端验证 - 强制性,客户端验证 - 很高兴。

希望它有所帮助。

与用户提供的任何值一样,您需要在页面上显示该值时转义该值。

更新search.aspx以在发出作为tx参数传递的值的任何位置使用HttpUtility.HtmlEncode(tx)

OWASP提供了一些有关如何防范此类XSS漏洞的良好指导。 https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

如果您热衷于保护您的网站,那么最好的办法是在页面上启用请求验证:

<@ Page validateRequest="true" %>

如果要在您的网站上启用,请点按此链接:

http://msdn.microsoft.com/en-us/library/hh882339(v=vs.110).aspx

如果你想继续使用更方便的检查,那么在网页上显示之前对数据进行编码就可以了。

您还可以从http://www.microsoft.com/en-us/download/details.aspx?id=28589下载Microsofts AntiXss库。 这样您就可以根据需要保护自己的网站。

希望这可以帮助。

在我看来,你有两个选择。 第一种是在将此文本输入发送到服务器之前,在jQuery代码中解析危险搜索客户端。 我不确定你到底要找什么,但我想你想阻止用户在你的搜索栏中发送特定内容。

防止这种情况的一个好方法是在搜索中搜索特定的内容。 例如,您可以将函数包装为在if语句中将搜索发送到服务器(对于伪代码抱歉):

if(txtinput.indexOf('<script>') === -1 && ...more checks...){
   // send input to server
}

可以链接这些if语句,以便在实际将其发送到服务器之前检查是否存在任何XSS问题。 也就是说,从系统设计的角度来看,这种方法并不是很吸引人。 就像你说的,更好的方法是做这个服务器端。 我对.NET后端并不是特别熟悉,但根据你所包含的代码,我想你可以解析你的txtSearch.text服务器端。 这看起来与上面的答案类似。 基本上,如果文本输入符合某些条件,您只会重定向到该链接。

不幸的是,我不是非常熟悉.NET中的字符串解析和验证,所以我不能给你代码,但它应该看起来像这样,假设你已经写了和isValid函数。

if(isValid(txtSearch.txt)){
   Response.Redirect("search.aspx?tx=" + txtSearch.Text);
} else {
   // Send Error code in response
}

我希望这能有所帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM