水如烟

                 顺其自然,水到渠成 LzmTW

文或代码皆是面向初学者.我是爱好者,也是初学者.那些"文章",只按自己理解写,我是不知术语名词的.所以只供参考,也仅供参考.

导航

.NET的变量在代码集中是不安全的

Posted on 2007-11-20 11:39  水如烟(LzmTW)  阅读(2378)  评论(17编辑  收藏  举报

Author:水如烟

.NET的安全性问题是一个综合性的问题,这不是我现在能学习好理解透的,我估计也不是一般的.NET的编码者能够把握住应用好的。

至少,在代码集中,.NET的全局变量,或者说受Private修饰保护的对象,是不安全的。

在现实中有一个传话游戏,其要义是,信息在信息链的传递过程中会失真。.NET也一样,很难保证一个关键的信息在传递的过程中保持“纯洁”而不被潜伏中的攻击而受污染。特别是在大规模的代码集中。

SecureString类
在.NET的设计中,SecureString类应该是安全系数比较高的。它有两个作用,一是赋值后MakeReadOnly以便在后续的传递中不致修改,二是在必要的时候进行销毁。但是用它来传递关键信息,比如密码,还是不安全的。这个类里头有一个m_readOnly As Boolean的Private变量来保存当前实例可否修改的状态,你可以重置该值为False,便可以对它重新修改,MakeReadOnly也就失去了它本身的作用。

ReadOnlyCollection类
它的本义是不能对当前实例的项目进行增删。在它的设计中,用一个list的Private变量来存储当前集合。事实并不能保证它的作用。你甚至可以用自己的list替换了它。

测试代码

Imports System.Runtime.InteropServices
Imports System.Collections.ObjectModel

Public Class NoSecure

    
Public Sub TestSecureString()
        
Dim t As New Security.SecureString
        t.AppendChar(
"A"c)
        t.AppendChar(
"B"c)
        t.MakeReadOnly()

        Console.WriteLine(Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(t)))

        
Dim h As New LzmTW.uSystem.uReflection.TypeHelper(t)
        h.SetMemberValue(
"m_readOnly"False)

        t.AppendChar(
"C"c)

        Console.WriteLine(Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(t)))
    
End Sub

    
Public Sub TestReadonlyCollection()

        
Dim t As New ReadOnlyCollection(Of String)(New String() {"A""B""C"})
        
For i As Integer = 0 To t.Count - 1
            Console.Write(t.Item(i))
        
Next

        Console.WriteLine()

        
Dim h As New LzmTW.uSystem.uReflection.TypeHelper(t)
        
Dim mNowList As New List(Of String)
        mNowList.AddRange(
New String() {"A""B""C""D"})
        h.SetMemberValue(
"list", mNowList)

        
For i As Integer = 0 To t.Count - 1
            Console.Write(t.Item(i))
        
Next

    
End Sub

End Class

上面用到的 TypeHelp类:

TypeHelper.Methods.vb
Imports System.Reflection

Namespace LzmTW.uSystem.uReflection

    Partial 
Class TypeHelper

        
Public Sub SetCurrentObj(ByVal obj As Object)
            
If Not obj Is Nothing AndAlso Not Me.CurrentType.IsInstanceOfType(obj) Then
                
Throw New ArgumentException("实例类型与内部类型不相符")
            
End If

            
Me.gCurrentObjct = obj
        
End Sub

        
Public Function GetMemberValue(ByVal name As StringByVal ParamArray args() As ObjectAs Object
            
Return Me.CurrentType.InvokeMember( _
                name, _
                MemberGetBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Function


        
Public Sub SetMemberValue(ByVal name As StringByVal ParamArray args() As Object)
            
Me.CurrentType.InvokeMember( _
                name, _
                MemberSetBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Sub

        
Public Function MethodInvoke(ByVal name As StringByVal ParamArray args() As ObjectAs Object
            
Return Me.CurrentType.InvokeMember( _
                name, _
                MethodBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Function

        
Public Function NewInstance(ByVal ParamArray args() As ObjectAs Object
            
Dim mParaCount As Integer = args.Length
            
Dim mCtors As ConstructorInfo() = Me.CurrentType.GetConstructors(MethodBinding)

            
For Each ctro As ConstructorInfo In mCtors
                
If ctro.GetParameters.Length = mParaCount Then
                    
Return ctro.Invoke(args)
                
End If
            
Next

            
Return Nothing
        
End Function

        
''' <summary>
        ''' 可以使用*?[abc][!abc],忽略大小写
        ''' </summary>
        Public Function FindMember(ByVal name As StringAs MemberInfo()
            
If String.IsNullOrEmpty(name) OrElse name = "*" Then
                
Return Me.CurrentType.GetMembers(Binding)
            
End If

            
Dim mPattern As String = "*[*?]*"
            
If Not name Like mPattern Then Return Me.CurrentType.GetMember(name, Binding)

            
Dim mArray As New List(Of MemberInfo)
            
For Each m As MemberInfo In Me.CurrentType.GetMembers(Binding)
                
If m.Name.ToLower Like name.ToLower Then
                    mArray.Add(m)
                
End If
            
Next

            
Return mArray.ToArray
        
End Function

        
Private MemberGetBinding As BindingFlags = _
                BindingFlags.Instance 
Or _
                BindingFlags.Public 
Or _
                BindingFlags.NonPublic 
Or _
                BindingFlags.Static 
Or _
                BindingFlags.GetField 
Or _
                BindingFlags.GetProperty 
Or _
                BindingFlags.IgnoreCase

        
Private MemberSetBinding As BindingFlags = _
                BindingFlags.Instance 
Or _
                BindingFlags.Public 
Or _
                BindingFlags.NonPublic 
Or _
                BindingFlags.Static 
Or _
                BindingFlags.SetField 
Or _
                BindingFlags.SetProperty 
Or _
                BindingFlags.IgnoreCase

        
Private MethodBinding As BindingFlags = _
                BindingFlags.Instance 
Or _
                BindingFlags.Public 
Or _
                BindingFlags.NonPublic 
Or _
                BindingFlags.Static 
Or _
                BindingFlags.InvokeMethod 
Or _
                BindingFlags.IgnoreCase
    
End Class

End Namespace


TypeHelper.vb
Imports System.Reflection

Namespace LzmTW.uSystem.uReflection

    
Public Class TypeHelper

        
Private gType As Type
        
Private gCurrentObjct As Object

        
Public ReadOnly Property CurrentType() As Type
            
Get
                
Return gType
            
End Get
        
End Property

        
Public ReadOnly Property CurrentObject() As Object
            
Get
                
Return gCurrentObjct
            
End Get
        
End Property


        
Sub New(ByVal referrenceObj As Object)
            
If Me.IsType(referrenceObj) Then

                
Me.gType = CType(referrenceObj, Type)
            
Else

                
Me.gType = referrenceObj.GetType
                
Me.gCurrentObjct = referrenceObj
            
End If
        
End Sub

        
Sub New(ByVal assembly As AssemblyByVal fullTypeName As String)
            
Me.InternalCreate(assembly, fullTypeName)

            
Me.InternalCheckIsValid(fullTypeName, True)
        
End Sub

        
Sub New(ByVal referrenceType As Type, ByVal typeName As StringOptional ByVal isNestedType As Boolean = False)

            
Dim mAssembly As Assembly = referrenceType.Assembly

            
Me.InternalCreate(mAssembly, typeName)

            
If Me.InternalCheckIsValid(typeNameFalseThen Return

            
Dim mFullTypeName As String = GetFullTypeName(referrenceType, typeName, isNestedType)

            
Me.InternalCreate(mAssembly, mFullTypeName)

            
Me.InternalCheckIsValid(mFullTypeName, True)
        
End Sub

        
Private Sub InternalCreate(ByVal ass As AssemblyByVal fulltypename As String)
            gType 
= ass.GetType(fulltypename, FalseTrue)
        
End Sub

        
Private Function InternalCheckIsValid(ByVal typename As StringByVal throwOnError As BooleanAs Boolean
            
If gType Is Nothing Then
                
If throwOnError Then
                    
Throw New ArgumentException(String.Format("typeName: {0} 不存在"typename))
                
Else
                    
Return False
                
End If
            
End If

            
Return True
        
End Function

        
Private Function GetFullTypeName(ByVal referrenceType As Type, ByVal typeName As StringByVal isNestedType As BooleanAs String
            
Dim mFullName As String = Nothing

            
Dim mRefFullName As String = referrenceType.FullName

            
If isNestedType Then

                mFullName 
= String.Concat(mRefFullName, "+"typeName)
            
Else

                
Dim mLastIndex As Integer = mRefFullName.LastIndexOf(referrenceType.Name)

                mFullName 
= String.Concat(mRefFullName.Substring(0, mLastIndex), typeName)
            
End If

            
Return mFullName
        
End Function

        
Private Function IsType(ByVal instance As ObjectAs Boolean
            
Return instance.GetType.IsSubclassOf(GetType(Type))
        
End Function

        
Public Const Binding As BindingFlags = _
            BindingFlags.Instance 
Or _
            BindingFlags.Public 
Or _
            BindingFlags.NonPublic 
Or _
            BindingFlags.Static 
Or _
            BindingFlags.CreateInstance 
Or _
            BindingFlags.IgnoreCase


    
End Class

End Namespace