Google Dorking
Dorking is using a search engine’s own query language to find things its index already holds but nobody meant to publish: config files, backups, admin panels, stack traces, cloud buckets, private keys. No packet reaches the target — you are querying Google’s copy of the web, which is why it opens Stage 00 — Passive External Recon and why it survives every firewall, WAF and rate limit the target owns.
The technique is old and the operators are few. What separates a useful dork from noise is knowing which operators still work, how they combine, and where each one silently fails.
[!danger] Indexed is not authorised Every dork on this page returns links. Following one to retrieve a config file, enumerate a bucket, or log into a panel is access, and access needs written permission — a public URL is not consent, and “it was in Google” has never been a defence. Personal data you collect is regulated (GDPR and equivalents) whether or not the engagement covers it. Use this against your own estate, a scope you hold in writing, or a lab you are entitled to.
1. Why it works — you are searching the index, not the site
A crawler finds a URL, fetches it, and the indexer stores the text, title, URL and file type. Everything dorking does is filter that stored record. Three consequences matter:
| Fact | Consequence for recon |
|---|---|
robots.txt is a crawl directive, not an access control | A Disallow: line stops polite crawlers fetching a path — it does not stop the path being served, and it publishes a list of the paths the owner considers sensitive. Fetch $DOMAIN/robots.txt first; it is a free sitemap of the interesting bits. |
Only noindex removes a page from results | X-Robots-Tag: noindex or a <meta name="robots" content="noindex"> tag is the actual removal mechanism, and it only works if the crawler is allowed in to see it. A Disallowed page that is linked from elsewhere can still appear. |
| The index outlives the file | Deleting a file does not delete the record. Titles and snippets persist for weeks; archives persist indefinitely. A dork that returns a 404 still tells you the file existed and what it was called. |
| Anything linked once is crawlable | A “secret” URL pasted into a public ticket, a README, a Slack export or a CDN log gets crawled. This is how private buckets and staging hosts end up indexed. |
The practical reading: the index is a historical record of what the target served, not a snapshot of what it serves now. Treat every hit as a lead with a timestamp, not a live finding.
2. Anatomy of a dork
site:example.com ext:sql intext:"CREATE TABLE" -site:docs.example.com
└──── scope ───┘ └─ type ┘ └───── content ────┘ └────── exclusion ─────┘
Four moving parts, and only the first is mandatory in practice:
- Scope — which hosts count (
site:). - Type — what kind of document (
ext:/filetype:). - Content — a literal that only the interesting version of the file contains (
intext:,intitle:,inurl:). - Exclusion — what to subtract once the first pass is noisy (
-site:,-inurl:).
Terms and operators are AND-ed by default. There is no AND keyword — writing one searches for the word “and”.
[!tip] Build them in that order Scope first, then type, then narrow with content, then subtract noise. Starting from a long stacked dork you copied off a list gives you zero results and no idea which clause killed it. Start broad, add one operator at a time, and watch the result count move.
3. Operator reference
Scope
| Operator | Does | Example |
|---|---|---|
site: | Restrict to a host. Matches the host as a suffix, so it covers subdomains. | site:example.com |
site:*. | Force the subdomain tree. Pair with a negative to drop the ones you know. | site:*.example.com -site:www.example.com |
-site: | Subtract a host. The main tool for forcing new subdomains to the surface. | -site:blog.example.com |
related: | Sites Google considers similar. Officially unsupported — usually returns nothing. | related:example.com |
Content position
| Operator | Matches in | Notes |
|---|---|---|
intitle: | The <title> element | Highest-signal field for fingerprinting an app by its shipped default title. |
inurl: | The whole URL, including the query string | This is why it finds parameter names: inurl:redirect=. Substring match. |
intext: | The page body | Forces a term into the body instead of letting it match the title or an inbound link. |
inanchor: | Inbound link text | Thin and unreliable now that link signals are de-emphasised. |
allintitle: allinurl: allintext: | Same fields, all following terms | Do not use. See the gotchas below. |
File type
| Operator | Does | Notes |
|---|---|---|
filetype: | One file extension | Matches the extension Google recorded, not the Content-Type header. |
ext: | Identical to filetype: | Shorter, so stacked dorks stay readable. Both work on Google, Bing and Brave. |
One extension per operator — stack them with OR to cover a family:
site:$DOMAIN ext:sql OR ext:bak OR ext:old OR ext:backup
Google indexes a fixed set of document types (pdf, doc/docx, xls/xlsx, ppt/pptx, rtf, ps, kml, txt and a handful more). A ext:env dork works only because such files were served as plain text and indexed as text — which is precisely what makes a hit worth reporting.
Logic and grouping
| Syntax | Does | Trap |
|---|---|---|
"phrase" | Exact match, in order, no stemming or synonyms | Any literal artefact — a banner, an error string, a key header — belongs in quotes. |
OR or | | Disjunction | Must be uppercase. Lowercase or is a stop word and is silently ignored. |
-term | Exclude | No space after the hyphen. Works on operators too: -site:, -inurl:. |
( ) | Grouping | Required whenever you mix OR with AND-ed terms, or precedence bites you. |
* | Whole-token wildcard | Only meaningful inside quotes. It is not a substring wildcard — adm*n does not work. |
AROUND(n) | The two terms within n words | Uppercase, no space before the bracket. Tighter than AND, looser than a phrase. |
site:$DOMAIN (ext:sql OR ext:bak) intext:password # grouped correctly
site:$DOMAIN ext:sql OR ext:bak intext:password # ambiguous — do not
password AROUND(3) database site:$DOMAIN # proximity
"confidential * report" site:$DOMAIN # token wildcard
Time and number
| Syntax | Does | Caveat |
|---|---|---|
before:YYYY-MM-DD | Documents Google dates before that day | Filters on Google’s estimate of the document date, which is frequently wrong for pages without date markup. |
after:YYYY-MM-DD | Documents Google dates after that day | Same caveat. Good for narrowing; never good enough to prove publication date. |
1000..2000 | Any number in the range | Two dots. Legal inside other operators: inurl:id=1..100. |
Retired — and what replaced them
[!warning] These appear in every dork list on the internet and none of them work
Operator Status Use instead cache:Removed by Google in September 2024, along with the cached-page links web.archive.org, archive.today link:Deprecated 2017; now a silent no-op that degrades to a keyword search Search Console (for sites you own) or a commercial backlink tool info:Retired; folded into ordinary search Just search the bare URL +termRemoved 2011 Quote the term instead: "term"daterange:Julian-date legacy syntax, unreliable before:/after:A retired operator does not error. Google drops it and searches the remaining words, so your dork returns plausible-looking garbage. This is the single most common reason a copied dork “stops working”.
4. The gotchas that actually break dorks
[!example] Read this section twice — it is most of the skill
Trap What happens Fix Lowercase orTreated as a stop word, dropped. Your disjunction became an AND. Always uppercase OR.allintitle:/allinurl:/allintext:They consume the rest of the query — every operator after them is ignored, including site:. Your scoped dork quietly went global.Stack the singular form instead: intitle:a intitle:b.Space after the colon site: example.comis parsed as a baresite:plus the keywordexample.com.Never put a space after an operator’s colon. Unquoted multi-word value intitle:index ofmeansintitle:indexAND the wordof.Quote it: intitle:"index of".*outside quotesIgnored entirely. Only use it inside a quoted phrase. site:is a suffix matchsite:example.comalso returnsnotexample.com-style matches on some engines and always includes every subdomain.Add -site:exclusions, or use Yandex’s stricterhost:.Very long stacked dorks Google historically truncated long queries, and still degrades them — the tail of a 15-operator dork may never be evaluated. Split into two or three narrower dorks. Personalised results Signed in, Google reorders and filters results for you. Two operators can look broken because your profile suppressed the hits. Search signed out, in a clean profile. Result count is a lie The “About N results” figure is an estimate and swings wildly. Page to the end. The real count is where results stop. Verbatim mode Google rewrites and expands queries by default. Append &tbs=li:1to the results URL, or use Tools → All results → Verbatim.
[!tip] Two switches worth memorising
&num=100on the results URL returns 100 per page instead of 10.&filter=0disables the “omitted similar results” collapse, which routinely hides the interesting duplicates on a large site.
5. Recipes by objective
Every dork below is written in the Google dialect with $DOMAIN, $ORG and $KEYWORD as placeholders. Section 6 covers translating them.
Exposed files and configs
The highest-yield category in the whole practice.
| Dork | Finds |
|---|---|
site:$DOMAIN ext:env OR ext:cfg OR ext:conf OR ext:ini | Application config. A served .env is plaintext credentials: database URI, mail password, cloud keys, app secret. |
site:$DOMAIN ext:bak OR ext:old OR ext:backup OR ext:swp | Editor and deploy leftovers. index.php.bak is served as text instead of executed — that is the source code. |
site:$DOMAIN ext:log OR ext:txt inurl:log | Logs: internal paths, usernames, session tokens, stack traces. |
site:$DOMAIN ext:yml OR ext:yaml OR ext:toml inurl:config | Compose files, CI definitions, appsettings, secrets baked into a values file. |
site:$DOMAIN ext:pem OR ext:key OR ext:ppk OR ext:p12 OR ext:pfx | Private keys and cert bundles. Any hit is a critical finding on its own. |
site:$DOMAIN inurl:.git OR inurl:.svn OR inurl:.hg | Exposed VCS metadata — a readable .git/ means the whole repo and its history. |
site:$DOMAIN inurl:wp-config OR inurl:configuration.php OR inurl:settings.py | Framework config by canonical filename. |
Login and admin panels
| Dork | Finds |
|---|---|
site:$DOMAIN inurl:admin OR inurl:administrator OR inurl:adminpanel | The obvious paths. Still hits constantly. |
site:$DOMAIN intitle:"login" OR intitle:"sign in" | Title-based, so it catches panels on paths you would never guess. |
site:$DOMAIN inurl:phpmyadmin OR inurl:adminer OR inurl:pma | Exposed database consoles, frequently on vendor defaults. |
site:$DOMAIN intitle:"Dashboard" (inurl:jenkins OR inurl:grafana OR inurl:kibana) | CI and observability — build secrets, internal hostnames, production telemetry. |
site:$DOMAIN inurl:/manager/html OR inurl:/jmx-console OR inurl:/axis2 | Java app-server managers. Tomcat manager with default creds is a WAR deploy from RCE. |
site:$DOMAIN inurl:owa OR inurl:/rdweb OR inurl:citrix OR inurl:vpn | Remote-access front doors — the surface spraying actually targets. |
Open directory listings
| Dork | Finds |
|---|---|
site:$DOMAIN intitle:"index of" | The canonical dork. Apache, nginx and IIS all emit a title starting this way. |
site:$DOMAIN intitle:"index of" (backup OR bak OR old OR archive) | Listings that name themselves as a dumping ground. |
site:$DOMAIN intitle:"index of" "parent directory" (.sql OR .zip OR .tar.gz) | Listings with a dump or archive sitting in them. |
site:$DOMAIN "Directory Listing For" -inurl:html | Tomcat and others whose listing wording differs from Apache’s. |
Cloud storage
| Dork | Finds |
|---|---|
site:s3.amazonaws.com "$ORG" | S3 buckets whose listing mentions the organisation. |
site:$DOMAIN inurl:s3.amazonaws.com | Pages on the target that link into S3 — the fastest way to learn the bucket naming convention. |
inurl:blob.core.windows.net "$ORG" | Azure Blob containers. |
inurl:storage.googleapis.com "$ORG" | Google Cloud Storage objects. |
site:$DOMAIN inurl:r2.dev OR inurl:digitaloceanspaces.com | Smaller providers — less scrutiny, misconfigured more often. |
"$ORG" (site:trello.com OR site:notion.site) | Public boards and docs. Trello leaks credentials and architecture diagrams at a remarkable rate. |
Credentials, keys and tokens
| Dork | Finds |
|---|---|
site:$DOMAIN intext:"BEGIN RSA PRIVATE KEY" | Key headers pasted into a wiki, a ticket, a README. |
site:$DOMAIN intext:"AKIA" | AWS access key IDs all begin AKIA — a distinctive literal that rarely false-positives. |
"$ORG" ("xoxb-" OR "ghp_" OR "sk_live_") | Slack, GitHub and Stripe token prefixes. Structurally unique, so a hit is almost never noise. |
site:$DOMAIN (ext:env OR ext:yml) intext:PASSWORD | Config files with a password assignment. |
site:pastebin.com OR site:justpaste.it "$DOMAIN" | Paste sites — where dumps, configs and credential lists get parked. |
[!danger] A live key is a finding, not a login Do not authenticate with anything you find. Record the URL, report it immediately so it can be rotated, and treat your own notes as sensitive material for the rest of the engagement. See Credential Hunting, Gitleaks and TruffleHog for the systematic version of this.
Documents and metadata
| Dork | Finds |
|---|---|
site:$DOMAIN ext:pdf OR ext:docx OR ext:xlsx OR ext:pptx | The corpus. Pull it, then run exiftool over the lot. |
site:$DOMAIN ext:pdf (confidential OR internal OR "not for distribution") | Documents labelled restricted that are nonetheless public. |
site:$DOMAIN ext:xlsx (employee OR salary OR roster) | Spreadsheets — the format people paste staff lists into. |
site:$DOMAIN ext:vsd OR ext:vsdx OR ext:drawio | Network and architecture diagrams. |
# the half of this that isn't the dork: metadata gives you usernames and internal paths
exiftool -Author -Creator -Producer -Company *.pdf | sort -u
exiftool -a -G1 -s report.docx | grep -Ei 'author|company|template|lastmodifiedby'
Error messages and stack traces
| Dork | Finds |
|---|---|
site:$DOMAIN intext:"You have an error in your SQL syntax" | The literal MySQL parser message — confirms injectable input. |
site:$DOMAIN intext:"Traceback (most recent call last)" | Python tracebacks. Django debug pages additionally dump settings and environment. |
site:$DOMAIN intitle:"Whoops, looks like something went wrong" | Laravel’s debug page, which shows environment variables verbatim. |
site:$DOMAIN intext:"Fatal error" OR intext:"Uncaught exception" | PHP and Java fatals — usually carry the absolute filesystem path. |
site:$DOMAIN intext:"Server Error in" intext:"Stack Trace" | ASP.NET yellow-screen-of-death with tracing left on. |
site:$DOMAIN intitle:"phpinfo()" | Full build config, loaded modules, absolute paths, sometimes environment secrets. |
Databases, backups and dumps
| Dork | Finds |
|---|---|
site:$DOMAIN ext:sql intext:"INSERT INTO" | SQL dumps confirmed by their own statement syntax, not just an extension. |
site:$DOMAIN ext:sql intext:"CREATE TABLE" intext:password | Dumps that include a credentials table. |
site:$DOMAIN (ext:zip OR ext:tar OR ext:gz) (backup OR dump OR export) | Archived backups in the webroot. |
site:$DOMAIN inurl:backup OR inurl:dump OR inurl:export | Path-based — catches the directory even when the file was not indexed. |
Injectable parameters
A target list for later, authorised testing. Nothing here is a finding by itself.
| Dork | Vulnerability class |
|---|---|
site:$DOMAIN inurl:id= OR inurl:pid= OR inurl:cat= | SQL injection, IDOR |
site:$DOMAIN inurl:file= OR inurl:page= OR inurl:path= | LFI, path traversal — see LFI |
site:$DOMAIN inurl:url= OR inurl:redirect= OR inurl:next= | Open redirect, the front half of many SSRF chains |
site:$DOMAIN inurl:cmd= OR inurl:exec= OR inurl:query= | Command injection, reflected XSS |
site:$DOMAIN inurl:debug=true OR inurl:admin=1 | Flags that flip the app into a verbose or privileged mode |
People, emails and usernames
| Dork | Finds |
|---|---|
site:linkedin.com/in "$ORG" | Staff profiles — names plus role, which is what derives the username scheme. |
site:$DOMAIN intext:"@$DOMAIN" | The org’s own pages leaking its address format (first.last@, flast@). |
"$ORG" (site:github.com OR site:gitlab.com) intext:"@$DOMAIN" | Developers using a work address in commits or profiles. |
"$ORG" (site:stackoverflow.com OR site:serverfault.com) | Engineers asking about their own stack, pasting real config with real hostnames. |
"$ORG" ("we use" OR "powered by") -site:$DOMAIN | Tech stack from job ads, case studies, conference talks. |
[!warning] Personal data is regulated independently of your scope Collect the minimum that supports the finding, store it with the engagement material, and delete it when the engagement closes.
Subdomains and forgotten hosts
| Dork | Finds |
|---|---|
site:*.$DOMAIN -site:www.$DOMAIN | The core subdomain dork. |
site:*.$DOMAIN (dev OR staging OR test OR uat OR qa) | Non-production — weaker credentials, debug on, real data. |
site:*.$DOMAIN (vpn OR remote OR portal OR intranet) | Access infrastructure and internal-facing hosts. |
"$DOMAIN" -site:$DOMAIN | Third-party references: partners, status pages, monitoring, archived copies. |
Dorking is the weakest of the subdomain sources — use it to catch what certificate transparency and DNS missed, not as the primary pass. See Amass and Stage 00 for the real enumeration.
Archived and removed pages
| Dork | Finds |
|---|---|
site:web.archive.org "$DOMAIN" | Wayback captures Google indexed. |
site:archive.today "$DOMAIN" | The other archive, which captures pages Wayback refuses. |
site:$DOMAIN before:2022-01-01 "$KEYWORD" | Older material still on the live site. |
# the archive's own API beats dorking it — every captured URL, deduplicated
curl -s "http://web.archive.org/cdx/search/cdx?url=$DOMAIN*&output=text&fl=original&collapse=urlkey" \
| sort -u > wayback-urls.txt
# pull the ones that look like config or secrets out of the pile
grep -Ei '\.(env|sql|bak|old|log|yml|ini|conf)($|\?)' wayback-urls.txt
6. Cross-engine translation
Google is the reference dialect, not the only one. Yandex and Bing routinely index hosts Google never crawled, so a subdomain dork is worth running through at least two engines.
| Intent | Bing | DuckDuckGo | Yandex | Brave | |
|---|---|---|---|---|---|
| Scope to host | site: | site: | site: | site: / host: / rhost: | site: |
| File type | filetype: ext: | filetype: ext: | filetype: | mime: | filetype: |
| In title | intitle: | intitle: | intitle: | title: | intitle: |
| In URL | inurl: | inurl: | inurl: | url: | inurl: |
| In body | intext: | inbody: | — | (default) | — |
| Exact phrase | "..." | "..." | "..." | "..." | "..." |
| Exclude | -term | -term | -term | -term | -term |
| Either/or | OR | OR | OR | OR | OR |
| Proximity | AROUND(n) | — | — | /+n | — |
| Date bound | before: after: | (UI filter) | (UI filter) | date: | (UI filter) |
Engine-native operators with no Google equivalent — worth the detour on their own:
| Engine | Operator | Why you would bother |
|---|---|---|
| Bing | ip:203.0.113.10 | Every site Bing indexed on that address — a free reverse-IP lookup, and often the rest of a shared estate behind one origin. |
| Bing | contains:sql | Pages that link to a .sql file rather than the file itself — catches the index page of a backup directory that was never indexed. |
| Bing | url:example.com/path | Tests whether one exact URL is in the index. |
| Yandex | rhost:com.example.* | Reversed-domain match across the whole tree — stricter and more predictable than Google’s suffix matching. |
| Yandex | mime:pdf | Yandex’s filetype:, keyed on recorded MIME type. |
| DuckDuckGo | !bangs (!gh, !so) | Not operators — redirects to another site’s own search. Handy, but the query leaves DDG. |
[!note] Brave and DuckDuckGo are the low-friction options Neither requires an account and neither personalises results, which makes them the right place to start from a clean browser. Their operator support is genuinely narrower than Google’s and less documented — when a dork returns nothing there, re-run it on Google before concluding the target is clean.
7. Other dialects worth knowing
GitHub code search
A different language entirely, and the single richest source of leaked secrets. Requires being signed in — use a throwaway account.
| Operator | Example | Notes |
|---|---|---|
org: | org:$ORG path:.env | Scope to an organisation’s public repos. |
repo: | repo:owner/name "password" | One repository. |
path: | path:.github/workflows | Replaced the old filename:. Globs: path:**/config/*.yml. |
language: | "$DOMAIN" language:yaml | Narrows a noisy content search. |
symbol: | symbol:connectDatabase | Definitions rather than mentions. |
org:$ORG path:.env
org:$ORG "BEGIN RSA PRIVATE KEY"
org:$ORG path:.github/workflows
"$DOMAIN" ("192.168." OR "10.0." OR ".local")
"$DOMAIN" "password" language:yaml
The last two are the interesting ones: they find other people’s repos that leak the target’s internal addressing and credentials — contractors, ex-employees, integration partners.
Shodan and Censys
These index service banners, not web pages, so the web operators do not apply at all. Covered properly in Shodan; the translation for a dorking reflex:
| You want | Shodan |
|---|---|
| Hosts presenting the org’s certificate | ssl.cert.subject.cn:$DOMAIN |
| Pages referencing the domain | http.html:"$DOMAIN" |
| A specific page title | http.title:"index of" |
| The org’s netblocks | org:"$ORG" or net:203.0.113.0/24 |
The origin-IP hunt behind a CDN is ssl.cert.subject.cn: — the origin still presents the real certificate.
8. The Google Hacking Database
The GHDB is Exploit-DB’s curated archive of dorks, started by Johnny Long, now thousands of entries across categories: files containing passwords, sensitive directories, vulnerable servers, error messages, footholds.
How to use it without wasting an afternoon:
- Filter by date. Most of the archive is a decade old and targets software nobody runs. Sort newest first.
- Read it as a pattern library, not a copy-paste list. The value of
intitle:"index of" "service.pwd"is not that exact string — it is that vendor-default filenames are the way in. Adapt the shape to the stack you actually found. - Scope everything. Almost every GHDB entry is unscoped and returns strangers’ infrastructure. Add
site:$DOMAINbefore you run it, every time.
9. OPSEC
[!danger] You are the one being logged Dorking sends nothing to the target — but it sends everything to the search engine, tied to your account, your IP and your browser fingerprint. The queries themselves describe your intent with unusual clarity.
| Rule | Why |
|---|---|
| Never dork signed in to a real account | The query history is retained, attributable, and personalises your results into uselessness. Use a clean profile or a private window. |
| Use a throwaway for GitHub code search | It is the one dialect that mandates an account. Do not attach your identity to a secrets hunt. |
| Expect CAPTCHAs, and slow down | A burst of operator-heavy queries from one IP trips Google’s automation detection. Once you are CAPTCHA’d, that IP is degraded for hours. |
| Do not click through to live secrets | Fetching the .env is a request to the target — logged, attributable, and outside “passive” recon. The snippet in the result usually contains enough to report. |
| Treat your notes as sensitive | A session log full of working dorks and hit URLs is a map of the target’s exposure. Store it with the engagement, encrypt it, delete it on close. |
| Report live keys immediately | Rotation is time-sensitive. Do not sit on a working credential until the report. |
10. Automation, rate limits and the ToS question
Scripted scraping of Google results violates its Terms of Service and fails in practice: the automation detection is good, the HTML changes, and the CAPTCHA is unsolvable at scale without paying someone to solve it. Every “google dork scanner” on GitHub has the same lifecycle — works for a week, then returns empty pages forever.
The options that actually work:
| Approach | Reality |
|---|---|
| Do it by hand | Slow, unblockable, and you read each result properly. For a single engagement this is genuinely the right answer. |
| Programmable Search Engine JSON API | Google’s sanctioned path. Free tier is ~100 queries/day, then paid. Supports most operators. Results are scoped to a custom engine you configure, which can be set to search the whole web. |
| A commercial SERP API | Pays someone else to absorb the blocking. Fine for volume; check that sending client data to a third party is acceptable under your engagement’s confidentiality terms. |
| Shodan / Censys APIs | Purpose-built, properly documented, generous limits. If the thing you want is a service rather than a document, stop dorking and query these. |
| Bing Search APIs | Microsoft has been winding these down — verify current availability before building anything on them. |
A tool that builds dorks and hands them to your browser has none of these problems, because you are still the one searching. That is what dorkforge does.
11. Blue team — defending your own estate
Dorking is trivially turned around: run it against yourself, on a schedule.
| Control | What it actually does |
|---|---|
X-Robots-Tag: noindex header, or <meta name="robots" content="noindex"> | The removal mechanism. Note the trap: a path blocked in robots.txt cannot be crawled, so the crawler never sees the noindex — the page can stay indexed forever. Allow the crawl, serve the noindex, then block it once it has dropped out. |
| Search Console removal tool | Fast takedown for a site you own (~6 months), which buys time while you fix the underlying exposure. It is a suppression, not a fix. |
robots.txt | A crawl hint, and a published list of your sensitive paths. Never treat it as access control; assume attackers read it first. |
| Disable autoindex | Options -Indexes (Apache), autoindex off (nginx). Kills the entire intitle:"index of" class. |
| Block dotfiles and backup extensions at the edge | Return 404 for \.(env|git|bak|old|sql|swp)$ before the request reaches the app. |
| Turn off debug in production | APP_DEBUG=false, customErrors="On", DEBUG = False. Removes the entire error-message class in one change. |
| Bucket ACLs and public-access blocks | Cloud storage exposure is a configuration problem; no search-engine control fixes it. |
| Continuous secret scanning | Gitleaks/TruffleHog in CI plus GitHub push protection catches the commit before it is ever indexed. |
| Dork yourself on a schedule | The blue-team use of this whole page. Automate the handful of dorks that matter for your estate and alert on new hits. |
# a minimal self-audit, run monthly against your own domain
for d in 'ext:env' 'ext:sql' 'ext:bak' 'intitle:"index of"' 'intext:"BEGIN RSA PRIVATE KEY"'; do
printf '%s\n' "site:$DOMAIN $d"
done
# feed them to the Programmable Search JSON API and diff the hit list against last month's
12. Practising safely
- Your own domains. The only fully unambiguous target, and the one where findings are actionable.
google-gruyere.appspot.com,testphp.vulnweb.com,demo.testfire.net— deliberately vulnerable hosts published for training. Verify the terms on each before touching it.- The GHDB, read but not run. Study the shapes; run them scoped to yourself.
- CTF and lab platforms with an OSINT category, where the scope is explicit.
[!warning] Unscoped dorks return strangers’ infrastructure A dork like
intitle:"webcamXP"returns hardware belonging to people who never consented to anything. Looking at the result list is one thing; connecting to a device is unauthorised access in essentially every jurisdiction. Scope withsite:or do not run it.
13. dorkforge — the companion script
dorkforge.py (SHA-256) is a single-file interactive workbench for everything on this page: it asks what you are hunting for, builds the dork, explains every operator it used, translates it for the engine you picked, and hands it to your clipboard, your browser, or an engagement log.
It ships the full library from section 5 — 14 objectives, 81 recipes, 32 operators — and it sends no traffic to any target. The searching still happens in your browser, under your account, from your IP, which is why it opens with the authorisation gate and records a scope reference in every session log.
Run it
It uses PEP 723 inline metadata, so uv resolves rich and questionary into a throwaway environment on first run. Nothing to install, nothing to clean up.
# download + verify
curl -sO https://cheatsheet.daemon-sec.xyz/downloads/enumeration/dorkforge.py
curl -sO https://cheatsheet.daemon-sec.xyz/downloads/enumeration/dorkforge.py.sha256
shasum -a 256 -c dorkforge.py.sha256 # expect: dorkforge.py: OK
# run it
uv run dorkforge.py
Expected SHA-256:
3173df88ab3102ebc4999985fcb881298f3f51374170592e5ac95d0674210193
Or make it executable and let the shebang do the work — #!/usr/bin/env -S uv run --script:
chmod +x dorkforge.py
./dorkforge.py
# keep it on PATH like the rest of your toolkit
install -m 755 dorkforge.py ~/.local/bin/dorkforge
[!note] Don’t have uv?
curl -LsSf https://astral.sh/uv/install.sh | sh(orbrew install uv). Failing that,pip install rich questionaryand run it with plainpython3— the script degrades to that path and tells you so.
The flow
▪ DÆMON//SEC
dorkforge v1.0.0 search-operator workbench
────────────────────────────────────────────────────────────
? What are you hunting for Exposed files & configs
? Target domain: example.com
? Which engine? Google
? Which dork? site:example.com ext:env OR ext:cfg OR ext:conf OR ext:ini
┌─ Google ─────────────────────────────────────────────────┐
│ │
│ site:example.com ext:env OR ext:cfg OR ext:conf OR ext:ini│
│ │
│ Application config. A served .env is credentials in │
│ plaintext - database URI, mail password, cloud keys. │
│ │
└────────────────────────────────────────────────────────────┘
OPERATOR WHAT IT DOES GOOGLE
──────────────────────────────────────────────────────────────
site: Only return pages whose host matches. ✓
ext: Synonym for filetype: on Google and Bing. ✓
OR Match either side. Must be uppercase. ✓
? Now what? Copy to clipboard / Open in browser / Save to log
Pick a non-Google engine and it rewrites the dork and tells you what changed:
$ uv run dorkforge.py --objective listing --domain example.com --engine yandex
site:example.com title:"index of"
dialect notes
▪ intitle: rewritten to title: for Yandex
Usage
| Command | Does |
|---|---|
uv run dorkforge.py | Interactive. The main path. |
dorkforge --session engagement.md | Append every dork you build to a markdown log, with the URL, the reasoning and the translation notes. |
dorkforge --objective files --domain example.com | Non-interactive: print every recipe for one objective. |
dorkforge --objective code --org acme --engine github | Same, in GitHub’s dialect. |
dorkforge --list | The whole library — 14 objectives, 81 recipes — to a pager or a file. |
dorkforge --operators | The operator reference table, with live / unreliable / retired status. |
dorkforge --explain site: | The long form on any one operator, plus which engines support it. |
dorkforge --doctor | Check clipboard helper, browser, colour support and state directory. |
dorkforge --ascii | ASCII markers instead of Nerd Font glyphs. |
dorkforge --reset-ack | Forget the authorisation acknowledgement and ask again. |
Flags: --domain --org --keyword --ext pre-fill the scope prompts. --engine picks the dialect (google bing ddg yandex brave github shodan). --no-color for piping.
The session log
--session writes engagement-ready markdown as you work — the dork, why it was built, the live URL, and anything that did not survive translation:
# dorkforge session
- **Started:** 2026-09-26 14:21 BST
- **Authorised scope:** ACME-2026-114
- **Tool:** dorkforge 1.0.0
## 1. Google
Application config. A served .env is credentials in plaintext.
```text
site:example.com ext:env OR ext:cfg OR ext:conf OR ext:ini
```
<https://www.google.com/search?q=site%3Aexample.com+ext%3Aenv...>
Paste it straight into the recon section of a report — see Documentation and Reporting.
[!tip] The authorisation gate is once per machine The acknowledgement is stored in
$XDG_STATE_HOME/dorkforge/ack.json(~/.local/state/dorkforge/by default) along with the scope reference you gave, which is then stamped into every session log.--reset-ackclears it.