2013-02-27 68 views
8

我在PowerShell中使用了哈希表,並且發現了一些與訪問項目相關的奇怪行爲。正如我們所知,PowerShell的可分配值的至少三種不同的方式哈希表項:哈希表漏洞(屬性覆蓋)?

$hashtable["foo"] = "bar"  #1 
$hashtable.Item("foo") = "bar" #2 
$hashtable.foo = "bar"   #3 

同時,我們使用了#3語法訪問Hashtable對象本身的屬性,如CountKeysValues等等。如果我們添加一個與內部屬性名衝突的項,PowerShell允許我們這樣做,並且我們實際上不再能夠讀取屬性的值(除了使用Reflection)。

我猜想在密鑰來自不可信任的來源(例如來自外部文件或網絡)的情況下,這可能會對流量控制產生不良影響,並可能被惡意用戶利用。

本段說明問題:

function Get-HashtableProperties($hashTable, $header) 
{ 
    "{0} {1} {0}" -f ("-" * 10), $header 

    "Count      : {0}" -f $hashtable.Count 
    "Keys.Count     : {0}" -f $hashtable.Keys.Count 
    "Values.Count    : {0}" -f $hashtable.Values.Count 
    "Actual Count (Reflection) : {0}" -f $hashtable.GetType().GetProperty("Count").GetValue($hashtable) 

    "`nItems (Keys iteration):" 
    $hashtable.Keys | ForEach-Object { " [ {0} = {1} ]" -f $_, $hashtable.Item($_) } 

    "`nItems (Enumerator iteration):" 
    $enumerator = $hashTable.GetEnumerator() 
    while ($enumerator.MoveNext()) 
    { 
     " [ {0} = {1} ]" -f $enumerator.Current.Key, $enumerator.Current.Value 
    } 
} 

$fileContent = @" 
    Foo = a 
    Bar = b 
"@ 

$maliciousFileContent = @" 
    Foo = a 
    Bar = b 
    Count = 0 
    Keys = 
    Values = 
"@ 

$hashtable = ConvertFrom-StringData $fileContent 
$damagedHashtable = ConvertFrom-StringData $maliciousFileContent 

Get-HashtableProperties $hashtable "Normal Hash Table" 
Get-HashtableProperties $damagedHashtable "Damaged Hash Table" 

輸出:

---------- Normal Hash Table ---------- 
Count      : 2 
Keys.Count     : 2 
Values.Count    : 2 
Actual Count (Reflection) : 2 

Items (Keys iteration): 
    [ Bar = b ] 
    [ Foo = a ] 

Items (Enumerator iteration): 
    [ Bar = b ] 
    [ Foo = a ] 
---------- Damaged Hash Table ---------- 
Count      : 0 
Keys.Count     : 1 
Values.Count    : 1 
Actual Count (Reflection) : 5 

Items (Keys iteration): 
    [ = ] 

Items (Enumerator iteration): 
    [ Count = 0 ] 
    [ Bar = b ] 
    [ Foo = a ] 
    [ Values = ] 
    [ Keys = ] 

問題:有沒有防止這個問題,除了手動檢查任務之前每個鍵的方式和/或當我們需要訪問某些Hashtable屬性的值時,在代碼中處處使用Reflection?

+0

您可以創建自己的方法在添加之前將其過濾掉? 'foreach($ key to $ wanttoadd){if(!(CheckProtectedKeys($ key)){....}}'。爲什麼要使用散列表來存儲一個叫做「Count」的東西?散列表每次只能包含一個項目關鍵字和「count」是一個名字,聽起來更像是你應該在對象中使用的東西(並且在數組中收集)。我看到了這個問題,但我認爲避免這些屬性名稱更容易(在我看來,它不是「 hashtable「-material)^^ – 2013-02-27 21:51:34

+0

@Graimer:我同意使用」Count「作爲散列表鍵的機率很低,但這是一種編程語言語義問題,並且語言用戶可以自由使用將「Count」與他們喜歡的任何含義聯繫起來。在我的情況下,這個問題是相當理論化的,我個人也會避免在真實腳本中使用這個問題。 – 2013-02-27 22:08:06

回答

6

在這種場景,你可以訪問哈希表的計數屬性,像這樣:

C:\PS> $ht = @{Count = 99} 
$ht.psbase.Count 
1 

擴展類型系統在PowerShell中通過這些PS *屬性的對象上提供了幾種不同的看法。詳細信息請參見PowerShell team blog post

+0

直到獲得'$ ht = @ {Count = 99; PSBase = 1。 .5}';)['select'](http://go.microsoft.com/fwlink/?LinkID=113387)可幫助您訪問基礎屬性lik e'Count'和'Keys',但不知道如何在不從表格中移除密鑰的情況下取消隱藏'PSBase'。 – 2013-03-09 15:33:28

+0

是的,但是爲什麼團隊選擇以「PS」作爲其ETS屬性的前綴是有原因的。與「PSBase」的衝突比「Count」更具角色情況。 :-) – 2013-03-09 21:52:11