int CheckForBlindBoolWith(string prefix, string quote, string operato, string[] trailers) { string[] keys = new string[] { "true-a", "false-a", "true-b", "false-b" }; //#variables to keep track of rechecking string first_strict_signature = ""; string first_relaxed_signature = ""; string second_strict_signature = ""; string second_relaxed_signature = ""; int confidence = 0; bool vuln = false; bool first_strict_vuln = false; bool first_relaxed_vuln = false; for (int j = 0; j < 2; j++) { if (j == 1 && !(first_strict_vuln || first_relaxed_vuln)) { break; } List<string> payloads = new List<string>(); List<Request> requests = new List<Request>(); List<Response> responses = new List<Response>(); List<string> conditions = new List<string>(); SimilarityChecker sc = new SimilarityChecker(); this.Scnr.Trace("<i<br>>"); for (int i = 0; i < trailers.Length; i++) { string payload = string.Format("{0}{1} {2} {3}", prefix, quote, operato, trailers[i].Replace("<q>", quote)); this.Scnr.RequestTrace(string.Format(" Request Key: '{0}' - Injecting {1}", keys[i], payload)); Response res = this.Scnr.Inject(payload); payloads.Add(payload); conditions.Add(trailers[i].Replace("<q>", quote)); requests.Add(this.Scnr.InjectedRequest.GetClone()); responses.Add(res); sc.Add(keys[i], res); this.Scnr.ResponseTrace(string.Format(" ==> Code-{0} Length-{1}", res.Code, res.BodyLength)); } sc.Check(); this.Scnr.Trace("<i<br>> The responses are analyzed for similarity based grouping to determine if injection succeeded."); this.Scnr.Trace(" Analysis Results:"); this.Scnr.Trace(string.Format(" Strict Groups Signature: {0}", sc.StrictGroupsSignature)); this.Scnr.Trace(string.Format(" Relaxed Groups Signature: {0}", sc.RelaxedGroupsSignature)); if (j == 0) { first_strict_signature = sc.StrictGroupsSignature; first_relaxed_signature = sc.RelaxedGroupsSignature; if (this.IsBlindBoolInjectableGroupingCheck(sc.StrictGroups)) { this.Scnr.Trace(" <i<b>>Strict Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_strict_vuln = true; } } else { this.Scnr.Trace(" Strict Grouping does not indicates that injection succeeded."); } if (this.IsBlindBoolInjectableGroupingCheck(sc.RelaxedGroups)) { this.Scnr.Trace(" <i<b>>Relaxed Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_relaxed_vuln = true; } } else { this.Scnr.Trace(" Relaxed Grouping does not indicates that injection succeeded."); } } else { second_strict_signature = sc.StrictGroupsSignature; second_relaxed_signature = sc.RelaxedGroupsSignature; vuln = false; if (first_strict_vuln && first_strict_signature == second_strict_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Strict Grouping indicates that injection succeeded.<i</cr>>"); } else { this.Scnr.Trace(" Strict Grouping does not indicate that injection succeeded."); } if (first_relaxed_vuln && first_relaxed_signature == second_relaxed_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Relaxed Grouping indicates that injection succeeded.<i</cr>>"); } else { this.Scnr.Trace(" Relaxed Grouping does not indicate that injection succeeded."); } if (vuln) { this.RequestTriggers.AddRange(payloads); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); for (int i = 0; i < payloads.Count; i++) { this.ResponseTriggers.Add(""); if (i == 0 || i == 2) { this.RequestTriggerDescs.Add(string.Format("The payload in this request contains the conditional operator '{0}' followed by the SQL condition {1} which evaluates to true. The payload is {2}", operato, conditions[i], payloads[i])); } else { this.RequestTriggerDescs.Add(string.Format("The payload in this request contains the conditional operator '{0}' followed by the SQL condition {1} which evaluates to false. The payload is {2}", operato, conditions[i], payloads[i])); } } this.ResponseTriggerDescs.Add("This response is the result of the first boolean true condition based payload. This response is equal to the response of the second boolean true condition payload and different from the responses of the boolean false condition payloads."); this.ResponseTriggerDescs.Add("This response is the result of the first boolean false condition based payload. This response is equal to the response of the second boolean false condition payload and different from the responses of the boolean true condition payloads."); this.ResponseTriggerDescs.Add("This response is the result of the second boolean true condition based payload. This response is equal to the response of the first boolean true condition payload and different from the responses of the boolean false condition payloads."); this.ResponseTriggerDescs.Add("This response is the result of the second boolean false condition based payload. This response is equal to the response of the first boolean false condition payload and different from the responses of the boolean true condition payloads."); this.TriggerCount = this.TriggerCount + 4; FindingReason reason = this.GetBlindBoolReason(payloads, operato, this.TriggerCount); this.reasons.Add(reason); return confidence; } } } return 0; }
int InjectBlindIntMath(int int_value) { this.Scnr.Trace("<i<br>><i<h>>Checking for Blind Injection with Integer Math:<i</h>>"); int val = int_value; /* #Addition Algo #if val < 2 then val = 3 #(val - 1) + 1 #(val - 2) + 2 # #(val) + 5 #(val - 1) + 6 # #(val) + "a" #(val) + "b" # */ if (val < 2) { val = 3;//#adjust the value to be suitable for addition based check } int[] plus_left = new int[] { val - 1, val - 2, val, val - 1, val, val }; string[] plus_right = new string[] { "1", "2", "5", "6", "a", "b" }; /* #Subtraction Algo #(val + 1) - 1 #(val + 2) - 2 # #if val < 6 then val = 11 # #(val) - 5 #(val + 1) - 6 # #(val) - "a" #(val) - "b" # */ val = int_value; int sub_val = 0; if (val < 6) { sub_val = 11;//#adjust the value to be suitable for subtraction based check } else { sub_val = val; } int[] minus_left = new int[] { val + 1, val + 2, sub_val, sub_val + 1, val, val }; string[] minus_right = new string[] { "1", "2", "5", "6", "a", "b" }; string[] symbols = new string[] { "+", "-" }; string[] keys = new string[] { "a", "aa", "b", "bb", "c", "cc" }; for (int ii = 0; ii < 2; ii++) { string sym = symbols[ii]; List<int> left = new List<int>(); List<string> right = new List<string>(); if (sym == "+") { this.Scnr.Trace("<i<br>> <i<b>>Checking Addition:<i</b>>"); left.AddRange(plus_left); right.AddRange(plus_right); } else { this.Scnr.Trace("<i<br>> <i<b>>Checking Subtraction:<i</b>>"); left.AddRange(minus_left); right.AddRange(minus_right); } //#variables to keep track for rechecking string first_strict_signature = ""; string first_relaxed_signature = ""; string second_strict_signature = ""; string second_relaxed_signature = ""; int confidence = 0; bool vuln = false; bool first_strict_vuln = false; bool first_relaxed_vuln = false; for (int j = 0; j < 2; j++) { if (j == 1 && !(first_strict_vuln || first_relaxed_vuln)) { break; } List<string> payloads = new List<string>(); List<Request> requests = new List<Request>(); List<Response> responses = new List<Response>(); SimilarityChecker sc = new SimilarityChecker(); this.Scnr.Trace("<i<br>>"); for (int i = 0; i < 6; i++) { string payload = string.Format("{0}{1}{2}", left[i], sym, right[i]); this.Scnr.RequestTrace(string.Format(" Request Key: '{0}' - Injecting {1} ", keys[i], payload)); Response res = this.Scnr.Inject(payload); //#store the request and responses to be added to the vulnerability data if SQLi is found payloads.Add(payload); requests.Add(this.Scnr.InjectedRequest.GetClone()); responses.Add(res); sc.Add(keys[i], res); this.Scnr.ResponseTrace(string.Format(" ==> Code-{0} Length-{1}", res.Code, res.BodyLength)); } sc.Check(); this.Scnr.Trace("<i<br>> The responses are analyzed for similarity based grouping to determine if injection succeeded."); this.Scnr.Trace(" Analysis Results:"); this.Scnr.Trace(string.Format(" Strict Groups Signature: {0}", sc.StrictGroupsSignature)); this.Scnr.Trace(string.Format(" Relaxed Groups Signature: {0}", sc.RelaxedGroupsSignature)); if (j == 0) { first_strict_signature = sc.StrictGroupsSignature; first_relaxed_signature = sc.RelaxedGroupsSignature; if (this.IsBlindMathInjectableGroupingCheck(sc.StrictGroups)) { this.Scnr.Trace(" <i<b>>Strict Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_strict_vuln = true; } } else { this.Scnr.Trace(" Strict Grouping does not indicates that injection succeeded."); } if (this.IsBlindMathInjectableGroupingCheck(sc.RelaxedGroups)) { this.Scnr.Trace(" <i<b>>Relaxed Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_relaxed_vuln = true; } else { this.Scnr.Trace(" Relaxed Grouping does not indicates that injection succeeded."); } } } else { second_strict_signature = sc.StrictGroupsSignature; second_relaxed_signature = sc.RelaxedGroupsSignature; vuln = false; if (first_strict_vuln && first_strict_signature == second_strict_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Strict Grouping indicates that injection succeeded.<i</cr>>"); } else { this.Scnr.Trace(" Strict Grouping does not indicate that injection succeeded."); } if (first_relaxed_vuln && first_relaxed_signature == second_relaxed_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Relaxed Grouping indicates that injection succeeded.<i</cr>>"); } else { this.Scnr.Trace(" Relaxed Grouping does not indicate that injection succeeded."); } if (vuln) { this.RequestTriggers.AddRange(payloads); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); for (int i = 0; i < payloads.Count; i++) { this.ResponseTriggers.Add(""); this.ResponseTriggerDescs.Add("Refer to the 'Reasons' section of this vulnerabilty's description to understand how to interpret this response."); if (i < 4) { if (sym == "+") { this.RequestTriggerDescs.Add(string.Format("The payload in this request tries to add the numbers {0} and {1}.", plus_left[i], plus_right[i])); } else { this.RequestTriggerDescs.Add(string.Format("The payload in this request tries to subtract the number {0} from {1}.", minus_left[i], minus_right[i])); } } else { if (sym == "+") { this.RequestTriggerDescs.Add(string.Format("The payload in this request is an invalid attempt to add the number {0} with string {1}.", plus_left[i], plus_right[i])); } else { this.RequestTriggerDescs.Add(string.Format("The payload in this request is an invalid attempt to subtract the number {0} from the string {1}.", minus_left[i], minus_right[i])); } } } this.TriggerCount = this.TriggerCount + 6; this.second_group = new List<string>(); foreach (string item in new string[] { "A", "B", "C", "D", "E", "F" }) { if (this.first_group.Contains(item)) { this.second_group.Add(item); } } FindingReason reason; if (sym == "+") { reason = this.GetBlindMathAddReason(payloads, plus_left[0] + Int32.Parse(plus_right[0]), plus_left[2] + Int32.Parse(plus_right[2]), this.first_group, this.second_group, this.TriggerCount); } else { reason = this.GetBlindMathSubtractReason(payloads, minus_left[0] - Int32.Parse(minus_right[0]), minus_left[2] - Int32.Parse(minus_right[2]), this.first_group, this.second_group, this.TriggerCount); } this.reasons.Add(reason); return confidence; } } } } return 0; }
int InjectBlindStrConc(string str_value) { int BlindConcInjectionScore = 0; this.Scnr.Trace("<i<br>><i<h>>Checking for Blind Injection with String Concatenation:<i</h>>"); List<Response> blind_str_conc_res = new List<Response>(); if (str_value.Length < 2) { str_value = "aaa"; } string str_value_first_part = str_value[0].ToString(); string str_value_second_part = str_value.Substring(1); string[] quotes = new string[] { "'", "\"" }; string[] joiners = new string[] { "||", "+", " " }; string[] keys = new string[] { "Oracle", "MS SQL", "MySQL" }; List<Request> requests = new List<Request>(); List<Response> responses = new List<Response>(); foreach (string quote in quotes) { if (quote == "'") { this.Scnr.Trace("<i<br>> <i<b>>Checking with Single Quotes:<i</b>>"); } else { this.Scnr.Trace("<i<br>> <i<b>>Checking with Double Quotes:<i</b>>"); } //#variables to keep track of rechecking string first_strict_signature = ""; string first_relaxed_signature = ""; string second_strict_signature = ""; string second_relaxed_signature = ""; int confidence = 0; bool vuln = false; bool first_strict_vuln = false; bool first_relaxed_vuln = false; for (int j = 0; j < 2; j++) { if (j == 1 && !(first_strict_vuln || first_relaxed_vuln)) { break; } List<string> payloads = new List<string>(); requests = new List<Request>(); responses = new List<Response>(); SimilarityChecker sc = new SimilarityChecker(); this.Scnr.Trace("<i<br>>"); for (int i = 0; i < 3; i++) { string payload = string.Format("{0}{1}{2}{3}{4}", str_value_first_part, quote, joiners[i], quote, str_value_second_part); this.Scnr.RequestTrace(string.Format(" Request Key: '{0}' - Injecting {1}", keys[i], payload)); Response res = this.Scnr.Inject(payload); payloads.Add(payload); requests.Add(this.Scnr.InjectedRequest.GetClone()); responses.Add(res); sc.Add(keys[i], res); this.Scnr.ResponseTrace(string.Format(" ==> Code-{0} Length-{1}", res.Code, res.BodyLength)); } sc.Check(); this.Scnr.Trace("<i<br>> The responses are analyzed for similarity based grouping to determine if injection succeeded."); this.Scnr.Trace(" Analysis Results:"); this.Scnr.Trace(string.Format(" Strict Groups Signature: {0}", sc.StrictGroupsSignature)); this.Scnr.Trace(string.Format(" Relaxed Groups Signature: {0}", sc.RelaxedGroupsSignature)); if (j == 0) { first_strict_signature = sc.StrictGroupsSignature; first_relaxed_signature = sc.RelaxedGroupsSignature; if (this.IsBlindStrConcInjectableGroupingCheck(sc.StrictGroups)) { this.Scnr.Trace(" <i<b>>Strict Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_strict_vuln = true; } } else { this.Scnr.Trace(" Strict Grouping does not indicates that injection succeeded."); } if (this.IsBlindStrConcInjectableGroupingCheck(sc.RelaxedGroups)) { this.Scnr.Trace(" <i<b>>Relaxed Grouping indicates that injection succeeded. Rechecking to confirm.<i</b>>"); if (j == 0) { first_relaxed_vuln = true; } } else { this.Scnr.Trace(" Relaxed Grouping does not indicates that injection succeeded."); } } else { second_strict_signature = sc.StrictGroupsSignature; second_relaxed_signature = sc.RelaxedGroupsSignature; vuln = false; string db = ""; if (first_strict_vuln && first_strict_signature == second_strict_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Strict Grouping indicates that injection succeeded.<i</cr>>"); foreach (SimilarityCheckerGroup g in sc.StrictGroups) { if (g.Count == 1) { db = g.GetKeys()[0]; } } } else { this.Scnr.Trace(" Strict Grouping does not indicate that injection succeeded."); } if (first_relaxed_vuln && first_relaxed_signature == second_relaxed_signature) { vuln = true; confidence = confidence + 1; this.Scnr.Trace(" <i<cr>>Even the second time Relaxed Grouping indicates that injection succeeded.<i</cr>>"); foreach (SimilarityCheckerGroup g in sc.RelaxedGroups) { if (g.Count == 1) { db = g.GetKeys()[0]; } } } else { this.Scnr.Trace(" Relaxed Grouping does not indicate that injection succeeded."); } if (vuln) { this.RequestTriggers.AddRange(payloads); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); List<string> non_db = new List<string>(); non_db.AddRange(keys); non_db.Remove(db); for (int i = 0; i < payloads.Count; i++) { this.ResponseTriggers.Add(""); this.RequestTriggerDescs.Add(string.Format("The payload in this request tries to concatenate two strings as per {0} database's syntax. The payload is {1}", keys[i], payloads[i])); if (keys[i] == db) { this.ResponseTriggerDescs.Add(string.Format("This response is different from the responses recieved for the payloads that used {0} and {1} databases' concatenation syntax.", non_db[0], non_db[1])); } else { non_db.Remove(keys[i]); this.ResponseTriggerDescs.Add(string.Format("This response is different from the response recieved for the payloads that used {0} database's concatenation syntax but similar to the response for the payload that used {1} database's concatenation syntax", db, non_db[0])); non_db.Add(keys[i]); } } this.TriggerCount = this.TriggerCount + 3; FindingReason reason = this.GetBlindConcatReason(payloads, db, this.TriggerCount); this.reasons.Add(reason); return confidence; } } } } return 0; }
void CheckForLocalFileIncludeWithDownwardTraversalWithSlash(string slash) { //#check downward traversal //#indicates presence of file read function and also a insecure direct object reference in that function this.Scnr.Trace("<i<br>><i<b>>Checking for Downward Directory Traversal:<i</b>>"); this.Scnr.Trace(string.Format("<i<br>>Normal Response Code - {0}. Length -{0}", this.BaseResponse.Code, this.BaseResponse.BodyLength)); string payload_a = string.Format("aa<s>..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_a = payload_a.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a)); Response res_a = this.Scnr.Inject(payload_a); Request req_a = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a.Code, res_a.BodyLength)); string payload_a1 = string.Format("aa..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_a1 = payload_a1.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a1)); Response res_a1 = this.Scnr.Inject(payload_a1); Request req_a1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a1.Code, res_a1.BodyLength)); string payload_b = string.Format("bb<s>..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_b = payload_b.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b)); Response res_b = this.Scnr.Inject(payload_b); Request req_b = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b.Code, res_b.BodyLength)); string payload_b1 = string.Format("bb..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_b1 = payload_b1.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b1)); Response res_b1 = this.Scnr.Inject(payload_b1); Request req_b1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b1.Code, res_b1.BodyLength)); this.Scnr.Trace("<i<br>>Analysing the responses for patterns..."); //#Analyzing the responses for patterns SimilarityChecker sc = new SimilarityChecker(); sc.Add("a", res_a); sc.Add("a1", res_a1); sc.Add("b", res_b); sc.Add("b1", res_b1); sc.Check(); List <Request> requests = new List <Request>() { req_a, req_a1, req_b, req_b1 }; List <Response> responses = new List <Response>() { res_a, res_a1, res_b, res_b1 }; List <string> request_trigger_descs = new List <string>(); request_trigger_descs.Add(string.Format("This payload refers to the {0} file by doing a proper upward directory traversal of a dummy directory 'aa'. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_a)); request_trigger_descs.Add(string.Format("This payload does not do a proper upward directory traversal of the dummy directory 'aa' and so does not refer to the {0} file. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_a1)); request_trigger_descs.Add(string.Format("This payload refers to the {0} file by doing a proper upward directory traversal of a dummy directory 'bb'. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_b)); request_trigger_descs.Add(string.Format("This payload does not do a proper upward directory traversal of the dummy directory 'bb' and so does not refer to the {0} file. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_b1)); List <string> response_trigger_descs = new List <string>(); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger before the previous."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger before the previous."); List <string> request_triggers = new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }; List <string> response_triggers = new List <string>() { "", "", "", "" }; foreach (SimilarityCheckerGroup group in sc.StrictGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for traversal based payloads are similar to each other and are different from non-traversal based responses. Indicates presence of LFI.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }, this.Scnr.PreInjectionParameterValue, slash, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); return; } } } foreach (SimilarityCheckerGroup group in sc.RelaxedGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for traversal based payloads are similar to each other and are different from non-traversal based responses. Indicates presence of LFI.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }, this.Scnr.PreInjectionParameterValue, slash, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(1); return; } } } this.Scnr.Trace("<i<br>>The responses did not fall in any patterns that indicate LFI"); }
void CheckForSSRF() { this.Scnr.Trace("<i<br>><i<h>>Checking for Server Side Request Forgery:<i</h>>"); this.Scnr.Trace(string.Format("<i<br>>Normal Response Code - {0}. Length -{0}", this.BaseResponse.Code, this.BaseResponse.BodyLength)); string p = ""; string first_time_pattern = ""; string second_time_pattern = ""; bool strict_group_matched = false; bool relaxed_group_matched = false; if (this.Scnr.PreInjectionParameterValue.StartsWith("http://")) { p = "http://"; } else if (this.Scnr.PreInjectionParameterValue.StartsWith("https://")) { p = "https://"; } else { p = ""; } for (int i = 0; i < 2; i++) { string payload_a = string.Format("{0}localhost:65555", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a)); Response res_a = this.Scnr.Inject(payload_a); Request req_a = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a.Code, res_a.BodyLength)); string payload_a1 = string.Format("{0}localhost:1", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a1)); Response res_a1 = this.Scnr.Inject(payload_a1); Request req_a1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a1.Code, res_a1.BodyLength)); string payload_b = string.Format("{0}localhost:66666", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b)); Response res_b = this.Scnr.Inject(payload_b); Request req_b = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b.Code, res_b.BodyLength)); string payload_b1 = string.Format("{0}localhost:2", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b1)); Response res_b1 = this.Scnr.Inject(payload_b1); Request req_b1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b1.Code, res_b1.BodyLength)); this.Scnr.Trace("<i<br>>Analysing the responses for patterns..."); //#Analyzing the responses for patterns SimilarityChecker sc = new SimilarityChecker(); sc.Add("a", res_a, payload_a); sc.Add("a1", res_a1, payload_a1); sc.Add("b", res_b, payload_b); sc.Add("b1", res_b1, payload_b1); sc.Check(); List <Request> requests = new List <Request>() { req_a, req_a1, req_b, req_b1 }; List <Response> responses = new List <Response>() { res_a, res_a1, res_b, res_b1 }; List <string> request_trigger_descs = new List <string>(); request_trigger_descs.Add(string.Format("This payload points to the invalid port 65555 on localhost. The payload is {0}", payload_a)); request_trigger_descs.Add(string.Format("This payload points to the valid port 1 on localhost. The payload is {0}", payload_a1)); request_trigger_descs.Add(string.Format("This payload points to the invalid port 66666 on localhost. The payload is {0}", payload_b)); request_trigger_descs.Add(string.Format("This payload points to the valid port 2 on localhost. The payload is {0}", payload_b1)); List <string> response_trigger_descs = new List <string>(); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger before the previous."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger before the previous."); List <string> request_triggers = new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }; List <string> response_triggers = new List <string>() { "", "", "", "" }; if (i == 0) { foreach (SimilarityCheckerGroup group in sc.StrictGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for invalid port based payloads are similar to each other and are different from responses for valid port based payloads. Indicates presence of SSRF.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }, false, new List <int>(), this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); strict_group_matched = true; } } } if (!strict_group_matched) { foreach (SimilarityCheckerGroup group in sc.RelaxedGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for invalid port based payloads are similar to each other and are different responses for valid port based payload. Indicates presence of SSRF.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }, false, new List <int>(), this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); relaxed_group_matched = true; } } } } } List <int> res_times = new List <int>() { res_a.RoundTrip, res_a1.RoundTrip, res_b.RoundTrip, res_b1.RoundTrip }; res_times.Sort(); if ((res_times[2] - res_times[0] > 200) && (res_times[3] - res_times[0] > 200) && (res_times[2] - res_times[1] > 200) && (res_times[3] - res_times[1] > 200) && ((res_times[1] - res_times[0]) < 200) && ((res_times[3] - res_times[2]) < 200)) { if ((res_a.RoundTrip == res_times[0] && res_b.RoundTrip == res_times[1]) || (res_a.RoundTrip == res_times[1] && res_b.RoundTrip == res_times[0])) { if (i == 0) { first_time_pattern = "Valid>Invalid"; } else { second_time_pattern = "Valid>Invalid"; } } else if ((res_a1.RoundTrip == res_times[0] && res_b1.RoundTrip == res_times[1]) || (res_a1.RoundTrip == res_times[1] && res_b1.RoundTrip == res_times[0])) { if (i == 0) { first_time_pattern = "Invalid>Valid"; } else { second_time_pattern = "Invalid>Valid"; } } } if (first_time_pattern.Length > 0) { if (i == 0) { this.Scnr.Trace("<i<br>>There is a pattern in the roundtrip time of the four responses. Rechecking to confirm.<i<br>>"); continue; } else if (i == 1) { if (first_time_pattern == second_time_pattern) { this.Scnr.Trace("<i<br>><i<cr>>Response times for invalid port based payloads are similar to each other and are different from response times for valid port based payload. Indicates presence of SSRF.<i</cr>>"); response_trigger_descs = new List <string>(); response_trigger_descs.Add("This response time is different from the response time of the next trigger but is similar to the response time of the trigger after the next."); response_trigger_descs.Add("This response time is different from the response time of the previous trigger but is similar to the response time of the trigger after the next."); response_trigger_descs.Add("This response time is different from the response time of the next trigger but is similar to the response time of the trigger before the previous."); response_trigger_descs.Add("This response time is different from the response time of the previous trigger but is similar to the response time of the trigger before the previous."); FindingReason reason = this.GetDiffReason(new List <string>() { payload_a, payload_a1, payload_b, payload_b1 }, true, new List <int>() { res_a.RoundTrip, res_a1.RoundTrip, res_b.RoundTrip, res_b1.RoundTrip }, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); return; } else { this.Scnr.Trace("<i<br>>The pattern in the response times is inconsistent and therefore does not indicate SSRF"); return; } } } else if (!(relaxed_group_matched || strict_group_matched)) { this.Scnr.Trace("<i<br>>The responses did not fall in any patterns that indicate SSRF"); break; } } }
void CheckForSSRF() { this.Scnr.Trace("<i<br>><i<h>>Checking for Server Side Request Forgery:<i</h>>"); this.Scnr.Trace(string.Format("<i<br>>Normal Response Code - {0}. Length -{0}", this.BaseResponse.Code, this.BaseResponse.BodyLength)); string p = ""; string first_time_pattern = ""; string second_time_pattern = ""; bool strict_group_matched = false; bool relaxed_group_matched = false; if (this.Scnr.PreInjectionParameterValue.StartsWith("http://")) { p = "http://"; } else if (this.Scnr.PreInjectionParameterValue.StartsWith("https://")) { p = "https://"; } else { p = ""; } for (int i = 0; i < 2; i++) { string payload_a = string.Format("{0}localhost:65555", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a)); Response res_a = this.Scnr.Inject(payload_a); Request req_a = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a.Code, res_a.BodyLength)); string payload_a1 = string.Format("{0}localhost:1", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a1)); Response res_a1 = this.Scnr.Inject(payload_a1); Request req_a1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a1.Code, res_a1.BodyLength)); string payload_b = string.Format("{0}localhost:66666", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b)); Response res_b = this.Scnr.Inject(payload_b); Request req_b = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b.Code, res_b.BodyLength)); string payload_b1 = string.Format("{0}localhost:2", p); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b1)); Response res_b1 = this.Scnr.Inject(payload_b1); Request req_b1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b1.Code, res_b1.BodyLength)); this.Scnr.Trace("<i<br>>Analysing the responses for patterns..."); //#Analyzing the responses for patterns SimilarityChecker sc = new SimilarityChecker(); sc.Add("a", res_a, payload_a); sc.Add("a1", res_a1, payload_a1); sc.Add("b", res_b, payload_b); sc.Add("b1", res_b1, payload_b1); sc.Check(); List<Request> requests = new List<Request>() { req_a, req_a1, req_b, req_b1 }; List<Response> responses = new List<Response>() { res_a, res_a1, res_b, res_b1 }; List<string> request_trigger_descs = new List<string>(); request_trigger_descs.Add(string.Format("This payload points to the invalid port 65555 on localhost. The payload is {0}", payload_a)); request_trigger_descs.Add(string.Format("This payload points to the valid port 1 on localhost. The payload is {0}", payload_a1)); request_trigger_descs.Add(string.Format("This payload points to the invalid port 66666 on localhost. The payload is {0}", payload_b)); request_trigger_descs.Add(string.Format("This payload points to the valid port 2 on localhost. The payload is {0}", payload_b1)); List<string> response_trigger_descs = new List<string>(); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger before the previous."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger before the previous."); List<string> request_triggers = new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }; List<string> response_triggers = new List<string>() { "", "", "", "" }; if (i == 0) { foreach (SimilarityCheckerGroup group in sc.StrictGroups) { if (group.Count == 2) if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for invalid port based payloads are similar to each other and are different from responses for valid port based payloads. Indicates presence of SSRF.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }, false, new List<int>(), this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); strict_group_matched = true; } } if (!strict_group_matched) { foreach (SimilarityCheckerGroup group in sc.RelaxedGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for invalid port based payloads are similar to each other and are different responses for valid port based payload. Indicates presence of SSRF.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }, false, new List<int>(), this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); relaxed_group_matched = true; } } } } } List<int> res_times = new List<int>() { res_a.RoundTrip, res_a1.RoundTrip, res_b.RoundTrip, res_b1.RoundTrip }; res_times.Sort(); if ((res_times[2] - res_times[0] > 200) && (res_times[3] - res_times[0] > 200) && (res_times[2] - res_times[1] > 200) && (res_times[3] - res_times[1] > 200) && ((res_times[1] - res_times[0]) < 200) && ((res_times[3] - res_times[2]) < 200)) { if ((res_a.RoundTrip == res_times[0] && res_b.RoundTrip == res_times[1]) || (res_a.RoundTrip == res_times[1] && res_b.RoundTrip == res_times[0])) { if (i == 0) { first_time_pattern = "Valid>Invalid"; } else { second_time_pattern = "Valid>Invalid"; } } else if ((res_a1.RoundTrip == res_times[0] && res_b1.RoundTrip == res_times[1]) || (res_a1.RoundTrip == res_times[1] && res_b1.RoundTrip == res_times[0])) { if (i == 0) { first_time_pattern = "Invalid>Valid"; } else { second_time_pattern = "Invalid>Valid"; } } } if (first_time_pattern.Length > 0) { if (i == 0) { this.Scnr.Trace("<i<br>>There is a pattern in the roundtrip time of the four responses. Rechecking to confirm.<i<br>>"); continue; } else if (i == 1) { if (first_time_pattern == second_time_pattern) { this.Scnr.Trace("<i<br>><i<cr>>Response times for invalid port based payloads are similar to each other and are different from response times for valid port based payload. Indicates presence of SSRF.<i</cr>>"); response_trigger_descs = new List<string>(); response_trigger_descs.Add("This response time is different from the response time of the next trigger but is similar to the response time of the trigger after the next."); response_trigger_descs.Add("This response time is different from the response time of the previous trigger but is similar to the response time of the trigger after the next."); response_trigger_descs.Add("This response time is different from the response time of the next trigger but is similar to the response time of the trigger before the previous."); response_trigger_descs.Add("This response time is different from the response time of the previous trigger but is similar to the response time of the trigger before the previous."); FindingReason reason = this.GetDiffReason(new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }, true, new List<int>() { res_a.RoundTrip, res_a1.RoundTrip, res_b.RoundTrip, res_b1.RoundTrip }, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); return; } else { this.Scnr.Trace("<i<br>>The pattern in the response times is inconsistent and therefore does not indicate SSRF"); return; } } } else if (!(relaxed_group_matched || strict_group_matched)) { this.Scnr.Trace("<i<br>>The responses did not fall in any patterns that indicate SSRF"); break; } } }
void CheckForLocalFileIncludeWithDownwardTraversalWithSlash(string slash) { //#check downward traversal //#indicates presence of file read function and also a insecure direct object reference in that function this.Scnr.Trace("<i<br>><i<b>>Checking for Downward Directory Traversal:<i</b>>"); this.Scnr.Trace(string.Format("<i<br>>Normal Response Code - {0}. Length -{0}", this.BaseResponse.Code, this.BaseResponse.BodyLength)); string payload_a = string.Format("aa<s>..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_a = payload_a.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a)); Response res_a = this.Scnr.Inject(payload_a); Request req_a = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a.Code, res_a.BodyLength)); string payload_a1 = string.Format("aa..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_a1 = payload_a1.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_a1)); Response res_a1 = this.Scnr.Inject(payload_a1); Request req_a1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_a1.Code, res_a1.BodyLength)); string payload_b = string.Format("bb<s>..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_b = payload_b.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b)); Response res_b = this.Scnr.Inject(payload_b); Request req_b = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b.Code, res_b.BodyLength)); string payload_b1 = string.Format("bb..<s>{0}", this.Scnr.PreInjectionParameterValue); payload_b1 = payload_b1.Replace("<s>", slash); this.Scnr.RequestTrace(string.Format(" Injected payload - {0}", payload_b1)); Response res_b1 = this.Scnr.Inject(payload_b1); Request req_b1 = this.Scnr.InjectedRequest; this.Scnr.ResponseTrace(string.Format(" ==> Got Response. Code- {0}. Length- {1}", res_b1.Code, res_b1.BodyLength)); this.Scnr.Trace("<i<br>>Analysing the responses for patterns..."); //#Analyzing the responses for patterns SimilarityChecker sc = new SimilarityChecker(); sc.Add("a", res_a); sc.Add("a1", res_a1); sc.Add("b", res_b); sc.Add("b1", res_b1); sc.Check(); List<Request> requests = new List<Request>() { req_a, req_a1, req_b, req_b1 }; List<Response> responses = new List<Response>() { res_a, res_a1, res_b, res_b1 }; List<string> request_trigger_descs = new List<string>(); request_trigger_descs.Add(string.Format("This payload refers to the {0} file by doing a proper upward directory traversal of a dummy directory 'aa'. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_a)); request_trigger_descs.Add(string.Format("This payload does not do a proper upward directory traversal of the dummy directory 'aa' and so does not refer to the {0} file. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_a1)); request_trigger_descs.Add(string.Format("This payload refers to the {0} file by doing a proper upward directory traversal of a dummy directory 'bb'. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_b)); request_trigger_descs.Add(string.Format("This payload does not do a proper upward directory traversal of the dummy directory 'bb' and so does not refer to the {0} file. The payload is {1}", this.Scnr.PreInjectionParameterValue, payload_b1)); List<string> response_trigger_descs = new List<string>(); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger after the next."); response_trigger_descs.Add("The contents of this response are different from the response of the next trigger but are similar to the response of the trigger before the previous."); response_trigger_descs.Add("The contents of this response are different from the response of the previous trigger but are similar to the response of the trigger before the previous."); List<string> request_triggers = new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }; List<string> response_triggers = new List<string>() { "", "", "", "" }; foreach (SimilarityCheckerGroup group in sc.StrictGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for traversal based payloads are similar to each other and are different from non-traversal based responses. Indicates presence of LFI.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }, this.Scnr.PreInjectionParameterValue, slash, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(2); return; } } } foreach (SimilarityCheckerGroup group in sc.RelaxedGroups) { if (group.Count == 2) { if (group.HasKey("a") && group.HasKey("b")) { this.Scnr.Trace("<i<br>><i<cr>>Responses for traversal based payloads are similar to each other and are different from non-traversal based responses. Indicates presence of LFI.<i</cr>>"); FindingReason reason = this.GetDiffReason(new List<string>() { payload_a, payload_a1, payload_b, payload_b1 }, this.Scnr.PreInjectionParameterValue, slash, this.TriggerCount, request_triggers.Count); this.Reasons.Add(reason); this.RequestTriggers.AddRange(request_triggers); this.ResponseTriggers.AddRange(response_triggers); this.RequestTriggerDescs.AddRange(request_trigger_descs); this.ResponseTriggerDescs.AddRange(response_trigger_descs); this.TriggerRequests.AddRange(requests); this.TriggerResponses.AddRange(responses); this.TriggerCount = this.TriggerCount + request_triggers.Count; this.SetConfidence(1); return; } } } this.Scnr.Trace("<i<br>>The responses did not fall in any patterns that indicate LFI"); }