I want to store user's input on my database. The user can write texts with html tags to style his texts.
I want to remove potential malware like javascript and so on. Instead of checking every string property in the class by hand, I want an object-extension which walks through every string property and replace potential malware...
My approach supports:
class TestClassStringProperties
{
public TestClassStringProperties()
{
MyProp = "123";
}
public string MyProp { get; set; }
}
class TestClassNestedProperties
{
public TestClassNestedProperties()
{
NestedType = new TestClassStringProperties();
MyProp = "123";
}
public string MyProp { get; set; }
public TestClassStringProperties NestedType { get; set; }
}
class TestWithCollectionOfNestedProperties
{
public TestWithCollectionOfNestedProperties()
{
NestedPropertiesCollection = new List<TestClassStringProperties>();
}
public ICollection<TestClassStringProperties> NestedPropertiesCollection { get; set; }
}
But it fails with this:
class TestClassWithStringCollection
{
public TestClassWithStringCollection()
{
Strings = new List<string> {"123", "123", "123", "123"};
}
public ICollection<string> Strings { get; set; }
}
Extensionmethod:
public static class ObjectExtension
{
private static HashSet<int> _vistedNestedTypes;
public static void SanitizeJavaScriptFromAllPublicStringProps(this object obj)
{
_vistedNestedTypes = new HashSet<int>();
Sanitize(obj);
}
private static void Sanitize(object obj)
{
var properties = obj.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
if (ProduceStackOverflow(obj))
return;
foreach (var property in properties)
{
CollectionBehaviour(obj, property);
if (property.PropertyType.GetTypeInfo().IsClass)
if (property.PropertyType == typeof(string))
{
// If not writable then cannot null it; if not readable then cannot check it's value
if (!property.CanWrite || !property.CanRead)
continue;
var mget = property.GetGetMethod(false);
var mset = property.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null || mset == null)
continue;
property.SetValue(obj, "HACKED"); // I remove evil code at this place...
}
else
{
NestedTypeBehaviour(obj, property);
}
}
}
private static void NestedTypeBehaviour(object obj, PropertyInfo p)
{
var pp = p.GetValue(obj, null);
if (pp != null && !_vistedNestedTypes.Contains(pp.GetHashCode()))
{
Sanitize(pp);
_vistedNestedTypes.Add(pp.GetHashCode());
}
}
private static void CollectionBehaviour(object obj, PropertyInfo p)
{
if (typeof(IEnumerable<object>).IsAssignableFrom(p.PropertyType))
{
var items = (IEnumerable) p.GetValue(obj, null);
var enumerable = items as IList<object> ?? items.Cast<object>().ToList();
var cnt = enumerable.Count;
for (int i = 0; i < cnt; i++)
{
var a = enumerable[i];
Sanitize(a);
enumerable[i] = a;
}
}
}
private static bool ProduceStackOverflow(object obj)
{
if (!_vistedNestedTypes.Contains(obj.GetHashCode()))
{
_vistedNestedTypes.Add(obj.GetHashCode());
return false;
}
return true;
}
}
After executing the extension, my strings are "123" in the collection and not "HACKED" as I would expect.
Thank you in advance.
Aucun commentaire:
Enregistrer un commentaire