AnswerLineStart free

, Google · SERP API · Engineering · Tutorials

Google dorking for defenders: find what your own domains expose in search

Google dorking for defenders is running targeted search operator queries against domains you own to find what should never have been indexed: internal documents, exposed directory listings, forgotten staging hosts, error pages that leak stack traces, and configuration or backup files. Attackers use the same operators for reconnaissance. The defensive version runs first, runs on a schedule, and ends in a fix.

OWASP’s Web Security Testing Guide includes search engine discovery as an information-gathering test and calls the operator-chaining technique Google hacking or dorking (checked 2026-09-17). This guide stays on the defensive side: every query is scoped to your own domains, and every finding leads to removal, not exploitation.

Ground rules

Put these in writing before anyone runs a query:

  1. Scope is your assets. Domains and subdomains your organization owns or has written authorization to assess. Every query carries a site: for an in-scope domain.
  2. Confirm, don’t collect. When a result looks sensitive, confirm the exposure from the search result and the URL, then hand it to the owner. Do not bulk-download exposed files, and do not use any credentials you find, even to “check if they work”. Rotate them instead.
  3. Findings outside scope are reported, not explored. If a query surfaces data about another organization, stop and follow your responsible-disclosure process.
  4. Personal data is handled as an incident. Exposed customer or employee data triggers your incident and privacy procedures, not a spreadsheet.
  5. Nothing here is legal advice. Your legal team defines authorization and disclosure rules.

The operators you need

Google’s Refine Google searches help page (checked 2026-09-17) documents these:

Operator Documented use Defensive use
"..." Exact word or phrase Match exact strings such as “confidential” or an internal project name
- Leave a word out Exclude your main public site to see the long tail
site: Limit to a site or domain Scope every query to an owned domain
filetype: Limit to a file type Find documents, spreadsheets, logs and exports
before: / after: Limit by date Focus on newly indexed exposure

Two caveats from Google’s own site: operator documentation (checked 2026-09-17): the operator “doesn’t necessarily return all the URLs that are indexed under the prefix,” and a bare site: query without other terms is not ranked, so result order is fairly random.

Other operators such as intitle: and inurl: are widely used but are not on that help page. Test how they behave on your own domains before relying on them in automated templates.

A defensive query library

Replace example.com with each domain you own. Queries are grouped by what they find and why it matters.

1. Subdomain and host inventory

site:example.com -site:www.example.com
site:example.com -site:www.example.com -site:docs.example.com -site:blog.example.com

The first shows indexed hosts other than your main site. Progressively exclude the hosts you know about; whatever remains is either shadow IT, a forgotten staging environment or a vendor-hosted page on your domain. Every unknown host becomes an inventory ticket.

2. Staging, test and development environments

site:example.com staging
site:example.com (dev OR test OR uat OR sandbox) login

Indexed staging environments often run old code, weaker authentication and copies of production data.

3. Documents that should be internal

site:example.com filetype:pdf (confidential OR "internal use only" OR "do not distribute")
site:example.com filetype:xlsx
site:example.com filetype:docx "draft"
site:example.com filetype:pptx

Spreadsheets and slide decks are the usual leaks: price lists, customer exports, board material, org charts. PDFs marked confidential are sometimes intentional (published contracts), so a person decides.

4. Logs, exports, backups and configuration

site:example.com filetype:log
site:example.com filetype:sql
site:example.com filetype:csv
site:example.com (filetype:bak OR filetype:old OR filetype:env)

Any hit here is almost always a finding. Treat configuration files as a credential exposure: rotate first, investigate second.

5. Directory listings

site:example.com "index of /"
site:example.com "parent directory"

Open directory listings expose everything a web server can read in that folder, including files nobody linked to.

6. Error pages and debug output

site:example.com ("stack trace" OR "traceback" OR "exception")
site:example.com ("warning:" OR "fatal error") "on line"

Indexed error pages reveal framework versions, file paths and sometimes queries. The fix is usually a production error handler plus removal of the indexed URLs.

7. Exposed admin and internal tools

site:example.com (admin OR dashboard OR phpmyadmin OR grafana OR jenkins)
site:example.com "sign in" -site:www.example.com

The goal is inventory: which login surfaces are public and indexed. Do not attempt to log in.

8. Your organization’s name on public collaboration and paste sites

Leaks do not only happen on your domains. Staff share boards, documents and snippets on third-party services.

"example.com" "api_key"
"@example.com" filetype:xlsx -site:example.com
"Example Corp" "internal use only" -site:example.com

These queries leave your own scope, so the rules tighten: confirm the exposure from the result’s title, URL and snippet, report it to the platform and to the internal owner, and do not download or retain the content.

Running the library on a schedule

Manual dorking finds today’s exposure. A scheduled run finds next month’s, which is when it matters. The pattern:

  1. Expand templates × owned domains into queries.
  2. Submit them as async tasks.
  3. For each completed task, extract organicResults[].link.
  4. Diff against URLs already seen and triaged.
  5. Alert on new URLs, grouped by template category.

A single query through the API:

curl -X POST https://api.answerline.dev/v1/monitor/google \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "site:example.com filetype:xlsx",
    "country": "US",
    "pages": 3
  }'

Google interprets the operators in the query text; the response’s result.organicResults[] carries position, title, link, displayedLink, snippet, date and page. Use pages (1 to 10) for categories where a domain can legitimately have many results.

A scheduled batch in Python, using plain requests:

import datetime as dt, os, requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

DOMAINS = ["example.com", "example.io"]
TEMPLATES = {
    "hosts": "site:{d} -site:www.{d}",
    "docs": 'site:{d} filetype:pdf (confidential OR "internal use only")',
    "sheets": "site:{d} filetype:xlsx",
    "logs": "site:{d} (filetype:log OR filetype:sql OR filetype:env)",
    "listing": 'site:{d} "index of /"',
    "errors": 'site:{d} ("stack trace" OR traceback)',
}

def submit_week():
    week = dt.date.today().strftime("%G-W%V")
    tasks = [
        {
            "taskType": "GOOGLE",
            "payload": {"query": q.format(d=d), "country": "US", "pages": 2},
            "idempotencyKey": f"dork:{d}:{name}:{week}",
            "webhook": {"url": "https://hooks.example.com/exposure"},
        }
        for d in DOMAINS
        for name, q in TEMPLATES.items()
    ]
    lookup = {}
    for i in range(0, len(tasks), 500):
        chunk = tasks[i:i + 500]
        r = requests.post(f"{API}/v1/async/task/batch", json=chunk, headers=HEADERS, timeout=60)
        r.raise_for_status()
        for item in r.json()["results"]:
            if item["success"]:
                _, domain, template, _ = chunk[item["index"]]["idempotencyKey"].split(":")
                lookup[item["task"]["id"]] = (domain, template)
    return lookup  # persist this mapping

The webhook handler verifies the signature (see webhooks), reads the domain and template from a lookup keyed by task id, and inserts each link into a seen_urls table with a unique constraint on (domain, template, url). Inserts that succeed are new findings; the rest are already known.

from urllib.parse import urlsplit

def new_findings(db, domain, template, organic):
    for r in organic:
        host = (urlsplit(r["link"]).hostname or "").lower()
        if not (host == domain or host.endswith("." + domain)):
            continue  # stay in scope even if Google returns something odd
        cur = db.execute(
            "insert into seen_urls (domain, template, url, title, snippet) values (%s,%s,%s,%s,%s) "
            "on conflict do nothing returning url",
            (domain, template, r["link"], r.get("title"), r.get("snippet")),
        )
        if cur.fetchone():
            yield r

The in-scope host check matters: it guarantees the pipeline never alerts on, or stores, results outside domains you own, whatever the query returns.

For category 8 (third-party sites), run a separate, smaller job with its own reviewers and retention rules, and store only the URL, title and the decision.

Triage

Category Default severity First action
Config, env, SQL, backup files Critical Remove access, rotate secrets, open an incident
Exports with personal data Critical Remove access, start the privacy incident process
Directory listing High Disable listing, review folder contents
Internal documents High Confirm with owner, remove or restrict
Staging or dev host indexed Medium Put behind authentication, noindex
Error pages Medium Fix error handling, remove URLs
Unknown host Medium Identify owner, add to inventory
Admin surface indexed Low to medium Confirm it should be public; restrict if not

Remediation

Search visibility is a symptom. Fix in this order:

  1. Remove or restrict access. Delete the file, or put it behind authentication. Until this happens, the file is exposed to anyone with the URL, indexed or not.
  2. Rotate anything secret that was exposed, and review access logs for the period it was reachable.
  3. Keep it out of the index. Google’s noindex documentation (checked 2026-09-17) explains that for noindex to work, the page “must not be blocked by a robots.txt file,” because a crawler that cannot fetch the page never sees the rule, and the URL can still appear in results.
  4. Do not rely on robots.txt for secrecy. RFC 9309, the Robots Exclusion Protocol, says its rules “are not a form of access authorization.” A robots.txt file also publicly lists the paths you would rather hide.
  5. Speed up removal from results. Google’s Removals tool (checked 2026-09-17) works for URLs in a Search Console property you own; a successful request lasts about six months and does not stop crawling, so the permanent fix (404 or 410, access control, or noindex) still has to be in place.
  6. Re-run the query after the removal window to confirm the URL is gone, and keep it in seen_urls with the resolution.

Metrics

Metric What it tells you
New findings per week, by category Whether exposure is growing
Time from detection to access removed Response speed, the number that matters
Time from access removed to out of index Whether removal steps are followed
Reintroduced findings Same URL pattern appearing again: a process gap
Unknown hosts discovered Inventory quality

Cost

A Google Search async task costs 3 credits for the first page and 2 for each additional page. The example above runs 6 templates × 2 domains × 2 pages weekly: 12 tasks × (3 + 2) credits = 60 credits a week, about 260 a month, inside the free tier’s 500 monthly credits. Twenty domains with the same library is about 2,600 credits a month; see pricing for plan sizes.

Limits of the method

Pair this with the threat intelligence use case for a broader open-web feed, OSINT tools for defenders for certificate transparency and attack-surface tools, and typosquatting detection for lookalike domains.

Start with the quickstart or the Google Search engine page.

Questions

What is Google dorking?

Google dorking, also called Google hacking, is using search operators such as site:, filetype: and exact-match quotes to find specific kinds of indexed content. Defenders use it to find what their own domains expose before someone else does.

Is it legal to run these searches?

Running a search is ordinary use of a search engine, but what you do with results can create legal and ethical problems. Restrict the practice to domains and organizations you are responsible for or authorized to assess, and do not open, download or use data that belongs to others. This is not legal advice.

Does robots.txt hide sensitive files?

No. RFC 9309 states that robots.txt rules are not a form of access authorization, and Google notes that a page blocked by robots.txt can still appear in results because the crawler never sees a noindex rule. Sensitive files need access control, not crawler instructions.

How do I get an exposed page out of Google quickly?

Fix the exposure first by removing the file or putting it behind authentication. Then, for a site you own in Search Console, the Removals tool temporarily hides the URL for about six months while the permanent fix (404, 410, access control or noindex) takes effect.

Will site: queries show everything Google has indexed on my domain?

No. Google's documentation says the site: operator does not necessarily return all indexed URLs under a prefix. Use it as a detection sweep, and use Search Console and your own inventory for completeness.

Try it on your own prompts

500 free credits a month, no card. One POST returns the answer, sources and citations as JSON.

Keep reading