• XSS.stack #1 – первый литературный журнал от юзеров форума

Поиск сайтов за CloudFlare на ASN14061 - наталкиваюсь на какие-то странные false positives

zdestuta

(L1) cache
Пользователь
Регистрация
04.06.2024
Сообщения
748
Реакции
373
В ходе поиска определённых сайтов за CloudFlare на ASN14061 (DigitalOcean) с помощью httpx , на некоторых IP стал натыкаться на какие-то странные nginx которые server: nginx выдают, но при этом также cf-ray и подобные специфичные для CloudFlare заголовки присутствуют, будто nginx проксирует на cloudflare сайт, причём на любой который в host: указываю - что это такое? кто-то сталкивался?

Вот примеры такого безобразия:
curl -k -v https://161.35.121.249/simple/ -H "Host: showmyip.com"
curl -k -v https://161.35.121.249/ -H "Host: www.google.com"

А вот другой пример - IP отдаёт любой сайт который я указываю в host:
curl -v http://138.197.20.105/simple -H "Host: showmyip.com"
curl -v http://138.197.20.105/ -H "Host: google.com"

Разумеется тут я примеры с host: общеизвестными привёл, а не с теми что ищу, но вот странные IP привожу тут именно реальные.
Мешает сканированию, дофига false positives.
Что это за хрень? Это проксики такие?

c0d3x , может быть ты знаешь? подскажи плиз что это может быть за хрень такая странная?

Вот скрипт сканирования, IP на входе разумеется пре-фильтрованы masscan на предмет наличия 80 или 443 портов, чтобы httpx не тормозил:
Код:
#!/bin/bash

IN_FILE="$HOME/AS14061_ips_with_80_443.txt"
VHOSTS_FILE="$HOME/1/vhosts_to_find.txt"
START_FROM="myfirstvhostinlist.com"
STARTED=false
LINEN=0

while read VHOST; do
  LINEN=$((LINEN+1))
  LINES=$(printf "%03d" "$LINEN")
  if [[ -n "$START_FROM" && "$STARTED" = false ]]; then
    if [[ "$VHOST" == "$START_FROM" ]]; then
      STARTED=true
      echo "Start: $VHOST Line: $LINES"
    else
      echo "Skip: $VHOST Line: $LINES"
      continue
    fi
  fi
  if [[ "$STARTED" = true ]]; then
    echo "Processing: $VHOST Line: $LINES"
    httpx2 \
        -l "$IN_FILE" \
        -H "Host: $VHOST" \
        -t 3000 -rl 30000 \
        -rstr 100000 \
        -timeout 5 -retries 1 \
        -ip -sc -title -server -location \
        -stats -si 10 \
        -silent -nc \
        -path "/путь/на/сайте/для/детекта/определённого/типа/сайтов/" -mc 200 -ms "Заголовок сайта - они одинаковы для типа сайтов которые я ищу" \
        1>>"$HOME/2/$LINES-$VHOST.txt" \
        </dev/null
  fi
done < $VHOSTS_FILE
Скрипт тупо на каждый vhost бежит по списку IP и на каждом пытается этот vhost найти, мэтча ответ по наличию определённого пути и заголовка.
Тестовые сайты из моего тестового набора (загонял небольшой range IP и vhost'ы для заранее известных сайтов этого типа за CloudFlare, те что уже знаю где) - детектятся как здрасьте.
 
Просто прокси, видимо с конфигом затупили.
вот думаю как бы их из false positives исключить тогда, по какому признаку. они ведь как оригинальные сайты по path и по title пробиваются.
 
вот думаю как бы их из false positives исключить тогда, по какому признаку. они ведь как оригинальные сайты по path и по title пробиваются.
Как вариант 2 запрос делать и смотреть тело.
Например host - api.telegram.org запрос ip/getMe если ответ
Код:
{"ok":false,"error_code":404,"description":"Not Found"}
false
 
c0d3x , может быть ты знаешь? подскажи плиз что это может быть за хрень такая странная?
Часто при поиске реалок такое бывает, это криво настроенные nginx. Каждый мой скан через httpx когда я ищу реалку имеет обязательно такой ключ: -fdc 'contains(webserver, "cloudflare") || contains(raw_header, "Cf-Ray:")', то есть я просто скипаю такие IP, на которых отдается хидер Cf-Ray или имя вэбсервера cloudflare.
 
Часто при поиске реалок такое бывает, это криво настроенные nginx. Каждый мой скан через httpx когда я ищу реалку имеет обязательно такой ключ: -fdc 'contains(webserver, "cloudflare") || contains(raw_header, "Cf-Ray:")', то есть я просто скипаю такие IP, на которых отдается хидер Cf-Ray или имя вэбсервера cloudflare.
о спасибо! Дон, Вы просто неподражаемы!
DSL же есть не хуже Nuclei в httpx, как я про него забыл то!...
-fdc, -filter-condition string filter response with dsl expression condition
а мне тут чего только каких извращений ухищрений то не предлагал народ по доброте душевной... :) ну возможно их советы бы и сработали, но свелось бы на нет всё преимущество скорости httpx.

Ещё вопрос возник:
Код:
-vhost                     probe and display server supporting VHOST
-vhost-input                     get a list of vhosts as input
а как пользоваться вот этим на практике совместно с -l, -list string input file containing list of hosts to process ?
у меня vhosts.txt это домены , а input.txt это IPшники после масскана
и вот как я только ни пытался как ни извращался , так и пришлось уродливый скрипт (см. выше) писать и через -H щупать виртуальные хосты.
 
те ip, которые ты упомянул, ведут себя точно как открытые reverse proxy или умные honeypot. это сервера, которые принимают любой host header, что ты им дашь, и пытаются фетчить контент откуда-то еще или имитировать его. почему? потому что digitalocean (asn14061) полон временных vm и контейнеров, которые люди запускают для тестов, прокси или даже для ловушек безопасности. например, кто-то мог настроить nginx с конфигом типа proxy_pass на upstream cloudflare, чтобы форвардить любой запрос. из-за этого ты видишь cf-ray и заголовки cf, но при этом server: nginx – ведь nginx просто проксирует, а не прям cloudflare... эти false positive можно отфильтровать, проверив sni (server name indication) в tls handshake. скажем, с помощью openssl s_client -connect ip:443 -servername vhost.com посмотри, сертификат выдан для этого vhost реальный или wildcard/generic. если cert от cloudflare, но с mismatch, скорее всего прокси. или в httpx добавь опцию -tls-probe и проверь, проба удалась или нет...
для твоего скрипта добавь слой фильтра: после httpx обработай вывод с grep или awk и чекни заголовки вроде cf-cache-status: hit (если miss, то может быть прокси, который только что фетчил). или понизь rate limit, чтоб honeypot меньше провоцировать – некоторые из них детектят по поведению сканера. если хочешь глубже копнуть, используй api censys.io (если есть доступ) для запросов на ip и посмотри, какие реальные сервисы там; например, query: services.tls.certificates.leaf_data.names включает твой vhost...


попробуй это, ложных срабатываний станет меньше... ну, в общем, как-то так.
 
pardon my stupidity, is this a method of you discovering hosts, that are using cloudflare or are discoverable behind cloudflare.
discoverable behind cloudflare
 
Пожалуйста, обратите внимание, что пользователь заблокирован
В ходе поиска определённых сайтов за CloudFlare на ASN14061 (DigitalOcean) с помощью httpx , на некоторых IP стал натыкаться на какие-то странные nginx которые server: nginx выдают, но при этом также cf-ray и подобные специфичные для CloudFlare заголовки присутствуют, будто nginx проксирует на cloudflare сайт, причём на любой который в host: указываю - что это такое? кто-то сталкивался?

Вот примеры такого безобразия:
curl -k -v https://161.35.121.249/simple/ -H "Host: showmyip.com"
curl -k -v https://161.35.121.249/ -H "Host: www.google.com"

А вот другой пример - IP отдаёт любой сайт который я указываю в host:
curl -v http://138.197.20.105/simple -H "Host: showmyip.com"
curl -v http://138.197.20.105/ -H "Host: google.com"

Разумеется тут я примеры с host: общеизвестными привёл, а не с теми что ищу, но вот странные IP привожу тут именно реальные.
Мешает сканированию, дофига false positives.
Что это за хрень? Это проксики такие?

c0d3x , может быть ты знаешь? подскажи плиз что это может быть за хрень такая странная?

Вот скрипт сканирования, IP на входе разумеется пре-фильтрованы masscan на предмет наличия 80 или 443 портов, чтобы httpx не тормозил:
Код:
#!/bin/bash

IN_FILE="$HOME/AS14061_ips_with_80_443.txt"
VHOSTS_FILE="$HOME/1/vhosts_to_find.txt"
START_FROM="myfirstvhostinlist.com"
STARTED=false
LINEN=0

while read VHOST; do
  LINEN=$((LINEN+1))
  LINES=$(printf "%03d" "$LINEN")
  if [[ -n "$START_FROM" && "$STARTED" = false ]]; then
    if [[ "$VHOST" == "$START_FROM" ]]; then
      STARTED=true
      echo "Start: $VHOST Line: $LINES"
    else
      echo "Skip: $VHOST Line: $LINES"
      continue
    fi
  fi
  if [[ "$STARTED" = true ]]; then
    echo "Processing: $VHOST Line: $LINES"
    httpx2 \
        -l "$IN_FILE" \
        -H "Host: $VHOST" \
        -t 3000 -rl 30000 \
        -rstr 100000 \
        -timeout 5 -retries 1 \
        -ip -sc -title -server -location \
        -stats -si 10 \
        -silent -nc \
        -path "/путь/на/сайте/для/детекта/определённого/типа/сайтов/" -mc 200 -ms "Заголовок сайта - они одинаковы для типа сайтов которые я ищу" \
        1>>"$HOME/2/$LINES-$VHOST.txt" \
        </dev/null
  fi
done < $VHOSTS_FILE
Скрипт тупо на каждый vhost бежит по списку IP и на каждом пытается этот vhost найти, мэтча ответ по наличию определённого пути и заголовка.
Тестовые сайты из моего тестового набора (загонял небольшой range IP и vhost'ы для заранее известных сайтов этого типа за CloudFlare, те что уже знаю где) - детектятся как здрасьте.


это реверс прокси или лоад балансеры которые проксируют трафик через cloudflare

они конфигурируются так что принимают любой хост и проксируют на заданный бэкенд через cloudflare
поэтому cf-ray есть а IP не cloudflare

для фильтрации таких фолс позитивов:

1. проверяй принадлежность IP к диапазонам cloudflare

curl -s https://www.cloudflare.com/ips-v4/ | grep -q "$IP"


2. добавляй в httpx проверку на сертификат

httpx -ssl -silk -ct

3. используй кастомные matchers для проверки что это настоящий cloudflare

YAML:
matchers:
  - type: word
    part: header
    words:
      - "cf-cache-status"
      - "cf-ray"
    condition: and

4. либо вообще исключи digitalocean из поиска если ищешь только настоящие cloudflare IP

такие прокси обычно настраивают для обхода блокировок или кэширования
 
1. проверяй принадлежность IP к диапазонам cloudflare

curl -s https://www.cloudflare.com/ips-v4/ | grep -q "$IP"
ха, прикол как раз в том что они попадаются на DigitalOcean IP из диапазонов AS14061 :)
но я уже понял, спасибо, что это какие-то прокси. детект простой - заголовки от них в ответах cf-ray и server:cloudflare чего на DO быть не должно, но если к CF проксируют то запросто могут быть, в общем фильтровать по заголовкам просто надо.
 
4. либо вообще исключи digitalocean из поиска если ищешь только настоящие cloudflare IP
фишка как раз в том чтобы найти домены (vhosts) на DigitalOcean, которые спрятали за CloudFlare
потому что CloudFlare имеет защиту от DDoS, WAF может там быть и порты попрятаны все кроме 80 и 443 , то есть CF как реверс-прокси до оригинала (который может быть вообще хз где, не обязательно на DO, поиск тут увы обширный, но не безнадёжны это факт, то есть я знаю чего делаю, просто аномалии вот такие увидел, заинтересовали)
а если найти оригинал то велик шанс (практика, уже находил) что админ криворучка и порты не закрыл например от БД или других сервисов, понадеялся типа на "зонтик" от CloudFlare ;-)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
фишка как раз в том чтобы найти домены (vhosts) на DigitalOcean, которые спрятали за CloudFlare
потому что CloudFlare имеет защиту от DDoS, WAF может там быть и порты попрятаны все кроме 80 и 443 , то есть CF как реверс-прокси до оригинала (который может быть вообще хз где, не обязательно на DO, поиск тут увы обширный, но не безнадёжны это факт, то есть я знаю чего делаю, просто аномалии вот такие увидел, заинтересовали)
а если найти оригинал то велик шанс (практика, уже находил) что админ криворучка и порты не закрыл например от БД или других сервисов, понадеялся типа на "зонтик" от CloudFlare ;-)
да, для этого отфильтруй прокси проверкой что сервер отвечает только на конкретный vhost
добавь в скрипт проверку:

httpx -header "Host: example.com" -server cloudflare -status-code 200 -no-fallback

и исключи все где server: nginx/apache но есть cf-ray
так найдешь только настоящие origin сервера с уязвимыми портами
 
В общем вот нормальный скрипт, может и неоптимальный, однако реально ищет и главное находит хосты за CloudFlare (а что ещё надо? works for me в общем), вдруг кому пригодится:
Код:
#!/bin/bash

IN_FILE="$HOME/AS14061_IPs_with_webservers.txt"
VHOSTS_FILE="$HOME/vhosts_to_find_in_AS14061.txt"
START_FROM="sitename_in_vhosts_to_find_file_to_start_from_if_script_was_interrupted.com"
STARTED=false
LINEN=0

while read VHOST; do
  LINEN=$((LINEN+1))
  LINES=$(printf "%03d" "$LINEN")
  if [[ -n "$START_FROM" && "$STARTED" = false ]]; then
    if [[ "$VHOST" == "$START_FROM" ]]; then
      STARTED=true
      echo "Start: $VHOST Line: $LINES"
    else
      echo "Skip: $VHOST Line: $LINES"
      continue
    fi
  fi
  if [[ "$STARTED" = true ]]; then
    echo "Processing: $VHOST Line: $LINES"
    httpx2 \
        -l "$IN_FILE" \
        -H "Host: $VHOST" \
        -t 3000 -rl 30000 \
        -rstr 100000 \
        -timeout 5 -retries 1 \
        -ip -sc -title -server -location \
        -stats -si 10 \
        -silent -nc \
        -path "/service/api-docs/" \
        -mc 200 \
        -fdc 'contains(webserver, "cloudflare") || contains(raw_header, "Cf-Ray:") || contains(raw_header, "cf-ray:")' \
        -ms "REST-API documentation" \
        1>>"$HOME/2/$LINES-$VHOST.txt" \
        </dev/null
  fi
done < $VHOSTS_FILE

Подсетки в AS'ке удобнее всего найти с помощью bgpq3 (есть в linux, стандартная тулза типа whois, то есть sudo apt install bgpq3 и готово)

Пример ( например, для DigitalOcean'овской AS14061 ) :
1. Для получения IPv4 префиксов bgpq3 -4 AS14061 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]+'
2. Для получения IPv6 префиксов bgpq3 -6 AS14061 | grep -Eo '([0-9a-f:]+:+)+[0-9a-f]+/[0-9]+'

Ну и эти подсетки пройтись masscan примерно как-то вот так (--rate - сами решайте, смотря какой у вас хост и сетка чего могут) :
masscan -iL ./AS14061_prefixes_IPv4_from_bgpq3_output.txt -p443,80 --rate=100000 --open-only -oH ./AS14061_IPs_with_webservers.txt

Для того чтобы сетка лётала, а не как черепаха, лучше лимиты на хосте поднять ну вот как-то примерно так:
1. делаем файлик sudo touch /etc/sysctl.d/99-custom.conf
2. содержимое:
Код:
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 250000
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65536
net.ipv4.ip_local_port_range = 1024 65535
3. и применяем: sudo sysctl -p /etc/sysctl.d/99-custom.conf
4. и потом ещё: sudo ulimit -n unlimited чтоб файлов/сокетов побольше проги могли создавать (можно в /etc/security/limits.conf внести конечно, но мне тупо лень обычно)
5. ну и можно сканить вот тут ;-)

p.s. отдельное спасибо c0d3x за -fdc 'contains(webserver, "cloudflare") || contains(raw_header, "Cf-Ray:") || contains(raw_header, "cf-ray:")' - false positives пропали, теперь скрипт находит цели чётко без шумов в логах.
 
На AWS ещё более странные странности обнаружились, например вот даже без Host: заголовка если то выдаёт формально "всё правильно то что ты и искал" (по факту нет) :
Код:
# curl -v http://3.18.189.183/service/api-docs/                                                              
*   Trying 3.18.189.183:80...
* Connected to 3.18.189.183 (3.18.189.183) port 80
* using HTTP/1.x
> GET /service/api-docs/ HTTP/1.1
> Host: 3.18.189.183
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 13 Nov 2025 14:53:16 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
<
<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>REST-API documentation</title>
<link rel="stylesheet" href="/service/api-docs/_nuxt/entry.BFKwzBd8.css">
<link rel="modulepreload" as="script" crossorigin href="/service/api-docs/_nuxt/_CONFIG.js">
<link rel="modulepreload" as="script" crossorigin href="/service/api-docs/_nuxt/entry-B4xqIixo.js">
<link rel="prefetch" as="style" href="/service/api-docs/_nuxt/error-404.CoUbADi5.css">
<link rel="prefetch" as="script" crossorigin href="/service/api-docs/_nuxt/Bb5Tybgj.js">
<link rel="prefetch" as="script" crossorigin href="/service/api-docs/_nuxt/BYrALbB2.js">
<link rel="prefetch" as="script" crossorigin href="/service/api-docs/_nuxt/BSTkL9fj.js">
<link rel="prefetch" as="style" href="/service/api-docs/_nuxt/error-500.BXQ_YkC0.css">
<link rel="prefetch" as="script" crossorigin href="/service/api-docs/_nuxt/CkmUGbkE.js">
<script type="module" src="/service/api-docs/_nuxt/_CONFIG.js" crossorigin></script>
<script type="module" src="/service/api-docs/_nuxt/entry-B4xqIixo.js" crossorigin></script>
<script id="unhead:payload" type="application/json">{"title":"REST-API documentation"}</script><script>"use strict";(()=>{const a=window,e=document.documentElement,c=window.localStorage,d=["dark","light"],n=c&&c.getItem&&c.getItem("nuxt-color-mode")||"system";let l=n==="system"?f():n;const i=e.getAttribute("data-color-mode-forced");i&&(l=i),r(l),a["__NUXT_COLOR_MODE__"]={preference:n,value:l,getColorScheme:f,addColorScheme:r,removeColorScheme:u};function r(o){const t=""+o+"-mode",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function u(o){const t=""+o+"-mode",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function m(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function f(){if(a.matchMedia&&m("").media!=="not all"){for(const o of d)if(m(":"+o).matches)return o}return"light"}})();
</script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
<script>window.__NUXT__={};window.__NUXT__.config={public:{PROJECT_NAME:"",PROJECT_DOMAIN:""},app:{baseURL:"/service/api-docs/",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"49618e0026af410c95fa6735c73dae5d","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
* Connection #0 to host 3.18.189.183 left intact
</body></html>
Ну и на каждый vhost с 10-к таких вылазит, руками заманаюсь проверять 200+ vhost'ов
С https:// с ними проще - там сертификаты на какие-то левые домены вылазят и всё понятно сразу.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх