Skip to content

This is Chapter 4 of the Recon & OSINT notebook. Chapters 1 through 3 built the foundation: what an attack surface is, how WHOIS/DNS/Certificate Transparency map an organisation’s infrastructure, and the OPSEC discipline that keeps a collection effort from touching or tipping off the target. This chapter puts the first genuinely offensive-feeling tool in your hands — the search engine — and teaches you to use it as a precision instrument.

The idea behind “Google dorking” (also called Google hacking) is deceptively simple: search engines have already crawled, indexed and cached an enormous fraction of everything an organisation ever accidentally published, and a carefully constructed query pulls exactly the dangerous parts back out. No packet is ever sent to the target. You are querying Google’s copy of the target, which makes dorking one of the safest, quietest and highest-return techniques in the entire passive-recon toolkit. Done well it finds exposed configuration files, backup archives, credentials in plaintext, forgotten admin panels, internal documents, and source code — the kind of findings that turn a “no critical issues” report into a very different conversation.


Part 1: What a Search Operator Actually Is

Section titled “Part 1: What a Search Operator Actually Is”

Before the tricks, understand the machine. A search engine is three moving parts:

  1. The crawler (spider/bot) — a program (Googlebot, Bingbot) that follows links, fetches pages, and hands them to the indexer. It discovers new URLs from links on pages it already knows, from sitemaps, and from other signals.
  2. The index — an inverted data structure mapping every word (and many metadata attributes: URL text, title, file type, host) to the list of documents containing it. When you search, you are not searching the live web; you are searching this pre-built index.
  3. The ranker — the algorithm that orders results for a human who wants the most relevant page. This is the part you are fighting. Default ranking hides the weird, the old, and the obscure — which is exactly what a hacker wants. Operators are how you override the ranker and demand precision.

A search operator is a special token in your query that the engine interprets as an instruction rather than a search term. site: is not a word to find on pages — it is a filter that says “only return results whose host matches this.” Understanding that distinction is the whole game: ordinary words are content filters, operators are metadata filters, and metadata filters are what let you slice the index by structure instead of topic.

Why this matters for recon: an organisation controls its content but rarely controls its structure. They will scrub the word “password” from a page, but they cannot easily stop Google from having indexed backup.sql at a predictable URL two years ago. Operators query the structure.

flowchart LR
    A[Googlebot crawls links & sitemaps] --> B[Indexer builds inverted index]
    B --> C[You submit an operator-rich query]
    C --> D[Ranker filters index by metadata + content]
    D --> E[Results: exposed files, panels, leaks]
    E --> F[You verify manually, collect evidence]

The golden rule: you query the index, not the site

Section titled “The golden rule: you query the index, not the site”

This has two consequences you must internalise:

  • Cached results can reveal content that no longer exists on the live site. A page taken down yesterday may still sit in Google’s cache for days or weeks. This is a feature for the investigator and a nightmare for the defender.
  • Absence of a result is not absence of the resource. If a dork returns nothing, the resource may still exist — it just may not be indexed (robots.txt, noindex, never linked, behind auth). Dorking finds the indexed attack surface, which is a subset of the real one. Always pair it with active discovery later in the methodology.

Part 2: The Core Google Operators, One at a Time

Section titled “Part 2: The Core Google Operators, One at a Time”

Everything below is standard, documented Google syntax. There is nothing to install and nothing illegal about the operators themselves — the legal and ethical line is about what you do with the scope (see Part 9). Teach yourself each operator by running it against a domain you own or a broad public target.

2.1 site: — restrict to a host or domain

Section titled “2.1 site: — restrict to a host or domain”
site:example.com

Returns only pages Google has indexed under that host. This is the anchor of almost every recon dork because it scopes results to your target. Key behaviours:

  • site:example.com matches the domain and all subdomains (blog.example.com, dev.example.com).
  • site:sub.example.com restricts to exactly that subdomain.
  • Combine with a leading - to exclude: site:example.com -site:www.example.com surfaces everything that is not the main www host — a fast way to enumerate forgotten subdomains that made it into the index.

Recon use: running site:example.com first tells you how much of the target Google even knows about, and the subdomain exclusion trick is a zero-cost supplement to the subdomain enumeration you’ll do properly in Chapter 5.

inurl:admin
site:example.com inurl:login

Filters to results where the string appears in the URL. Extremely powerful because URLs leak structure: /admin, /wp-admin, /phpmyadmin, /.git, /backup, /api/v1, ?id=. The variant allinurl: requires all the following terms to appear in the URL:

allinurl: admin login

Red team usage: inurl: is how you find management interfaces and parameterised endpoints (inurl:"id=") that later feed into injection testing.

2.3 intitle: — match text in the page <title>

Section titled “2.3 intitle: — match text in the page <title>”
intitle:"index of"
intitle:"admin login"

The <title> tag is often auto-generated and betrays the software. intitle:"index of" is the classic directory-listing dork: when a web server has directory listing enabled and no index file, Apache/nginx generate a page titled “Index of /…”. allintitle: requires all terms in the title.

2.4 intext: — match text in the page body

Section titled “2.4 intext: — match text in the page body”
intext:"password"
intext:"BEGIN RSA PRIVATE KEY"

Matches words in the visible body. allintext: requires all of them. Body-text dorks are noisier (lots of false positives) but catch content that structural operators miss — a leaked key pasted into a wiki page, a connection string in a rendered error.

2.5 filetype: / ext: — restrict by file extension

Section titled “2.5 filetype: / ext: — restrict by file extension”
site:example.com filetype:pdf
site:example.com filetype:xls OR filetype:xlsx
filetype:sql "INSERT INTO"

Arguably the highest-value operator for finding leaked documents. Organisations publish or accidentally expose spreadsheets, PDFs, config files, logs, database dumps and archives constantly. ext: behaves the same as filetype:. High-value extensions to memorise:

ExtensionWhat it commonly leaks
sql, db, sqliteDatabase dumps / backups
env, cfg, conf, ini, yml, yamlConfig files, secrets, connection strings
logApplication/debug logs, sometimes creds & tokens
bak, old, backup, swp, ~Backups of source or config
xls, xlsx, csvInternal data, employee lists, exports
pdf, docx, pptxInternal docs, network diagrams, policies
git, svnExposed VCS metadata
pem, key, ppk, crtPrivate keys, certificates
json, xmlAPI responses, config, sometimes secrets

2.6 cache: — retrieve Google’s cached copy

Section titled “2.6 cache: — retrieve Google’s cached copy”
cache:example.com/secret-page

Historically pulled Google’s stored snapshot even if the live page changed or vanished. Google has deprecated the public cache: operator, so in practice you now reach cached content through the Wayback Machine (web.archive.org), Bing’s cache, or by clicking the cache link where still offered. The concept remains vital: content you find and lose can often be recovered from a cache or archive, which you’ll use heavily in Chapter 8 and beyond.

  • Implicit AND: space between terms means both must match.
  • OR (must be uppercase) or |: either term. filetype:xls OR filetype:xlsx.
  • - (minus): exclude. site:example.com -www removes noise.
  • " " (quotes): exact phrase. "index of /backup".
  • * (wildcard): single-term placeholder inside a phrase. "admin * panel".
  • ( ) grouping: site:example.com (filetype:sql OR filetype:bak).
  • AROUND(n): the two terms within n words of each other. "username" AROUND(3) "password" finds them near each other — great for catching credential pairs.
OperatorEffectExample
related:Sites similar to a URLrelated:example.com
link:Pages linking to a URL (largely deprecated)link:example.com
define:Definitiondefine:idor
before: / after:Date-bounded results (YYYY-MM-DD)site:example.com after:2024-01-01
numrange (..)Numeric range"employee id" 1000..9999
@ / #Search social handles / hashtags@companyname

The before:/after: operators are underrated for recon — they let you find recently changed or old, forgotten content, both of which are interesting for different reasons.

mindmap
  root((Google Operators))
    Structure
      site:
      inurl:
      intitle:
      filetype:/ext:
    Content
      intext:
      quotes
      AROUND(n)
    Logic
      AND(space)
      OR / pipe
      minus
      grouping
    Time/Meta
      before:/after:
      cache:/archive
      related:

Part 3: From Operators to Attack-Surface Dorks

Section titled “Part 3: From Operators to Attack-Surface Dorks”

Individual operators are letters; dorks are sentences. A good dork combines a scope filter (site:), a structure filter (inurl:/filetype:/intitle:), and optionally a content filter (intext:/quotes) to isolate one specific class of exposure. Below are field-tested categories. Replace example.com with your authorised scope.

site:example.com intitle:"index of"
site:example.com intitle:"index of" (backup OR bak OR old OR sql OR env)
intitle:"index of" "parent directory" site:example.com

Directory listings are gold: they expose the raw file tree, often including backups, configs and archives the developers forgot were reachable.

site:example.com ext:env
site:example.com ext:env intext:"DB_PASSWORD"
site:example.com filetype:cfg OR filetype:conf OR filetype:ini
site:example.com filetype:yml intext:"password"
site:example.com intext:"BEGIN RSA PRIVATE KEY"
site:example.com filetype:log intext:"password"

.env files are a perennial jackpot — they hold database credentials, API keys and secret tokens for many frameworks (Laravel, Node, Rails). They should never be web-reachable, yet they routinely are.

site:example.com ext:sql intext:"INSERT INTO"
site:example.com ext:sql intext:"CREATE TABLE"
site:example.com (ext:bak OR ext:old OR ext:backup OR ext:zip OR ext:tar OR ext:gz)
site:example.com inurl:backup

A single indexed dump.sql can contain an entire user table, hashed (or worse, plaintext) passwords included.

site:example.com inurl:admin
site:example.com inurl:login
site:example.com (inurl:wp-admin OR inurl:administrator OR inurl:phpmyadmin)
site:example.com intitle:"login" (inurl:admin OR inurl:portal OR inurl:dashboard)

Finding the panel is step one; you do not brute-force or bypass it without explicit authorisation. In a real engagement, the finding is “an admin panel is exposed at X” — the exploitation is scoped and consented.

site:example.com inurl:.git
site:example.com intitle:"index of" ".git"
site:example.com filetype:php intext:"mysql_connect"
site:example.com (ext:java OR ext:py OR ext:rb OR ext:go) intext:"api_key"

An exposed /.git/ directory can allow full source reconstruction (you’ll meet tooling like git-dumper in later chapters); source often embeds secrets and reveals every endpoint.

site:s3.amazonaws.com example
site:storage.googleapis.com example
site:blob.core.windows.net example
inurl:s3.amazonaws.com filetype:pdf company

Misconfigured public buckets are one of the most common breach causes; search engines index public bucket listings and objects.

site:example.com intext:"Fatal error" intext:"on line"
site:example.com intext:"Warning: mysql_"
site:example.com intext:"stack trace" filetype:txt
site:example.com "phpinfo()" intitle:"phpinfo()"

Verbose errors leak paths, framework versions, database structure and internal IPs — pure reconnaissance value.

intitle:"webcamXP 5"
inurl:"/view.shtml" intitle:"Network Camera"
intitle:"router" intext:"login" inurl:example.com

For scoped engagements these reveal management interfaces of network gear, cameras and printers.

Bug bounty angle (woven in): the dorks in 3.1–3.6 map almost one-to-one to common paid findings — exposed .env, .git, database backups and cloud buckets are recurring high/critical disclosures on HackerOne and Bugcrowd. A disciplined dorking pass at the start of a bounty engagement, scoped to the program’s in-scope domains, frequently surfaces low-effort criticals before anyone touches a proxy.


Part 4: A Structured Dorking Table You’ll Reuse

Section titled “Part 4: A Structured Dorking Table You’ll Reuse”

Keep a personal dork library. Here is a starter matrix you can adapt; the point is repeatability, not memorising every line.

GoalDork templateWhy it works
Enumerate subdomainssite:*.example.com -wwwSurfaces non-www hosts in the index
Find login portalssite:example.com inurl:(login OR signin OR admin)Login URLs are predictable
Exposed configssite:example.com ext:(env OR ini OR conf OR yml)Configs hold secrets
DB dumpssite:example.com ext:sql intext:INSERT INTODumps contain SQL statements
Backupssite:example.com ext:(bak OR old OR zip OR tar OR gz)Backups sit at predictable names
Documentssite:example.com ext:(pdf OR docx OR xlsx)Internal docs leak data & metadata
Source leakssite:example.com (inurl:.git OR ext:bak) intext:passwordVCS/source expose secrets
Error/debugsite:example.com intext:"stack trace" OR "Fatal error"Errors leak internals
Cloud bucketssite:s3.amazonaws.com examplePublic buckets get indexed
Employee datasite:example.com ext:xlsx intext:(email OR phone)Spreadsheets leak PII

CTF angle: many OSINT-flavoured CTF challenges (and HackTheBox “starting point”/recon-heavy boxes) hide a flag in an indexed file, a robots.txt entry, or a directory listing. The intitle:"index of" and ext: patterns are exactly the muscle memory those challenges reward.


Part 5: robots.txt, sitemaps and other free maps

Section titled “Part 5: robots.txt, sitemaps and other free maps”

Dorking pairs naturally with two files every web recon starts from.

https://example.com/robots.txt tells crawlers what not to index. Attackers read it precisely because the Disallow: lines often point straight at the sensitive stuff:

User-agent: *
Disallow: /admin/
Disallow: /backup/
Disallow: /internal-api/
Disallow: /config/

The site owner intended to hide these from search — instead they handed you a curated list of interesting paths. robots.txt never enforces access control; it is a request to well-behaved bots, and you are not a well-behaved bot.

https://example.com/sitemap.xml is the opposite: an explicit list of URLs the owner wants indexed. It’s a fast way to enumerate the intended content surface and spot naming conventions (e.g. /user/12345) that hint at IDOR later.

https://example.com/.well-known/ holds standardised metadata: security.txt (a contact for vulnerability reports — read it, it defines how to disclose), openid-configuration, apple-app-site-association (which can reveal app deep-link routes and internal API paths).

flowchart TD
    A[Target domain] --> B[robots.txt: Disallow hints]
    A --> C[sitemap.xml: intended URLs]
    A --> D[.well-known/security.txt: disclosure contact]
    B --> E[Candidate sensitive paths]
    C --> E
    E --> F[Cross-check against dork results]

Part 6: Beyond Google — Bing, DuckDuckGo, Yandex and specialised engines

Section titled “Part 6: Beyond Google — Bing, DuckDuckGo, Yandex and specialised engines”

No single engine indexes everything, and each has quirks worth exploiting. Diversify.

Bing supports most of the same operators plus a few unique ones:

  • ip:1.2.3.4 — returns other sites hosted on the same IP. This is genuinely powerful for finding co-hosted / virtually-hosted sites and expanding an attack surface. Google has no clean equivalent.
  • contains:filetype — pages linking to a given file type.
  • feed: — find RSS/Atom feeds.
site:example.com filetype:pdf (Bing)
ip:203.0.113.10 (Bing — co-hosted sites)

DDG supports site:, filetype:, intitle:, and its “bang” shortcuts (!g, !bing) to redirect a query to another engine instantly. Its value in recon is a different index and less aggressive result personalisation.

Yandex’s image search and its willingness to index content other engines drop make it a strong second opinion, especially for reverse image search (Chapter 11) and content in non-Western regions.

6.4 Specialised / infrastructure engines (preview)

Section titled “6.4 Specialised / infrastructure engines (preview)”

Google indexes content; a different family of engines indexes hosts and services:

  • Shodan / Censys / FOFA / ZoomEye — index open ports, banners, TLS certs and device fingerprints across the whole IPv4 space. These are covered in depth in Chapter 9; mentally file them as “Google for machines.”
  • GrayHatWarfare — indexes public cloud buckets specifically.
  • PublicWWW / IntelligenceX — search source code, markup and leaked data across many sites (e.g. find every site embedding a given analytics ID or API key).
EngineBest forSignature operator
GoogleBroad content, filessite: filetype:
BingCo-hosted sitesip:
DuckDuckGoAlt index, bangs!g
YandexImages, regional(reverse image)
ShodanOpen services/devicesport: org:
GrayHatWarfarePublic buckets(bucket search)
PublicWWWSource/markup search(code strings)

Part 7: The Google Hacking Database (GHDB) and automation

Section titled “Part 7: The Google Hacking Database (GHDB) and automation”

You do not have to invent every dork. The Google Hacking Database (GHDB), hosted by Exploit-DB (Offensive Security), is a curated, categorised, community-maintained collection of thousands of dorks — “Files Containing Passwords,” “Sensitive Directories,” “Vulnerable Servers,” “Error Messages,” etc. It is the canonical reference and the origin of the term.

How to use it as a professional: browse the category relevant to your goal, understand why each dork works (never paste blindly), and adapt the pattern to your scope by adding site:target. Treat GHDB as a pattern library, not a magic button.

Several tools automate dorking, but automation collides head-on with search engines’ anti-bot defences and terms of service. Understand each before use:

  • Search-engine ToS: automated scraping of Google results violates its ToS and triggers CAPTCHAs / temporary IP blocks. Respect rate limits; prefer official APIs where they exist.
  • Google Programmable Search Engine / Custom Search JSON API — the legitimate, rate-limited way to query programmatically (limited free quota, then paid).
  • googler — a CLI that fetches Google results; convenient for a human running a handful of queries, not for hammering thousands.
  • Recon frameworks (theHarvester, Recon-ng, SpiderFoot — full treatment in Chapter 6) include dork/search modules that pull from multiple engines with pacing built in.

OPSEC note (ties back to Chapter 3): run heavy dorking from a research environment, not your daily IP; expect and handle CAPTCHAs; never automate at a rate that looks like abuse. Getting your IP throttled mid-engagement is a self-inflicted wound.

flowchart LR
    A[Goal: e.g. exposed secrets] --> B[Pick GHDB category / craft dork]
    B --> C[Add site: scope]
    C --> D[Run across Google + Bing + DDG]
    D --> E{Hit?}
    E -->|Yes| F[Manually verify + screenshot + log]
    E -->|No| G[Refine operators / try archive]
    F --> H[Evidence pack for report]

Part 7.5: An Extended Dork Arsenal and Real-World Exposure Patterns

Section titled “Part 7.5: An Extended Dork Arsenal and Real-World Exposure Patterns”

The category dorks in Part 3 are the spine, but a professional keeps a much larger, well-organised arsenal and — crucially — understands the breach patterns behind each one so they can improvise new dorks on the spot. This section deepens both.

# Framework env files (never web-reachable, routinely are)
site:example.com ext:env "APP_KEY"
site:example.com ext:env "AWS_SECRET_ACCESS_KEY"
site:example.com ext:env "STRIPE_SECRET"
# Connection strings and DSNs
site:example.com intext:"jdbc:mysql://"
site:example.com intext:"mongodb+srv://"
site:example.com intext:"Data Source=" intext:"Password="
# Private keys and secrets in any file type
site:example.com intext:"-----BEGIN OPENSSH PRIVATE KEY-----"
site:example.com intext:"-----BEGIN PGP PRIVATE KEY BLOCK-----"
site:example.com intext:"aws_access_key_id"
# Cloud/service tokens
site:example.com intext:"xoxb-" # Slack bot token pattern
site:example.com intext:"ghp_" # GitHub personal access token prefix
site:example.com intext:"sk_live_" # Stripe live key prefix

Each of these works because the shape of a secret is predictable even when its value is not. Tokens have prefixes (ghp_, xoxb-, sk_live_), keys have banner lines (-----BEGIN...), connection strings have schemes (jdbc:, mongodb+srv:). You are pattern-matching the container, not guessing the contents.

7.5.2 Framework- and product-specific dorks

Section titled “7.5.2 Framework- and product-specific dorks”

Different stacks expose different tell-tale artefacts. Recognising the stack (Chapter 10 covers active fingerprinting) lets you fire targeted dorks:

Stack / productHigh-signal dorkWhat it finds
WordPresssite:example.com inurl:wp-content inurl:uploadsUploaded files, sometimes backups
WordPresssite:example.com inurl:wp-config.php.bakBacked-up config with DB creds
Laravelsite:example.com ext:env "APP_ENV"Framework env secrets
Jenkinssite:example.com intitle:"Dashboard [Jenkins]"CI server, often unauth
GitLabsite:example.com intitle:"GitLab" inurl:users/sign_inSelf-hosted GitLab
phpMyAdminsite:example.com inurl:phpmyadmin intitle:"phpMyAdmin"DB admin panel
Grafanasite:example.com intitle:"Grafana" inurl:loginMetrics dashboards
Kibana / ELKsite:example.com inurl:app/kibanaLog/data dashboards
Spring Bootsite:example.com inurl:actuator/envActuator endpoints leaking config
Swagger/OpenAPIsite:example.com inurl:swagger-ui.htmlFull API documentation

The Swagger/OpenAPI dork deserves special mention: an exposed API doc hands you every endpoint, parameter and expected payload — a complete map for the testing you’ll do in the web-app phase.

filetype: dorks for pdf, docx, xlsx and pptx are valuable twice over: the content may be sensitive, and the metadata embedded in Office/PDF files routinely leaks internal usernames, software versions, local file paths, printer names and email addresses. This is the bridge into Chapter 11 (metadata OSINT with ExifTool). A single internal PowerPoint can reveal the naming convention for employee accounts (jsmith, mjones) that later seeds a password-spray target list.

site:example.com filetype:pdf "internal use only"
site:example.com filetype:docx "confidential"
site:example.com filetype:xlsx (intext:"@example.com")

The reason these dorks keep working, year after year, comes down to a handful of recurring organisational failures. Internalise the pattern and you can invent dorks faster than any list:

flowchart TD
    A[Developer convenience] --> B[Secret committed / backup left in web root]
    B --> C[Crawler follows a link or sitemap]
    C --> D[Content indexed]
    D --> E[Dork retrieves it]
    F[Ops shortcut] --> G[Directory listing left on / bucket set public]
    G --> C
    H[Removed but not de-indexed] --> I[Archive / cache retains copy]
    I --> E
  • Convenience over hygiene: a developer drops config.php.bak next to config.php to test a change, and forgets it. Backups (.bak, .old, ~, editor swap files .swp) are the single richest source of source-and-secret leaks.
  • Default-on features: directory listing and verbose errors ship enabled in many stacks; nobody turns them off.
  • Public-by-accident storage: a bucket or share flipped to public “just for a minute” during a migration and never reverted.
  • Remove ≠ de-index: taking a file down does not remove it from caches, archives or third-party mirrors.

Every dork you will ever write is really a query for one of these four failures against a specific technology.

7.5.5 Notable public exposure classes (illustrative)

Section titled “7.5.5 Notable public exposure classes (illustrative)”

Without naming victims, these exposure classes have driven real, publicly reported incidents and bug-bounty payouts and are worth recognising:

  • Exposed .git directories enabling full source reconstruction, which then reveal hardcoded credentials and every API route.
  • Public cloud buckets (s3.amazonaws.com, storage.googleapis.com, blob.core.windows.net) containing customer PII, indexed and searchable.
  • Spring Boot Actuator /env and /heapdump endpoints leaking environment variables and, via heap dumps, live secrets and session tokens.
  • Indexed .env files giving away database credentials and third-party API keys for entire SaaS products.
  • CI/CD dashboards (Jenkins/GitLab) left unauthenticated, exposing build logs that themselves contain secrets.

Recognising the class is what lets you say, on a new engagement, “let me check for an exposed Actuator” before you have any specific evidence one exists.


Part 8: Hands-On Lab — A Disciplined Dorking Pass

Section titled “Part 8: Hands-On Lab — A Disciplined Dorking Pass”

Scope and ethics first. This lab assumes you have written authorisation for a target, OR you use a domain you own, OR you practise the operators against broad, public, non-targeted queries. Do not run credential-hunting dorks against organisations you have no permission to test, and never access, download, or use data you find that belongs to a third party outside your scope.

We’ll model the workflow against a placeholder authorised scope acme-scope.example and record everything.

Create a simple, timestamped log so every finding is reproducible and defensible.

Terminal window
mkdir -p ~/engagements/acme/dorking/screens
cd ~/engagements/acme/dorking
cat > log.md <<'EOF'
# Dorking Log — ACME (authorised, ref: SOW-2024-014)
| # | Dork | Engine | Result summary | Evidence | Severity |
|---|------|--------|----------------|----------|----------|
EOF
echo "Log initialised at $(date -u) UTC"

Sample output:

Log initialised at 2026-09-27 05:41:12 UTC

Step 2 — Baseline: how much does Google know?

Section titled “Step 2 — Baseline: how much does Google know?”

Query site:acme-scope.example and note the approximate result count and the subdomains that appear. Record the number.

site:acme-scope.example
site:acme-scope.example -www # non-www hosts

Log entry example:

| 1 | site:acme-scope.example | Google | ~1,240 results; found dev., staging., portal. subdomains | screens/01-baseline.png | Info |

Step 3 — Sweep the high-value categories

Section titled “Step 3 — Sweep the high-value categories”

Run each category dork, one at a time, and record hits. Do not fire them all blindly — read each result.

site:acme-scope.example intitle:"index of"
site:acme-scope.example ext:env
site:acme-scope.example ext:sql intext:"INSERT INTO"
site:acme-scope.example ext:(bak OR old OR zip)
site:acme-scope.example inurl:(admin OR login OR phpmyadmin)
site:acme-scope.example inurl:.git
site:acme-scope.example filetype:xlsx

Realistic annotated result for the directory-listing dork:

Result: https://staging.acme-scope.example/uploads/
Title: Index of /uploads
Body: Parent Directory db_backup_2023.sql config.old users.csv

That single hit is three findings: a directory listing enabled on staging, a database backup, and an exposed CSV. Screenshot the search result and, only if in scope and authorised, verify the resource exists (a HEAD request or a single browser load) — do not mass-download.

For each candidate, confirm it’s real and note the minimum needed to prove impact.

Terminal window
# Confirm the file is reachable (authorised scope only) — HEAD only, no download of PII
curl -sI "https://staging.acme-scope.example/uploads/db_backup_2023.sql"

Sample output:

HTTP/2 200
content-type: application/sql
content-length: 8419233
last-modified: Tue, 14 Nov 2023 09:02:11 GMT

The 200 and content-length prove existence and rough size. That is enough for the report — you do not download 8 MB of customer data to “confirm.” Note the finding and move on. (This restraint is both ethical and legal; see Part 9.)

Re-run the two best dorks on Bing and DuckDuckGo. Different indexes catch different files, and the Bing ip: operator can reveal co-hosted sites you did not know were in scope:

site:acme-scope.example ext:env (Bing)
ip:203.0.113.42 (Bing — what else lives on this host?)

Step 6 — Archive check for removed content

Section titled “Step 6 — Archive check for removed content”

If a promising URL 404s on the live site, check the Wayback Machine:

Terminal window
curl -s "http://archive.org/wayback/available?url=staging.acme-scope.example/config.php"

Sample output:

{"archived_snapshots":{"closest":{"available":true,
"url":"http://web.archive.org/web/20230711084512/https://staging.acme-scope.example/config.php",
"timestamp":"20230711084512","status":"200"}}}

The live file is gone; the archive kept a copy. This is how “we removed that” becomes “the credentials were public for eight months.”

Your log.md now contains reproducible dorks, engines, summaries, screenshots and severities. That table is the appendix of your recon report and lets a reviewer re-run every finding.

Final log excerpt:

| 3 | site:acme-scope.example intitle:"index of" | Google | Dir listing on staging /uploads with DB backup + users.csv | screens/03-index.png | High |
| 4 | curl -I .../db_backup_2023.sql | manual | 200, 8.4MB SQL dump reachable | screens/04-head.png | Critical |

Part 8.5: Second Mini-Lab — A Cross-Engine Bucket & Co-Host Hunt

Section titled “Part 8.5: Second Mini-Lab — A Cross-Engine Bucket & Co-Host Hunt”

The first lab focused on a single domain in Google. This shorter lab shows how to pivot across engines to expand the attack surface — the skill of not stopping at one index.

Step 1 — Find public buckets tied to the org

Section titled “Step 1 — Find public buckets tied to the org”

Cloud buckets are frequently named after the company or product. Search Google, then a bucket-specialised engine.

# Google / Bing
site:s3.amazonaws.com acme
site:storage.googleapis.com acme
site:blob.core.windows.net acme

Then on GrayHatWarfare (bucket-specialised index), search the keyword acme. Sample conceptual result:

acme-backups.s3.amazonaws.com 1,204 files (public)
acme-static-assets.s3... 18,540 files (public)

acme-backups being public is a critical-severity lead. Record it; verify existence with a single listing request only if in scope — never bulk-download.

Step 2 — Expand via co-hosting (Bing ip:)

Section titled “Step 2 — Expand via co-hosting (Bing ip:)”

Resolve one in-scope host to an IP, then ask Bing what else lives there:

Terminal window
dig +short portal.acme-scope.example

Sample output:

203.0.113.42
ip:203.0.113.42 (Bing)

Sample results:

portal.acme-scope.example
legacy.acme-scope.example
vendor-tool.acme-scope.example

legacy. and vendor-tool. are hosts you had not enumerated yet. Confirm they are in scope before touching them; if they are, they join the target list for Chapter 5’s subdomain work and the scanning phase.

Step 3 — Source-string pivot (PublicWWW)

Section titled “Step 3 — Source-string pivot (PublicWWW)”

If you found a unique identifier (a Google Analytics ID UA-XXXXX, a custom JS bundle hash, an API key fragment), search PublicWWW for every other site embedding the same string. This finds sibling properties and staging clones the org forgot about:

"UA-11223344-1" (PublicWWW — every site using this analytics ID)

Sample results might reveal acme-labs.example and acme-internal-tools.example — previously unknown, now candidates for scope confirmation.

Step 4 — Decision tree for what to do with a hit

Section titled “Step 4 — Decision tree for what to do with a hit”
flowchart TD
    A[Dork returns a candidate] --> B{In authorised scope?}
    B -->|No| C[Do not access. Note as out-of-scope exposure. Report via disclosure channel.]
    B -->|Yes| D{Sensitive data?}
    D -->|Yes| E[Prove existence with HEAD/listing only. Screenshot. Log. Do NOT download PII.]
    D -->|No| F[Note as info/low. Continue.]
    E --> G[Add to evidence pack with severity]
    F --> G
    C --> G

This decision tree is the discipline that separates a professional from someone who gets themselves into legal trouble. Every hit runs through it.


Dorking sits in a legally sensitive place, and professionals stay well inside the line.

  • Crafting and running search queries is not, by itself, unauthorised access. You are querying a public search engine. That is legal.
  • Accessing the exposed resource may be a different matter. Loading a public URL is generally fine, but using exposed data (downloading a customer database, using leaked credentials to log in) can constitute unauthorised access under laws like the US CFAA, the UK Computer Misuse Act, and equivalents worldwide — even if the resource was “public.” The exposure being someone else’s mistake is not a defence.
  • Scope is everything. In a paid engagement or bug-bounty program, act only within the documented scope and rules of engagement (Chapter 2). If a dork surfaces data belonging to a third party not in your scope, stop, do not download it, and report the exposure appropriately.
  • Minimise. Prove existence and impact with the least intrusive evidence (a HEAD request, a screenshot of the result), never a full exfiltration.
  • Responsible disclosure. If you find an exposure with no engagement in place, use security.txt or a formal disclosure channel; do not tweet the URL.

The habit that keeps you safe: find, verify minimally, document, report — never exploit or hoard.


Everything above is also a defensive checklist. If you run a security or platform team, you should be dorking your own estate continuously.

Find your own exposure:

  • Run the full category sweep (Part 3) against every domain you own, on a schedule. If Google can find your .env, so can everyone else.
  • Monitor for new indexed content with before:/after: and saved queries; alert on new filetype:sql, ext:env, or intitle:"index of" hits under your domains.
  • Search GrayHatWarfare and cloud-native tooling for your own public buckets.
  • Watch PublicWWW / IntelligenceX for your API keys, internal hostnames, or unique strings leaking on third-party sites and pastebins.

Prevent indexing of sensitive content:

  • Never rely on robots.txt for security — it advertises, it does not protect. Put real access control (authentication, network restrictions) in front of anything sensitive.
  • Use X-Robots-Tag: noindex HTTP headers and <meta name="robots" content="noindex"> for pages that must not be indexed — but treat these as defence-in-depth, not the primary control.
  • Disable directory listing (Options -Indexes on Apache; autoindex off; on nginx). This kills the entire intitle:"index of" class.
  • Keep secrets out of web roots entirely: .env, .git, backups, dumps and configs should live outside any web-served directory and be blocked at the server (location ~ /\.git { deny all; }).
  • Lock down cloud buckets to private-by-default; enable public-access-block at the account level.

Remove what’s already indexed:

  • Fix the underlying exposure first (remove/secure the file), then use Google Search Console’s Removals tool to expedite de-indexing, and request cache purges. De-indexing without removing the file is theatre — the file is still reachable directly.

Detect adversary dorking:

  • Pure Google dorking is invisible to you — the queries hit Google, not your servers. You cannot log it.
  • What you can detect is the follow-up: sudden hits to /.git/, /.env, /backup/, sitemap-derived paths, or unusual User-Agents pulling many static file types. Alert on requests for known-sensitive paths (a “canary path” that should never be requested legitimately is a cheap tripwire).
  • Deploy honeytokens: a fake admin page or a decoy credentials.txt containing a canary token that fires an alert the moment anyone opens it.
flowchart TD
    A[Attacker dorks Google] -->|invisible to you| B[Finds exposed path]
    B --> C[Requests /.git or /.env on your server]
    C --> D{WAF / access rule}
    D -->|blocked + logged| E[Alert fires]
    D -->|allowed| F[Exposure hit]
    G[You dork your own estate] --> H[Find exposure first]
    H --> I[Remove file + de-index + honeytoken]
    I --> D

  • Blindly pasting GHDB dorks without site: scope, then poking exposures that belong to random third parties. That is not testing; it can be a crime. Always scope.
  • Treating a zero-result dork as “nothing exists.” It only means “nothing indexed.” Active discovery still to come.
  • Downloading found data “to confirm.” Prove existence with a HEAD request or screenshot. Hoarding third-party data is an ethical and legal disaster.
  • Getting your IP CAPTCHA-blocked by hammering Google with automation. Pace yourself; use official APIs; run from a research environment.
  • Ignoring cache/archive when a page 404s. The most damaging findings are often the ones the target thinks they removed.
  • Relying on robots.txt/noindex as security (defenders) — they are indexing hints, not access controls.
  • Forgetting other engines. Bing’s ip: and specialised engines routinely find what Google won’t.

  • A search engine is a crawler + index + ranker; operators override the ranker to query structure, not just content.
  • You query the index (and caches/archives), never the live target — which makes dorking a passive, low-noise, high-value technique.
  • Core operators: site: (scope), inurl:/intitle:/filetype: (structure), intext:/quotes/AROUND (content), boolean glue (OR, -, ()), and time filters (before:/after:).
  • Combine them into category dorks for directory listings, configs/secrets, DB dumps, backups, admin panels, source/VCS leaks, cloud buckets and error pages.
  • Pair dorking with robots.txt, sitemap.xml and .well-known/ for free maps of intended and hidden paths.
  • Diversify across Bing (ip: co-hosting), DuckDuckGo, Yandex, and infrastructure engines (Shodan/Censys — Chapter 9), plus GrayHatWarfare and PublicWWW.
  • Use the GHDB as a pattern library; automate only within ToS/rate limits and from a research environment.
  • Legality: running queries is fine; accessing/using exposed third-party data may not be. Scope, minimise, document, report — never exploit or hoard.
  • Defenders should dork their own estate continuously, disable directory listing, keep secrets out of web roots, lock down buckets, and use honeytokens plus sensitive-path alerting for the follow-up requests.

# Scope
site:example.com only this domain + subdomains
site:sub.example.com only this subdomain
site:example.com -www non-www hosts
# Structure
inurl:admin text in URL
allinurl: admin login all terms in URL
intitle:"index of" text in title (directory listing)
filetype:sql / ext:env by extension
# Content
intext:"password" body text
"exact phrase" exact match
"user" AROUND(3) "password" proximity
term1 OR term2 / term1 | term2 boolean OR
-exclude remove noise
( ) grouping
before:2024-01-01 / after:2024-01-01 date bounds
# High-value one-liners (add site: your-scope)
intitle:"index of" (backup OR sql OR env OR old)
ext:env intext:"DB_PASSWORD"
ext:sql intext:"INSERT INTO"
inurl:.git
inurl:(admin OR login OR phpmyadmin)
ext:(bak OR old OR zip OR tar OR gz)
filetype:(xlsx OR csv OR pdf)
# Other engines
Bing: ip:203.0.113.10 co-hosted sites
Bing: site:example.com filetype:pdf
DDG: !g <query> redirect to Google
Shodan: org:"Example" port:443 (Chapter 9)
GrayHatWarfare public S3/GCS/Azure buckets
# Free maps
/robots.txt /sitemap.xml /.well-known/security.txt
# Archive recovery
http://archive.org/wayback/available?url=<url>

Defender quick actions: disable directory listing • keep .env/.git/backups out of web root • block dotfiles at the server • private-by-default buckets • noindex + Search Console Removals for cleanup • honeytokens + sensitive-path alerts.


Part 13.5: Building and Maintaining Your Personal Dork Library

Section titled “Part 13.5: Building and Maintaining Your Personal Dork Library”

Professionals do not retype dorks from memory each engagement; they maintain a version-controlled library and a small workflow around it. This turns dorking from an ad-hoc activity into a repeatable, auditable process.

Structure a simple library as a text or YAML file grouped by objective, with a placeholder token you substitute per target:

# dorks.yml — substitute {{DOMAIN}} per engagement
directory_listing:
- 'site:{{DOMAIN}} intitle:"index of"'
- 'site:{{DOMAIN}} intitle:"index of" (backup OR sql OR env OR old)'
secrets:
- 'site:{{DOMAIN}} ext:env'
- 'site:{{DOMAIN}} ext:env intext:"DB_PASSWORD"'
- 'site:{{DOMAIN}} intext:"-----BEGIN OPENSSH PRIVATE KEY-----"'
db_dumps:
- 'site:{{DOMAIN}} ext:sql intext:"INSERT INTO"'
backups:
- 'site:{{DOMAIN}} ext:(bak OR old OR zip OR tar OR gz)'
panels:
- 'site:{{DOMAIN}} inurl:(admin OR login OR phpmyadmin)'
vcs:
- 'site:{{DOMAIN}} inurl:.git'
api_docs:
- 'site:{{DOMAIN}} inurl:swagger-ui.html'
- 'site:{{DOMAIN}} inurl:actuator/env'

A trivial substitution script turns the library into a ready-to-run list:

#!/usr/bin/env bash
# gen-dorks.sh <domain> — emit runnable dorks for a scope
DOMAIN="$1"
[ -z "$DOMAIN" ] && { echo "usage: $0 example.com"; exit 1; }
grep -oE "'[^']+'" dorks.yml | tr -d "'" | sed "s/{{DOMAIN}}/$DOMAIN/g"

Sample run:

Terminal window
$ ./gen-dorks.sh acme-scope.example | head -4
site:acme-scope.example intitle:"index of"
site:acme-scope.example intitle:"index of" (backup OR sql OR env OR old)
site:acme-scope.example ext:env
site:acme-scope.example ext:env intext:"DB_PASSWORD"

Maintenance habits that keep the library sharp:

  • Prune dead operators. Google deprecates operators over time (cache:, link:); mark or remove them so you don’t waste queries.
  • Tag each dork with the failure pattern it targets (backup-in-webroot, public-bucket, verbose-error). When you learn a new pattern, add a dork; when a stack changes, add stack-specific entries.
  • Record hit rates. Note which dorks actually produced findings across engagements — over time you learn which five dorks find 80% of the criticals, and you run those first.
  • Keep it version-controlled and private. Your refined library is genuinely valuable tradecraft; treat it like tooling, not disposable notes.

This library becomes the input to the recon frameworks in Chapter 6, which can iterate a dork list across multiple engines with pacing and de-duplication built in.


Train the exact skills in this chapter, safely and legally:

  • Google Hacking Database (GHDB) on Exploit-DB — read a category, understand why each dork works, then reproduce the pattern against a domain you own.
  • PortSwigger Web Security Academy — while focused on web vulns, its labs on information disclosure and directory traversal reinforce what indexed exposures lead to.
  • TryHackMe — “Google Dorking” room, “OSINT” room, and “Passive Reconnaissance” teach the operators hands-on with guided targets.
  • HackTheBox — “Starting Point” and recon-heavy machines frequently reward reading robots.txt, finding indexed files, and directory listings.
  • VulnHub — download and run boxes locally; practise dorking against a self-hosted domain you control end to end.
  • GrayHatWarfare — search for open buckets (practise identifying exposure classes without touching third-party data).
  • Your own domain — the safest lab of all. Stand up a small site, deliberately misconfigure a directory listing and an .env, watch it get indexed, then practise finding and fixing it.

Practice questions:

  1. Write a single Google dork that finds SQL database dumps containing INSERT INTO statements on target.com, and explain which operator does the scoping vs. the structure filtering.
  2. A page you need 404s on the live site. Describe two ways to still recover its content and why the live 404 doesn’t mean the content is gone.
  3. Your dork returns zero results for site:target.com ext:env. Give two distinct reasons this does not prove no .env file exists.
  4. You find an indexed users.csv belonging to a company that is not in your engagement scope. Walk through exactly what you should and should not do.
  5. As a defender, list the four controls (in order of importance) that would eliminate the intitle:"index of" and ext:env finding classes, and explain why robots.txt is not one of them.

Discussion

Questions, corrections, or something to add? Comment with your GitHub account.