@@ -26,8 +26,8 @@ public abstract class Assessment<T extends Scanner, C extends AppConfig> {
2626
2727 private ScanResult firstScanSuccess ;
2828 private ScanResult secondScanSuccess ;
29- private ScanResult thirdScanSuccess ;
30- private ScanResult fourthScanFailure ;
29+ private ScanResult isVulnerableScan ;
30+ private ScanResult isOkScan ;
3131
3232 public Assessment (T successScanner , T failureScanner ) {
3333 this .successScanner = successScanner ;
@@ -54,93 +54,143 @@ public Report run(String clientId, C scannerConfig) {
5454 var start = Instant .now ();
5555 validate (scannerConfig );
5656
57+ try {
58+ return runInternal (clientId , scannerConfig );
59+ }catch (Exception e ){
60+ LOG .error ("Unexpected error:" , e );
61+ var duration = Duration .between (start , Instant .now ());
62+ ReportBuilder reportBuilder = new ReportBuilder (clientId , duration .toMillis () , firstScanSuccess , secondScanSuccess , isVulnerableScan , isOkScan , new HashMap <>(), List .of (e .getMessage ()));
63+ return reportBuilder .Build ();
64+ }
65+ }
66+
67+ private Report runInternal (String clientId , C scannerConfig ) {
68+ var start = Instant .now ();
69+
5770 List <String > errors = new ArrayList <>();
58- LOG .info ("Start initial tests " );
71+ LOG .info ("Start first baseline scan " );
5972 // First scan with successful login
6073 firstScanSuccess = runScan (scannerConfig , successScanner );
74+
75+ LOG .info ("Start second baseline scan" );
6176 // Second scan with successful login, but maybe changes in the page content from login to login
6277 secondScanSuccess = runScan (scannerConfig , successScanner );
63- // Third scan with successful login - means VULNERABLE
64- thirdScanSuccess = runScan (scannerConfig , successScanner );
65- // Fourth scan with failed login - means OK
66- fourthScanFailure = runScan (scannerConfig , failureScanner );
6778
79+ LOG .info ("Start test scan - proof ok" );
80+ // scan with failure - means OK (not vulnerable)
81+ isOkScan = runScan (scannerConfig , failureScanner );
82+
83+ // Dynamically adopt Verification Strategy
84+ List <String > okVerifications = isOkScan .getVerificationStrategies (ScanResultStatus .OK );
85+ List <String > vulnVerifications = isOkScan .getVerificationStrategies (ScanResultStatus .VULNERABLE );
86+ if (!vulnVerifications .isEmpty () && !okVerifications .isEmpty ()){
87+ // a significant drift in the response is expected, therefore verifications should report OK
88+ // if not we remove all verifications that are not reporting OK!
89+ scannerConfig = (C )scannerConfig .deepCopy ();
90+ scannerConfig .setVerificationStrategies (okVerifications );
91+ LOG .info ("Restart test scan - proof ok (Adopted Verification Strategy)" );
92+ isOkScan = runScan (scannerConfig , failureScanner );
93+ }
94+
95+ LOG .info ("Start test scan - proof vulnerable" );
96+ // Scan with success - means VULNERABLE
97+ isVulnerableScan = runScan (scannerConfig , successScanner );
6898
69- // For a manipulated OIDCResponse we expect a significant drift in the response
70- // The third scan with a successful login does not have that drift on purpose!
99+ // For a malicious scan, we expect a significant drift in the response
100+ // The successScanner does not have that drift on purpose!
71101 // As no error occur and the user is normally logged in, we expect that to be classified as VULNERABLE
72- if (thirdScanSuccess .getStatus () == ScanResultStatus .OK ) {
73- errors .add ("Third scan must always be classified as VULNERABLE!" );
102+ if (isVulnerableScan .getStatus () == ScanResultStatus .OK ) {
103+ var msg = "Fourth scan must always be classified as VULNERABLE!" ;
104+ LOG .warn (msg );
105+ errors .add (msg );
74106 }
75107
76- // The fourth scan with a failing login should have a significant drift in the response
108+ // For a malicious scan, we expect a significant drift in the response
109+ // The failureScanner should have a significant drift in the response
77110 // Because an error occur and the user is not logged in, we expect that to be classified as OK
78- if (fourthScanFailure .getStatus () == ScanResultStatus .VULNERABLE ) {
79- // For a manipulated OIDCResponse we expect a significant drift in the response
80- // The third scan with positive login does not have that on purpose!
81- errors .add ("Fourth scan must always be classified as OK!" );
111+ if (isOkScan .getStatus () == ScanResultStatus .VULNERABLE ) {
112+ var msg = "Third scan must always be classified as OK!" ;
113+ LOG . warn ( msg );
114+ errors .add (msg );
82115 }
83116
117+ LOG .info ("Finished baseline and test scans" );
84118
85- LOG .info ("End initial tests" );
86119 var scanResults = new HashMap <String , ScanResult >();
87120 for (var scanner : scanners ) {
88121 if (scannerConfig .getScanners () != null && !scannerConfig .getScanners ().contains (scanner .getClass ().getSimpleName ())) {
89122 LOG .info ("Skip scanning with {}" , scanner .getClass ().getSimpleName ());
90123 continue ;
91124 }
92125
93- LOG .info ("Start scanning with {}" , scanner .getClass ().getSimpleName ());
94- var scanResult = runScan (scannerConfig , scanner );
95- scanResults .put (scanner .getClass ().getSimpleName (), scanResult );
96- LOG .trace ("Scanner {} finished with status: {}.\n Following evidences collected:\n {}" , scanner .getClass ().getSimpleName (), scanResult .getStatus (), String .join ("\n " , scanResult .getEvidences ()));
126+ LOG .debug ("Start scanning with {}" , scanner .getClass ().getSimpleName ());
127+ try {
128+ var scanResult = runScan (scannerConfig , scanner );
129+ scanResults .put (scanner .getClass ().getSimpleName (), scanResult );
130+ LOG .info ("ClientId: {}; Status: {}; Scanner: {};" , clientId , scanResult .getStatus (), scanner .getClass ().getSimpleName ());
131+ }catch (Exception e ){
132+ var scanResult = ScanResult .failed (List .of (e .getMessage ()));
133+ LOG .error ("ClientId: {}; Status: {}; Scanner: {};" , clientId , scanResult .getStatus (), scanner .getClass ().getSimpleName ());
134+ scanResults .put (scanner .getClass ().getSimpleName (), scanResult );
135+ }
97136 }
98-
99- var duration = Duration .between (start , Instant .now ());
100- ReportBuilder reportBuilder = new ReportBuilder (clientId , duration .toMillis () , firstScanSuccess , secondScanSuccess , thirdScanSuccess , fourthScanFailure , scanResults , errors );
101- return reportBuilder .Build ();
137+ var duration = Duration .between (start , Instant .now ());
138+ ReportBuilder reportBuilder = new ReportBuilder (clientId , duration .toMillis () , firstScanSuccess , secondScanSuccess , isVulnerableScan , isOkScan , scanResults , errors );
139+ var report = reportBuilder .Build ();
140+ LOG .info ("ClientId: {}; Status: {}; Finished Assessment " , report .getClientId (), report .getStatus ());
141+ return report ;
102142 }
103143
104144 private ScanResult runScan (C inputScannerConfig , T scanner ) {
105- scanner .init (firstScanSuccess , secondScanSuccess , thirdScanSuccess , fourthScanFailure );
145+ scanner .init (firstScanSuccess , secondScanSuccess , isVulnerableScan , isOkScan );
106146
107147 C scannerConfig = (C )scanner .getScannerConfig (inputScannerConfig .deepCopy ());
108148
109149 AuthResult authResult = scan (scannerConfig , scanner );
110150
111151 // All VerificationStrategies are used to gather infos
112152 var allVerificationStrategies = createVerificationStrategy (scanResultVerificationStrategies .keySet ());
113- List < String > infos = allVerificationStrategies . extractInfos (authResult );
153+ var infos = extractInfos (allVerificationStrategies , authResult );
114154
115155 if (firstScanSuccess == null || secondScanSuccess == null ) {
116- return new ScanResult (authResult , ScanResultStatus . OK , infos );
156+ return ScanResult . ok (authResult , infos );
117157 }
118158
119159 var selectedVerificationStrategies = createVerificationStrategy (scannerConfig .getVerificationStrategies ());
120- var scanResult = selectedVerificationStrategies .evaluateScanResult (firstScanSuccess .getAuthResult (), secondScanSuccess .getAuthResult (), authResult );
121- var infosAndEvidences = new ArrayList <>(infos );
122- infosAndEvidences .addAll (scanResult .getEvidences ());
123- return new ScanResult (scanResult .getAuthResult (), scanResult .getStatus (), infosAndEvidences );
160+ var verifications = evaluate (selectedVerificationStrategies , firstScanSuccess .getAuthResult (), secondScanSuccess .getAuthResult (), authResult );
161+ return new ScanResult (authResult , verifications , infos );
162+ }
163+
164+ private Map <String , List <String >> extractInfos (List <ScanResultVerificationStrategy > verifications , AuthResult scanAuthResult ) {
165+ var infos = new HashMap <String , List <String >>();
166+ for (var verificationStrategy : verifications ){
167+ infos .put (verificationStrategy .getClass ().getSimpleName (), verificationStrategy .extractInfos (scanAuthResult ));
168+ }
169+ return infos ;
170+ }
171+
172+ public Map <String , VerificationResult > evaluate (List <ScanResultVerificationStrategy > verifications , AuthResult firstPositiveAuthResult , AuthResult secondPositiveAuthResult , AuthResult authResult ) {
173+ var results = new HashMap <String , VerificationResult >();
174+ for (var verificationStrategy : verifications ){
175+ var result = verificationStrategy .evaluateScanResult (firstPositiveAuthResult , secondPositiveAuthResult , authResult );
176+ results .put (verificationStrategy .getClass ().getSimpleName (), result );
177+ }
178+ return results ;
124179 }
125180
126181 protected abstract AuthResult scan (C scannerConfig , T scanner );
127182
128- private ScanResultVerificationStrategy createVerificationStrategy (Collection <String > verificationStrategyNames ) {
183+ private List < ScanResultVerificationStrategy > createVerificationStrategy (Collection <String > verificationStrategyNames ) {
129184 if (verificationStrategyNames == null || verificationStrategyNames .isEmpty ()) {
130- verificationStrategyNames = List .of (
131- DiffVerification .class .getSimpleName (),
132- UrlAndStatusCodeVerification .class .getSimpleName (),
133- CookieVerification .class .getSimpleName ()
134- );
185+ verificationStrategyNames = scanResultVerificationStrategies .keySet ();
135186 }
136187
137188 List <ScanResultVerificationStrategy > verificationStrategies = new ArrayList <>();
138189 for (var name : verificationStrategyNames ) {
139190 verificationStrategies .add (findVerificationStrategyByName (name ));
140191 }
141192
142- return new AnyMatchVerification (verificationStrategies );
143-
193+ return verificationStrategies ;
144194 }
145195
146196 private ScanResultVerificationStrategy findVerificationStrategyByName (String name ) {
0 commit comments