@@ -709,12 +709,18 @@ def _detectBoolean(slot, endpoint):
709709 return None , None
710710
711711 truePage , _ = _gqlSend (endpoint , trueQuery )
712+ truePage2 , _ = _gqlSend (endpoint , trueQuery )
712713 falsePage , _ = _gqlSend (endpoint , falseQuery )
713714
714715 trueVal = _slotValue (truePage )
716+ trueVal2 = _slotValue (truePage2 )
715717 falseVal = _slotValue (falsePage )
716718
717- if _ratio (trueVal , falseVal ) < (1.0 - _MIN_RATIO_DIFF ):
719+ # Require the true response to be REPRODUCIBLE (trueVal ~= trueVal2) and to diverge
720+ # from the false response. A single true-vs-false compare turns page jitter into a
721+ # false positive; a reproducibility guard (like the other non-SQL engines' _boolean)
722+ # rejects it, since a jittery page also fails to reproduce against itself.
723+ if _ratio (trueVal , trueVal2 ) >= (1.0 - _MIN_RATIO_DIFF ) and _ratio (trueVal , falseVal ) < (1.0 - _MIN_RATIO_DIFF ):
718724 return "boolean-based blind (string)" , truePage
719725
720726 return None , None
@@ -731,21 +737,29 @@ def _detectTime(slot, endpoint):
731737 if not baseQuery :
732738 return None , None , None
733739
734- start = time .time ()
735- _gqlSend (endpoint , baseQuery )
736- baseline = time .time () - start
740+ def elapsed (query ):
741+ start = time .time ()
742+ _gqlSend (endpoint , query )
743+ return time .time () - start
737744
745+ baseline = elapsed (baseQuery )
738746 delay = conf .timeSec
747+ cutoff = baseline + delay * 0.5
748+
739749 for dbms , dialect in DIALECTS .items ():
740750 if not dialect .delay :
741751 continue
742- query = _buildQuery (slot , "%s' OR %s-- " % (SENTINEL , dialect .delay ("1=1" , delay )))
743- if not query :
752+ sleepQuery = _buildQuery (slot , "%s' OR %s-- " % (SENTINEL , dialect .delay ("1=1" , delay )))
753+ if not sleepQuery or elapsed ( sleepQuery ) <= cutoff :
744754 continue
745- start = time .time ()
746- _gqlSend (endpoint , query )
747- if (time .time () - start ) > baseline + delay * 0.5 :
748- return "time-based blind" , baseline + delay * 0.5 , dbms
755+
756+ # Confirm before attributing: the delay must REPRODUCE and a false-condition
757+ # control must stay fast. A single sample turns jitter/a uniformly-slow endpoint
758+ # into a false positive and can pin the wrong dialect; requiring the delay to
759+ # track the condition rules both out.
760+ controlQuery = _buildQuery (slot , "%s' OR %s-- " % (SENTINEL , dialect .delay ("1=2" , delay )))
761+ if elapsed (sleepQuery ) > cutoff and (controlQuery is None or elapsed (controlQuery ) <= cutoff ):
762+ return "time-based blind" , cutoff , dbms
749763
750764 return None , None , None
751765
0 commit comments