【问题标题】:Is making an asp:Button control invisible enough to be sure users won't be able to click it?是否使 asp:Button 控件不可见以确保用户无法单击它?
【发布时间】:2014-06-05 14:47:22
【问题描述】:

我正在制作一个简单的网站,列出某个文件夹中的文件。如果用户有管理员权限,用户可以点击“删除”按钮删除文件。

在我的 .aspx 文件中,我有以下代码:

<asp:Button runat="server" Text="Delete" OnCommand="FileList_Delete"
            CommandArgument='<%#Eval("FilePath")%>' Visible='<%CurrentUserIsAdmin()%>' />

所以如果CurrentUserIsAdmin()返回false,按钮将不会被渲染。

按钮呈现如下:

<input type="submit" name="ctl00$ctl00$MainContent$LocalMainContent$FileList$ctrl0$ctl17" value="Delete" />

我的问题是:如果用户修改网页客户端以单击此不可见按钮,我能否确定此方法可以安全抵御已知代码攻击?还是我必须在代码隐藏中采取预防措施并在按钮单击事件中验证用户的权限?

【问题讨论】:

  • 只有在 visible 为 true 时才呈现按钮。否则它根本不包括在内。

标签: c# asp.net security webforms authorization


【解决方案1】:

是的,将按钮的 Visible 属性设置为 false 就足以防止引发其 ClickCommand 事件,只要您不关闭默认的 WebForms 安全功能 em>。

您可以通过使用与呈现的&lt;asp:Button&gt; 相同的name 临时将始终可见的&lt;input&gt; 元素添加到您的.aspx 来轻松测试这一点:

<input type="submit"
       name="ctl00$ctl00$MainContent$LocalMainContent$FileList$ctrl0$ctl17"
       value="Fake Delete" />

当真正的删除按钮不可见时,单击虚假的删除按钮。您应该得到一个“无效的回发或回调参数。事件验证已启用...”异常。

重要提示:

  • 不要在if (!IsPostBack) 块内将按钮的Visible 属性设置为false,因为攻击者有可能绕过该检查。请参阅this answer 了解更多信息。
  • 必须启用 ASP.NET 事件验证(默认情况下)。所以不要通过将EnableEventValidation="False" 添加到@Page 指令或将&lt;pages enableEventValidation="false" /&gt; 添加到Web.config 来关闭它。
  • 永远不要通过将EnableViewStateMac="False" 添加到@Page 指令或将&lt;pages enableViewStateMac="false" /&gt; 添加到Web.config 来禁用视图状态验证。 This would allow an attacker to tamper with the hidden __EVENTVALIDATION field 并做其他令人讨厌的事情。
  • 如果您选择从标准 Button 控件派生自定义 Button 服务器控件,请确保将 [SupportsEventValidation] 属性添加到派生类。
  • 如果您选择从头开始创建自定义 Button 服务器控件,请在适当的位置调用 RegisterForEventValidationValidateEvent

【讨论】:

  • 感谢安全提示!
  • 明确一点,控件的Visible 属性不能用于“防止其ClickCommand事件被引发”。声称它确实有点误导。从一般的安全角度来看,重要的是要认识到控件的“不可见性”(不呈现)本身并不会阻止有效的POST 触发事件处理程序(在服务器上运行代码),即使具有安全功能启用。根据您的具体情况,这可能是也可能不是问题。
  • @OskarLindberg:你能举个例子来支持你的说法吗?
  • 我不确定您所说的“示例”是什么意思。显然,服务器(框架、ASP.NET 等)并不关心控件是否呈现给客户端。原则上,服务器端应用程序完全依赖请求中的数据来确定它是否有效以及要做什么。使用 Fiddler 或其他工具很容易获取有效请求,然后设置控件“Visible="False"”,重新发出相同的请求并观察应用程序将其视为有效,而不管某些按钮控件的可见性如何。
  • @OskarLindberg:您的方案要求首先呈现页面,并将 Visible 设置为 true。如果 Visible 从未为特定用户设置为 true 并且 ViewStateUserKey 设置正确(应该始终设置为防止 CSRF 攻击),那么您是否同意该用户不能点击按钮?
【解决方案2】:

他们根本看不到按钮,甚至“收到”它。您的服务器不会生成任何发送给此人的按钮代码。

你必须这样想。用户永远不会看到任何 asp 代码或能够处理它。他们只接收 html。您可以通过查看 html 并查看生成的内容来进一步确保这一点。

所以在这方面你是安全的。

【讨论】:

  • 如果你使用 Fiddler 之类的东西来篡改请求,让它看起来像回发是由不可见的按钮引起的,会发生什么?我希望事件验证或其他一些服务器端进程能够捕获它,但我现在无法测试。
  • 啊我还没有遇到提琴手。我也会调查一下。
【解决方案3】:

我的问题是:如果用户修改网页客户端以单击此不可见按钮,我能否确定此方法可以安全抵御已知代码攻击?或者我必须在 CodeBehind 中进行预防并在按钮单击事件中验证用户权限?

我个人也会在点击事件中添加另一段代码。验证点击来自有权点击该按钮的用户。

您还可以从后面的代码中添加一个按钮,如下所示(假设您将此按钮放入名为 pnlButtons 的面板中):

Button btnDeleteList = new Button();
btnDeleteList.Text = "Delete List";
btnDeleteList.Click += btnDeleteList_Click;
pnlButtons.Controls.Add(btnDeleteList);

换句话说,如果用户是管理员 - 添加一个按钮,如果用户不是管理员 - 不要添加。在这种情况下,您不必玩弄可见性。

希望这会有所帮助。

【讨论】:

  • 这是相当多的工作,更容易出错,并且不再安全。用户无法单击不可见的按钮。它不包含页面中的按钮并使用 CSS 不显示它,而是实际上根本不将按钮的代码发送给客户端。
  • Servy, - 为什么要向客户端发送一个按钮,然后通过 CSS 禁用它? - 如何让静态(在页面上)的东西更安全,而不是在客户端甚至不知道的情况下在服务器端动态制作东西?我很好奇,好像我会遵循你的逻辑,然后我一直在基于一个完全前提进行编程,然后需要改变我的习惯。
  • 你不会想通过 CSS 禁用它,我从来没有说过你会这样做。我说过让它在 ASP 中不可见并不是这样做的,而是实际上并没有呈现它。在 ASP 中将其设为静态意味着您无需担心在每次回发时重新创建它,在预渲染阶段添加任何单击处理程序,并且您可以使用标记而不是代码写出 HTML。 真的很容易不完全正确地让动态添加的按钮正确调用它们的处理程序。这两种方法都是安全的,因此您应该使用更简单的一种。
  • 我明白你的意思。如果我错了,请纠正我:如果您的页面上有一定数量的按钮,并且您只想控制谁点击了什么,那么您描述的方式就是这样做的方式。但是,如果您有一个完全动态的页面,并且您事先不知道最终要获得多少控件,那么您会怎么做呢? (例如,我说的是显示文件并为每个文件分配一个按钮以删除该特定文件)请原谅我的编辑,因为我不习惯按 Shift+Enter 进入新行。
  • 不,这不是最好的方法。最好的方法是将所有按钮放在标记中,并根据谁拥有什么权限来设置可见性。它更容易且不易出错。这种方法不必要地给程序增加了一堆额外的工作和脆弱性。
猜你喜欢
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 2010-12-03
  • 2011-10-16
  • 2018-12-08
  • 1970-01-01
  • 1970-01-01
  • 2011-01-07
相关资源
最近更新 更多