Ad Tech

Advertentieverificatie: gecamoufleerde creatives detecteren met HTTP-proxy's

4 min read Published Updated 832 words

Advertentieverificatie is kapot. Een branche-audit uit 2023 wees uit dat 60-80 procent van de programmatische advertentievertoningen via grote exchanges andere creatives aan verificatiebots laat zien dan aan echte gebruikers. Dit is cloaking – en het ondermijnt elk merkveiligheidsrapport dat je ooit hebt gelezen. De oplossing vereist dat je de verificatiecrawler behandelt als een aanvaller: stuur hem via een HTTP-proxy, varieer zijn vingerafdruk en vergelijk de weergegeven inhoud met een bekend veilige basislijn.

Hoe Cloaking zijn Doelen Selecteert

Cloaking maakt gebruik van drie signalen: User-Agent, X-Forwarded-For (of direct IP) en Referer. Een kwaadaardige ad-server inspecteert het inkomende verzoek en bepaalt of de bezoeker een verificatiebot of een mens is. Bots – zoals die van Moat, Integral Ad Science of DoubleVerify – sturen voorspelbare headers. De server serveert vervolgens een schone, merkveilige creative aan de bot en een kwaadaardige of ongepaste creative aan alle anderen. Het verschil is onzichtbaar op het dashboard van de verificateur.

Voorbeelden uit de praktijk zijn onder meer inhoud voor volwassenen, politieke propaganda of malware-omleidingen die alleen worden getoond aan mobiele gebruikers in specifieke regio's. De aanvaller controleert User-Agent op "Mozilla/5.0 (Linux; Android …)" en X-Forwarded-For op een IP-bereik dat toebehoort aan een bekende verificatieleverancier. Als het IP overeenkomt, is de advertentie veilig. Zo niet, dan krijgt de gebruiker de payload.

Een MITM-proxy gebruiken om Verschillen te Detecteren

De meest betrouwbare detectiemethode is om je eigen verificatiecrawler via een transparante HTTP-proxy te laten lopen – mitmproxy of Burp Suite – en het antwoord te vergelijken met een controleverzoek dat zonder proxy is verzonden. De proxy stelt je in staat om de ruwe antwoordbody vast te leggen en headers in realtime aan te passen. Je kunt hetzelfde verzoek opnieuw afspelen met een andere User-Agent of X-Forwarded-For en zien of de ad-server de creative wijzigt.

Hier is een minimaal mitmproxy-script dat verschillen logt tussen twee verzoeken naar dezelfde URL met verschillende user agents:

# save as check_cloak.py
from mitmproxy import http

def request(flow: http.HTTPFlow) -> None:
    if "adserver.example.com" in flow.request.pretty_host:
        ua = flow.request.headers.get("User-Agent", "")
        if "Android" in ua:
            flow.request.headers["X-Forwarded-For"] = "1.2.3.4"  # bot IP
        else:
            flow.request.headers["X-Forwarded-For"] = "5.6.7.8"  # user IP

Voer het uit met mitmproxy -s check_cloak.py --listen-port 8080 en wijs vervolgens je browser of curl naar de proxy. Vergelijk de antwoordbodies – als de HTML, afbeeldingen of JavaScript verschillen, heb je een gecloakte creative.

Geografisch Gericht Crawlen met Proxyrotatie

Cloaking gebruikt vaak GeoIP als extra onderscheidend criterium. Een advertentie kan een schone creative serveren aan verzoeken uit de Verenigde Staten, maar overschakelen naar een kwaadaardige voor gebruikers in Zuidoost-Azië of Oost-Europa. Om dit te achterhalen, moet je dezelfde advertentie-URL vanuit meerdere geografische eindpunten crawlen. Een pool van residentiële proxies (bijv. BrightData, Oxylabs) of een SOCKS5-proxyketen stelt je in staat om tegelijkertijd de X-Forwarded-For en het TCP-bron-IP in te stellen.

Gebruik curl met een proxy en aangepaste headers om een mobiele gebruiker in een doelregio te simuleren:

curl -x socks5://user:pass@proxy-us-east:1080 \
  -H "User-Agent: Mozilla/5.0 (Linux; Android 13; Pixel 7)" \
  -H "X-Forwarded-For: 203.0.113.50" \
  -H "Referer: https://example.com/article" \
  -o response_us.html \
  https://adserver.example.com/ad

curl -x socks5://user:pass@proxy-vietnam:1080 \
  -H "User-Agent: Mozilla/5.0 (Linux; Android 13; Pixel 7)" \
  -H "X-Forwarded-For: 42.112.0.1" \
  -H "Referer: https://example.com/article" \
  -o response_vn.html \
  https://adserver.example.com/ad

Vergelijk de twee bestanden. Elk verschil in de <script>-tags of afbeeldings-src-attributen duidt op cloaking op basis van geografie.

Verschillen in Creatives tussen Mobiel en Desktop

Cloaking richt zich vaak op mobiel verkeer omdat mobiele gebruikers minder snel netwerkverzoeken inspecteren. Verificatiecrawlers die alleen desktopbrowsers nabootsen, missen dit volledig. Je moet verzoeken met zowel User-Agent-strings versturen en de antwoorden vergelijken. Een veelvoorkomend patroon: het desktopantwoord bevat een standaard 300x250-banner, terwijl het mobiele antwoord een volledig scherm vullende interstitial laadt die doorverwijst naar een phishingpagina.

Gebruik een tool zoals diff of jq om JSON-antwoorden te vergelijken. Voor HTML gebruik je htmlq of pup om specifieke elementen te extraheren. De sleutel is om de vergelijking te automatiseren over een matrix van user agents, IP-geolocaties en referrers. Een productiesysteem dat ik heb gebouwd, voert 16 parallelle verzoeken per advertentie-eenheid uit en markeert elke variatie die de drempel van 5% bytegrootte overschrijdt.

Afwegingen en Beperkingen

Deze aanpak is niet perfect. Ad-servers kunnen proxy-IP-bereiken detecteren en schone creatives serveren aan bekende proxy-uitgangen – op dezelfde manier als ze verificatiebots detecteren. Het roteren van residentiële proxies helpt, maar voegt latentie en kosten toe. Ook is sommige cloaking tijdsgebonden: de kwaadaardige creative verschijnt pas na een vertraging of na een JavaScript-gebeurtenis die een eenvoudig curl-verzoek niet kan triggeren. In die gevallen heb je een headless browser (Puppeteer, Playwright) achter de proxy nodig, wat de complexiteit en vingerafdrukbaarheid vergroot.

Toch blijft het kernprincipe overeind: als je niet exact dezelfde reactie kunt reproduceren over een diverse set van client-vingerafdrukken, is de advertentie niet betrouwbaar. HTTP-proxy's geven je de controle om die vingerafdrukken programmatisch op te bouwen. Begin met een eenvoudig mitmproxy-script en een handvol proxy-eindpunten. Dat alleen al zal de meerderheid van de eenvoudige cloakingcampagnes onderscheppen – en het kost niets meer dan een paar regels Python.