github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/winlocal/winlocal_windows_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build windows 16 17 package winlocal 18 19 import ( 20 "slices" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 ) 25 26 func TestInternalScan(t *testing.T) { 27 tests := []struct { 28 name string 29 hashes []*userHashInfo 30 wantErr error 31 expectedFindingsReferences []string 32 }{ 33 { 34 name: "no_hashes_returns_no_findings", 35 hashes: []*userHashInfo{ 36 &userHashInfo{ 37 lmHash: "", 38 ntHash: "", 39 }, 40 }, 41 expectedFindingsReferences: nil, 42 }, 43 { 44 name: "lm_hash_returns_lm_finding", 45 hashes: []*userHashInfo{ 46 &userHashInfo{ 47 lmHash: "irrelevant", 48 ntHash: "irrelevant", 49 }, 50 }, 51 expectedFindingsReferences: []string{ 52 vulnRefLMPassword, 53 }, 54 }, 55 { 56 name: "weak_password_returns_finding", 57 hashes: []*userHashInfo{ 58 &userHashInfo{ 59 lmHash: "", 60 ntHash: "329153F560EB329C0E1DEEA55E88A1E9", // root 61 }, 62 }, 63 expectedFindingsReferences: []string{ 64 vulnRefWeakPass, 65 }, 66 }, 67 { 68 name: "weak_password_and_lm_hash_returns_findings", 69 hashes: []*userHashInfo{ 70 &userHashInfo{ 71 lmHash: "D480EA9533C500D4AAD3B435B51404EE", // root 72 ntHash: "329153F560EB329C0E1DEEA55E88A1E9", // root 73 }, 74 }, 75 expectedFindingsReferences: []string{ 76 vulnRefLMPassword, 77 vulnRefWeakPass, 78 }, 79 }, 80 } 81 82 for _, tc := range tests { 83 t.Run(tc.name, func(t *testing.T) { 84 d := Detector{} 85 result, err := d.internalScan(t.Context(), tc.hashes) 86 if err != nil { 87 t.Fatalf("internalScan(...) unexpected error, got: %v, want: %v", err, tc.wantErr) 88 } 89 90 for _, finding := range result.GenericFindings { 91 if !slices.Contains(tc.expectedFindingsReferences, finding.Adv.ID.Reference) { 92 t.Errorf("internalScan(...) unexpected finding, got: %v, want: %v", finding.Adv.ID.Reference, tc.expectedFindingsReferences) 93 } 94 } 95 }) 96 } 97 } 98 99 func TestBruteforce(t *testing.T) { 100 tests := []struct { 101 name string 102 hashes []*userHashInfo 103 wantMap map[string]string 104 }{ 105 { 106 name: "no_hashes_returns_no_findings", 107 hashes: []*userHashInfo{ 108 &userHashInfo{ 109 username: "user", 110 lmHash: "", 111 ntHash: "", 112 }, 113 }, 114 wantMap: map[string]string{}, 115 }, 116 { 117 name: "lm_not_weak_returns_no_finding", 118 hashes: []*userHashInfo{ 119 &userHashInfo{ 120 username: "root", 121 lmHash: "978A0A1C20E21F373757F7116254AD0B", // AVeryComplexPassword 122 ntHash: "", 123 }, 124 }, 125 wantMap: map[string]string{}, 126 }, 127 { 128 name: "nt_weak_password_returns_finding", 129 hashes: []*userHashInfo{ 130 &userHashInfo{ 131 username: "root", 132 lmHash: "", 133 ntHash: "0CB6948805F797BF2A82807973B89537", // test 134 }, 135 }, 136 wantMap: map[string]string{ 137 "root": "test", 138 }, 139 }, 140 { 141 name: "nt_not_weak_returns_no_finding", 142 hashes: []*userHashInfo{ 143 &userHashInfo{ 144 username: "root", 145 lmHash: "", 146 ntHash: "D5F234DB9AA96CEAC168598BB576C7A6", // AVeryComplexPassword 147 }, 148 }, 149 wantMap: map[string]string{}, 150 }, 151 } 152 153 for _, tc := range tests { 154 t.Run(tc.name, func(t *testing.T) { 155 d := Detector{} 156 gotMap, err := d.bruteforce(t.Context(), tc.hashes) 157 if err != nil { 158 t.Fatalf("bruteforce(...) unexpected error: %v", err) 159 } 160 161 if diff := cmp.Diff(gotMap, tc.wantMap); diff != "" { 162 t.Errorf("bruteforce(...) unexpected diff (-want +got): %v", diff) 163 } 164 }) 165 } 166 }