<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: cl0q</title>
    <description>The latest articles on DEV Community by cl0q (@cl0qsearch).</description>
    <link>https://dev.to/cl0qsearch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4146017%2Fb27a7e64-50b9-456c-93b6-13449754e96a.png</url>
      <title>DEV Community: cl0q</title>
      <link>https://dev.to/cl0qsearch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cl0qsearch"/>
    <language>en</language>
    <item>
      <title>We Thought We Had No PHP. We Were Wrong.</title>
      <dc:creator>cl0q</dc:creator>
      <pubDate>Thu, 22 Oct 2026 01:36:39 +0000</pubDate>
      <link>https://dev.to/cl0qsearch/we-thought-we-had-no-php-we-were-wrong-2ejo</link>
      <guid>https://dev.to/cl0qsearch/we-thought-we-had-no-php-we-were-wrong-2ejo</guid>
      <description>&lt;h1&gt;
  
  
  We Thought We Had No PHP. We Were Wrong.
&lt;/h1&gt;

&lt;p&gt;The first thing we did when the php2shell advisory landed was make the mistake almost everyone makes.&lt;/p&gt;

&lt;p&gt;We checked the websites.&lt;/p&gt;

&lt;p&gt;That sounds responsible until you remember what php2shell actually is. CVE-2026-109618 and CVE-2026-109619 are critical unauthenticated remote code execution flaws in PHP itself. The vulnerable surface is not one plug-in, one theme, or one badly written upload form. It is the PHP handler sitting between the web server and the code. Apache, nginx, LiteSpeed, FPM, mod_php: if PHP is in the request path and it is not patched, the details of your application may not save you.&lt;/p&gt;

&lt;p&gt;So the better question was not, "Do we run a PHP site?"&lt;/p&gt;

&lt;p&gt;It was, "Where can PHP execute anywhere on these machines?"&lt;/p&gt;

&lt;p&gt;That is where it got uncomfortable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The box we almost waved through
&lt;/h2&gt;

&lt;p&gt;We run cl0q, a search engine and index of the public web. Our own stack is mostly Go, Postgres, static files, and the usual operational scar tissue. From the outside, our production web box did not look like a PHP target. Probing the public site did not show PHP fingerprints. It would have been easy to write "not affected" in the team channel and move on.&lt;/p&gt;

&lt;p&gt;Then the on-box check told a different story.&lt;/p&gt;

&lt;p&gt;PHP-FPM was installed and active, wired behind Apache for cl0q and other virtual hosts. Nothing about the public pages screamed PHP, but the handler was there, alive, and able to process requests routed to it. We patched the PHP 8.3 packages to the Ubuntu security backport and restarted FPM. Then we checked the sites again.&lt;/p&gt;

&lt;p&gt;That should have been the end of it. It was not.&lt;/p&gt;

&lt;p&gt;Our second machine, the one that hosts our database, Gitea, and team chat, was worse. Apache had mod_php loaded. Not installed in a corner. Loaded. Of all the variants in the advisory, mod_php is the one you least want to discover by accident, because PHP runs inside the web server process itself.&lt;/p&gt;

&lt;p&gt;We upgraded the PHP 8.1 packages to the jammy-security build and restarted Apache on the patched module.&lt;/p&gt;

&lt;p&gt;Two machines. Two different PHP exposure paths. Neither one was obvious from the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But the site does not use PHP"
&lt;/h2&gt;

&lt;p&gt;This is the sentence that gets people hurt during a disclosure like this.&lt;/p&gt;

&lt;p&gt;A modern server is not a single app with a tidy label. It is a pile of decisions made over months: a package installed for one test, a handler left enabled after a migration, a default virtual host nobody remembers, a legacy tool that still gets one request a week. Attackers do not care which parts were intentional. They care which parts execute.&lt;/p&gt;

&lt;p&gt;That is also why configuration tricks are such a poor comfort blanket here. The guidance around php2shell has been blunt: do not talk yourself into safety with a clever rule or a partial workaround. The fix is the patched PHP release. Upstream fixed versions are PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35, with distribution backports doing the same work under different version strings.&lt;/p&gt;

&lt;p&gt;Patch the interpreter. Restart the service. Then prove the public site still works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the wider web looks like from here
&lt;/h2&gt;

&lt;p&gt;cl0q currently knows about 46.8 million domains and 33.7 million indexed pages. Numbers that large stop feeling real until a day like this turns them into a checklist. Millions of sites advertise Apache, nginx, or LiteSpeed in their server banners. A banner does not prove PHP is present, and it certainly does not prove a host is vulnerable. That distinction matters.&lt;/p&gt;

&lt;p&gt;But a banner does tell you where to look first.&lt;/p&gt;

&lt;p&gt;That is the practical use of an index like ours during a fast-moving disclosure. You can search and browse the public web by the technology a site exposes, follow a domain into its dossier, and see the shape of its stack before you start asking harder questions. Start with &lt;a href="https://cl0q.com/explore" rel="noopener noreferrer"&gt;cl0q Explore&lt;/a&gt; if you want the wide view. Or pick a known stack and inspect it, the way this &lt;a href="https://cl0q.com/site/litespeedtech.com" rel="noopener noreferrer"&gt;LiteSpeed dossier&lt;/a&gt; shows what we know about one public site.&lt;/p&gt;

&lt;p&gt;None of that replaces checking your own machines. It does stop you from guessing blind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checklist we are using now
&lt;/h2&gt;

&lt;p&gt;If you run anything with a web server, steal this order of operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inventory the machine, not the brand of the website. List web servers, PHP packages, FPM services, Apache modules, containers, and old virtual hosts.&lt;/li&gt;
&lt;li&gt;Ask where PHP can execute. A package that is merely installed is different from a handler that is loaded or proxied, but you need evidence for either answer.&lt;/li&gt;
&lt;li&gt;Patch PHP from your distribution or upstream. Do not settle for a workaround when a fixed build exists.&lt;/li&gt;
&lt;li&gt;Restart the actual service that loaded the old code. FPM, Apache, and containers do not magically pick up a patched library by wishing.&lt;/li&gt;
&lt;li&gt;Retest from outside and inside. Outside shows what the internet sees. Inside catches the quiet handler that never made it into the brochure.&lt;/li&gt;
&lt;li&gt;Write down what you found, even if the answer is boring. Future you will not remember which box had mod_php loaded at 2 a.m.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The uncomfortable takeaway
&lt;/h2&gt;

&lt;p&gt;The scariest part of php2shell for us was not the severity, although unauthenticated RCE is about as bad as a Tuesday gets. It was the gap between the system we thought we were running and the system that was actually switched on.&lt;/p&gt;

&lt;p&gt;That gap is normal. It is also measurable.&lt;/p&gt;

&lt;p&gt;We built cl0q to make the public web easier to inspect: what a domain runs, where it lives, what changed, and how the pieces connect. Days like this are why that matters. Check your own stack first, patch it, and then come look at the rest of the internet with us.&lt;/p&gt;

&lt;p&gt;Start with &lt;a href="https://cl0q.com/explore" rel="noopener noreferrer"&gt;Explore&lt;/a&gt;. If you need the data programmatically, the &lt;a href="https://cl0q.com/api/billing/pricing" rel="noopener noreferrer"&gt;cl0q API pricing page&lt;/a&gt; has the live tiers, including the free starting point and paid plans for higher limits.&lt;/p&gt;

&lt;p&gt;And if your inventory starts with "we do not run PHP," go look anyway.&lt;/p&gt;

&lt;p&gt;We said that too.&lt;/p&gt;

</description>
      <category>security</category>
      <category>php</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>We Open Sourced Our Web Crawler. Here's How to Run a Node.</title>
      <dc:creator>cl0q</dc:creator>
      <pubDate>Tue, 06 Oct 2026 01:31:43 +0000</pubDate>
      <link>https://dev.to/cl0qsearch/we-open-sourced-our-web-crawler-heres-how-to-run-a-node-145</link>
      <guid>https://dev.to/cl0qsearch/we-open-sourced-our-web-crawler-heres-how-to-run-a-node-145</guid>
      <description>&lt;p&gt;The crawler behind cl0q.com is now public. Anyone can read the code, run a node, and help index the open web.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeberg.org/cl0qsearch/crawler-node" rel="noopener noreferrer"&gt;https://codeberg.org/cl0qsearch/crawler-node&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open source it?
&lt;/h2&gt;

&lt;p&gt;Search shouldn't be a black box. The big engines don't tell you what they crawl, how they rank, or what they do with the data. We think that's wrong.&lt;/p&gt;

&lt;p&gt;cl0q is an independent search engine with its own crawler and index. We've mapped 38.5M domains so far, working toward 100M. Now the crawler itself is open for anyone to inspect, run, or improve.&lt;/p&gt;

&lt;p&gt;If you've ever wondered "what does a real web crawler look like under the hood," this is your answer. Every line is readable. No magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;The node software discovers websites, fetches their homepages politely, and sends what it finds to cl0q's index. That's it. It doesn't scrape personal data, doesn't follow you around, doesn't build profiles.&lt;/p&gt;

&lt;p&gt;Five services, one Postgres database, zero public ports. Everything runs locally on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's a good bot (by design, not by promise)
&lt;/h2&gt;

&lt;p&gt;Most crawlers say they respect robots.txt. Ours can't not respect it. The politeness rules are hardcoded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One honest User-Agent that names your node. It never pretends to be a browser.&lt;/li&gt;
&lt;li&gt;Public internet only. It physically cannot connect to private networks, localhost, or cloud metadata endpoints.&lt;/li&gt;
&lt;li&gt;robots.txt is checked first, every time. Crawl-delay is obeyed.&lt;/li&gt;
&lt;li&gt;At least 1 second between requests to any server. No hammering.&lt;/li&gt;
&lt;li&gt;Only fetches homepages, at most once every 120 days per site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't settings you can turn off. They're in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run your own node
&lt;/h2&gt;

&lt;p&gt;You need Docker and a machine that's online. That's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://codeberg.org/cl0qsearch/crawler-node.git
&lt;span class="nb"&gt;cd &lt;/span&gt;crawler-node
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
docker compose build
docker compose run &lt;span class="nt"&gt;--rm&lt;/span&gt; cl0q-node enroll &lt;span class="nt"&gt;--contact&lt;/span&gt; you@example.com
docker compose run &lt;span class="nt"&gt;--rm&lt;/span&gt; preflight
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The enroll step registers your node with cl0q and gives you a token. The preflight check makes sure everything works before you start crawling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is v0.1.0. Coming up: more repos open sourced, a GitHub mirror, and performance work.&lt;/p&gt;

&lt;p&gt;The code is MIT licensed. Fork it, break it, improve it, send PRs.&lt;/p&gt;

&lt;p&gt;Run a node. Help index the open web.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>go</category>
    </item>
    <item>
      <title>I Pointed My Domain Search Engine at Cybercrime — Here's What It Found</title>
      <dc:creator>cl0q</dc:creator>
      <pubDate>Wed, 30 Sep 2026 02:55:51 +0000</pubDate>
      <link>https://dev.to/cl0qsearch/i-pointed-my-domain-search-engine-at-cybercrime-heres-what-it-found-1ce7</link>
      <guid>https://dev.to/cl0qsearch/i-pointed-my-domain-search-engine-at-cybercrime-heres-what-it-found-1ce7</guid>
      <description>&lt;h1&gt;
  
  
  I Pointed My Domain Search Engine at Cybercrime — Here's What It Found
&lt;/h1&gt;

&lt;p&gt;I build cl0q, a domain search engine (38.5M domains scanned, free API, no tracking). Last night I got curious: what happens when you run threat-intel queries through a general domain index instead of a specialized feed?&lt;/p&gt;

&lt;p&gt;Turns out: quite a lot. Here's what three searches returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. "crypto drainer" → 13 results, including live drainer kits
&lt;/h2&gt;

&lt;p&gt;Top hits included &lt;strong&gt;infernodrainer.xyz&lt;/strong&gt; ("Inferno Drainer — best crypto drainer since 2022," advertising "0-day exploits, 120+ wallet support"), &lt;strong&gt;exogator.com&lt;/strong&gt; ("Liquidate all cryptocurrencies and NFTs from any wallet"), &lt;strong&gt;purpledrainer.club&lt;/strong&gt;, and &lt;strong&gt;cryptodrainerscript.net&lt;/strong&gt; selling "multichain crypto drainer scripts."&lt;/p&gt;

&lt;p&gt;Each result came with resolved IPs and MX records — immediate pivot points. exogator.com sits on 5.182.209.88; infernodrainer.xyz on 216.198.79.65. That's infrastructure you can feed straight into a blocklist.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. "stealer log" → a notorious carding market, indexed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;russianmarket.work&lt;/strong&gt; showed up: "The most trusted underground marketplace. Buy CVV, Stealer Logs, RDP, dumps..." — sitting in a general web index, with its IPs (172.67.149.100) and metadata attached. Alongside it: breach-intel platforms, stealer-log search services, and a Turkish hacking forum (spyhackerz.org) dealing in RATs and fresh leaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. "phishing kit" → an active scampage shop
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;lurez.online&lt;/strong&gt; — "Spamming Tools, Office 365 Scampages, Bybit &amp;amp; Binance Scampages For Sale," complete with SMTP servers, cracking utilities, and a "complete spamming course." Plus &lt;strong&gt;spams.tools&lt;/strong&gt; ("Spam Tools | Scampages | Checkers | Letters | Email Senders | SMTPs | cPanels") with its MX records exposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Threat intel usually means expensive feeds and APIs. But a huge amount of attacker infrastructure lives on the clear web, on cheap domains, behind Cloudflare — indexed like anything else. A domain-level search engine with DNS enrichment (IPs, MX, CNAMEs) turns a hunch into pivotable infrastructure in one query.&lt;/p&gt;

&lt;p&gt;The searches are free, the API is free (30 req/min, 1,000/day), and nothing is logged. Try it: &lt;a href="https://cl0q.com" rel="noopener noreferrer"&gt;cl0q.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All domains above were live in the index at time of writing. If you're a defender, the IPs and MX records are yours to use.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI assistance was used in drafting this article.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>38.5 million domains on a 2 GB droplet: the honest story of building an open search engine</title>
      <dc:creator>cl0q</dc:creator>
      <pubDate>Sun, 27 Sep 2026 21:25:38 +0000</pubDate>
      <link>https://dev.to/cl0qsearch/385-million-domains-on-a-2-gb-droplet-the-honest-story-of-building-an-open-search-engine-4op4</link>
      <guid>https://dev.to/cl0qsearch/385-million-domains-on-a-2-gb-droplet-the-honest-story-of-building-an-open-search-engine-4op4</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I used AI assistance to help draft this post. The story, the mistakes, and every number below are mine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In 2025, I started crawling the web.&lt;/p&gt;

&lt;p&gt;Not metaphorically. I pointed a crawler at the open internet from a 2 GB VPS and decided to build a search engine — a free, open-source one that doesn't log your searches, doesn't need an account, and that anyone can self-host. The first crawl records date to April 2025. Then things went quiet for a while. Then this June, cl0q took off: 8.5 million domains in a single month.&lt;/p&gt;

&lt;p&gt;Today, cl0q knows 38.5 million domains and has indexed 24.8 million pages. The goal is 100 million.&lt;/p&gt;

&lt;p&gt;This is the honest version of how that went.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first million nearly killed the project
&lt;/h2&gt;

&lt;p&gt;The naive approach to crawling is: start with a list of sites, follow every link, repeat. What nobody tells you is that the web has traps. Point a crawler at the open web and it finds Blogspot — about a million subdomains hanging off a single domain — and happily spends a week indexing them while the rest of the internet waits.&lt;/p&gt;

&lt;p&gt;Getting to the first million was the hardest part, because I didn't know the right crawl path. Crawl too narrow and you re-walk the same neighborhood forever. Crawl too wide and you fall down a subdomain hole and your index fills up with a million pages from the same blog host.&lt;/p&gt;

&lt;p&gt;The fix was treating the known web as a rotating frontier instead of a finished list: keep re-sampling domains you already know and mine their homepages for fresh outbound links. And Certificate Transparency logs turned out to be a goldmine — at peak, they were surfacing around 1,700 new domains a minute. Discovery never ends; it just keeps moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything broke, mostly because of disk
&lt;/h2&gt;

&lt;p&gt;For most of this project, cl0q ran on that 2 GB VPS. A web crawl is, at its core, a fight against disk space. Every page is a row, every favicon is bytes, every DNS record is overhead, and the crawl never stops growing.&lt;/p&gt;

&lt;p&gt;Lots broke. Things crashed, crawls stalled, I ran out of room at the worst moments. These days the storage lives on a remote host connected over Tailscale, which helped enormously — and I'm still fighting storage issues today. If there's one thing I'd tell anyone starting a crawl project: budget ten times the disk you think you need, then double it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The database has one core, and everything fights over it
&lt;/h2&gt;

&lt;p&gt;Here's something the docs won't tell you: search and the crawler share a single database, a single core, and the same table. When a burst of background jobs stampedes the database, search times out. When the crawler picks its next targets, it eats a big share of DB time doing it.&lt;/p&gt;

&lt;p&gt;There's no elegant fix yet — just triage, scheduling, and the occasional 2 a.m. realization that the thing slowing down search is my own crawler. The one part that never touches the database: the stats and drill-down pages, which are served from precomputed files. If the site feels fast while the crawler is hammering away, that's why.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually worked
&lt;/h2&gt;

&lt;p&gt;A few decisions paid off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The pipeline is four small stages&lt;/strong&gt; — discovery, page crawl, enrichment, serving — each incremental and restartable. Nothing depends on a full rebuild. (That's the simplified version. The real version involves the single-core database above.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refusing to index garbage.&lt;/strong&gt; When a site serves an anti-bot challenge page, lazy crawlers index the text "Checking your browser…" as if it were content. cl0q detects interstitials and throws them out. A search engine is only as good as what it refuses to index.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Favicons turned out to be a superpower.&lt;/strong&gt; Every icon gets hashed with SHA-256: 16.3 million sites in the index have a favicon, collapsing down to about 7 million distinct icons. Sites sharing an icon are usually related — same operator, same framework, same phishing kit. What started as a storage deduplication trick became one of the most useful OSINT pivots in the index.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy as architecture, not policy.&lt;/strong&gt; Signed out, cl0q sets no cookies and stores nothing about your searches — there's no per-request log to leak, subpoena, or sell. Accounts are optional and passkey-based, and search history exists only if you turn it on. The code is open source, though I'll be honest: the public mirror is a couple months behind right now, and refreshing it is on my list.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where things stand
&lt;/h2&gt;

&lt;p&gt;The numbers, measured from the actual database rather than the dashboard: cl0q knows 38.5 million domains — 97% have been attempted, 92% resolve in DNS. It's indexed 24.8 million pages, 24.4 million of them live, across 1,027 TLDs. About 250,000 to 300,000 pages get crawled every day, and re-crawls start October 9 so pages stay fresh instead of going stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  The road to 100 million
&lt;/h2&gt;

&lt;p&gt;The plan is simple: hit 100 million domains, then open up the API properly. There's a free beta API today and paid tiers are coming — and once the project makes money, the next frontier is depth. Right now cl0q fetches homepages; with real revenue behind it, the crawl goes deeper into sites instead of just wider across them.&lt;/p&gt;

&lt;p&gt;If you want to help, you can run a crawler and contribute pages — that's by invitation today, so get in touch — or just try a search at cl0q.com.&lt;/p&gt;

&lt;p&gt;A year and a half of crawling, 38.5 million domains, one very tired VPS. On to 100.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
