.NET中是否有任何预先存在的方法来检测/阻止xpath注入攻击?
我可以预见2个例子,但可能还有更多。
e.g。
"/Some/XPath/" + UntrustedNodeName
如果UntrustedNodeName
为"DoesNotExist | /Some/Other/XPath"
,则可能是攻击。
"/Some/XPath[" + UntrustedFilter + "]"
如果UntrustedFilter
为"1 = 1"
,那么这也可能是攻击。
我不假设我已经涵盖了所有案例!
我猜这两种情况需要用不同的逻辑单独测试。
对于其他类型的攻击,有编码方法和参数化类来减轻风险。对于XPath,我找不到类似的东西。
(除了 - 我确实找到了这个:http://www.tkachenko.com/blog/archives/000385.html但是安装程序没有用)
答案 0 :(得分:3)
正如Michael Kay所说,这里正确的方法是使用XPath变量,但使用内置的.NET API有点棘手。我将在下面提供一个允许您定义XPath变量的(非常简单的骨骼)类的示例。一旦你有了这个,你可以像这样使用它:
VariableContext context =
new VariableContext { { "hello", 4 }, { "goodbye", "adios" } };
// node is a System.Xml.XmlNode object
XmlNodeList result =
node.SelectNodes("/my/field[. = $hello or . = $goodbye]", context);
同一个课程也应与XmlNode.SelectSingleNode()
,XPathNavigator.Select()
,XPathNavigator.SelectSingleNode()
,XPathNavigator.Evaluate()
以及XElement
中的XPath方法一起使用。
这提供了一种将用户提供的数据值合并到XPath中的安全方法,但与Tomalak的答案一样,它没有解决如何允许用户提供整个XPath的问题。我不认为有一种方法可以确定一块XPath是否客观安全,所以如果你担心这会带来安全风险,那么唯一的解决办法就是不要这样做。
这是班级。如果你想让它处理名称空间和类似的东西,那就需要添加。
class VariableContext : XsltContext
{
private Dictionary<string, object> m_values;
public VariableContext()
{
m_values = new Dictionary<string, object>();
}
public void Add(string name, object value)
{
m_values[name] = value;
}
public override IXsltContextVariable ResolveVariable(string prefix, string name)
{
return new XPathVariable(m_values[name]);
}
public override int CompareDocument(string baseUri, string nextbaseUri)
{
throw new NotImplementedException();
}
public override bool PreserveWhitespace(XPathNavigator node)
{
throw new NotImplementedException();
}
public override IXsltContextFunction ResolveFunction(string prefix, string name,
XPathResultType[] ArgTypes)
{
throw new NotImplementedException();
}
public override bool Whitespace
{
get { throw new NotImplementedException(); }
}
private class XPathVariable : IXsltContextVariable
{
private object m_value;
internal XPathVariable(object value)
{
m_value = value;
}
public object Evaluate(XsltContext xsltContext)
{
return m_value;
}
public bool IsLocal
{
get { throw new NotImplementedException(); }
}
public bool IsParam
{
get { throw new NotImplementedException(); }
}
public XPathResultType VariableType
{
get { throw new NotImplementedException(); }
}
}
}
答案 1 :(得分:0)
避免使用字符串连接构建XPath表达式。改为使用参数/变量。
答案 2 :(得分:0)
我认为你可以做到以下几点。
对于应该表示字符串的输入,它很方便XPath中没有转义序列。
从用户输入中删除所有单引号,并仅在表达式模板中使用单引号字符串。您可以安全地注射,因为除了单引号之外无法从单引号字符串中逃脱。
var xpathTmpl = "/this/is/the/expression[@value = '{0}']";
var input = "asd'asd";
var safeInput = input.Replace("'", "");
var xpath = String.Format(xpathTmpl, safeInput);
// -> "/this/is/the/expression[@value = 'asdasd']"
或者相反。相同的效果,更多的反斜杠(至少在C#中)。
var xpathTmpl = "/this/is/the/expression[@value = \"{0}\"]";
var input = "asd\"asd";
var safeInput = input.Replace("\"", "");
var xpath = String.Format(xpathTmpl, safeInput);
// -> "/this/is/the/expression[@value = "asdasd"]"
......当然,这不是100%好,因为你改变了用户的输入。
如果要逐字表示用户输入,则必须将其拆分为您选择的XPath字符串分隔符(例如单引号)并使用XPath的concat()
函数,如下所示:< / p>
var xpathTmpl = "/this/is/the/expression[@value = {0}]";
var input = "asd'asd";
var inputParts = input.Split('\'');
var safeInput = "concat('" + String.Join("', \"'\", '", inputParts) + "')";
var xpath = String.Format(xpathTmpl, safeInput);
// -> "/this/is/the/expression[@value = concat('asd', "'", 'asd')]"
在实用程序功能和动态XPath构建中包装它变得易于管理。
float.Parse()
)和String.Format()
。true()
或false()
)或数值(即1
或0
)插入,这些是然后在布尔上下文中使用时,通过XPath自动强制使用布尔值。