neobotnet / blog / company-of-the-week
company of the week·11 min read

company of the week: trip.com

Trip.com sells flights, hotels and rail — about fifty country storefronts, plus a corporate-travel arm, two rail brands, and TripLink, its virtual commercial-card product.

It runs a public bug bounty on HackerOne, which puts that estate in scope for outside research — neobotnet's full index is in /urls. The scope is 18 root domains, and trip.com itself is 171 of 5,027 dns names: 3.4% of it. The other 4,807 belong to Travix, the Dutch flight-booking group Trip.com bought — and Travix's DNS is still narrating that company's engineering history to anyone who reads it.

18
in-scope roots
5,027
dns names
348
live web servers
35
behind one google login
114,396
urls indexed

read from dns: the company inside the company

Public DNS hands you the shape of the company before a page loads. Here it hands you a different company than the one on the letterhead:

trip.com  ·  18 in-scope roots  ·  5,027 dns names  ·  4,807 of them travix's
│
├─ travix · consumer brands ....... cheaptickets.nl ........ 2,890
│                                   vayama.com .............    99
│                                   budgetair.com ..........    98
│                                   vliegwinkel.nl .........    45
│                                   flugladen.de ...........    39
│
├─ travix · platform .............. travix.com .............   993
│
├─ travix · environments that ..... travix.io ..............   169
│  got promoted to root domains     stg.travix.com .........   141
│                                   staging.travix.com .....   114
│                                   development.travix.com .   108
│                                   dev.travix.com .........    50
│                                   playground.travix.com ..    11
│                                   └─ 593 names across these six · 0 answer 200
│
└─ trip.com's own ................. trip.com ...............   171   the namesake — 3.4%
                                    triplinkintl.com .......    52   virtual commercial cards
                                    trip.biz ...............    18   corporate travel
                                    mytrainpal.com .........    17   rail
                                    trainpal.com ...........     6   rail
                                    tyo-masters.co.jp ......     6   jp corporate-travel partner

The 2,890 names on cheaptickets.nl are the marquee finding, and they are not servers. 2,752 of them (95.2%) end in -acceptance or -fe-server — an acceptance environment is the copy of the site a team clicks through before a change ships. 2,159 are prefixed with a ticket id, which means the naming was automated: continuous integration cut a DNS record per feature branch, the branch merged, the environment was torn down, and the record was never deleted.

cheaptickets.nl  ·  2,890 names  ·  2,752 preview environments that no longer exist
│
├─ ori-930-fix-modal-backgr-fe-server
├─ ori-1555-sp-voucher-field-fe-server
├─ ori-1128-analytics--poc--eec-fe-server
├─ srp-design-2-acceptance
├─ clean-small-garbage-acceptance
├─ test-refactor-action-types-fe-server
└─ hotifx-double-booking-on-upsell-acceptance    ← the typo is in the hostname
     │
     30 jira project keys, read straight off dns:
     ORI 889 names (up to #18701) · CFE 461 (#21884) · DIS 278 · MA 135 · PI 90
     PLA 89 · CO 64 · HOT 46 · PAY 40 · THN 27 · AB 11 · FI 4 · EN 3 · GDPR 2

None of these hosts has to be up for that to matter. The map is the value: which teams exist (there is a PAY project and a GDPR project), how far the backlog ran, and what individual tickets were about — hotifx-double-booking-on-upsell is a double-booking bug on an upsell flow, misspelled, preserved in public DNS.

Walk the size back. The 2,890 names resolve to 38 IP addresses — one shared ingress, not per-branch boxes. Of roughly 2,678 probed, 10 answer 200; 1,110 return 403, 912 return 429 (rate-limited at the edge), 645 return 404. The environments are gone; the names outlived them. Same one layer up: the six non-production roots carry 593 names between them and not one answers 200. Named, not reachable.

browse the dns layer in /dns →

read from http: two estates, two standards

4,055 hosts were probed; 348 answer with a live page across 76 fingerprinted technologies. Two of those groups sit in the same DNS zone and follow opposite rules:

travix.com  ·  130 of 931 hosts answer 200  ·  one zone, two standards
│
├─ estate A · behind one google login   (35 hosts · "Sign in - Google Accounts" · server ESF)
│    estafette.travix.com ..................... travix's own open-source ci
│    teamcity · octopus.travix.com ............ build + deploy
│    kibana-prd · kibana.stg · grafana.stg .... logs and dashboards
│    jaeger.prd.travix.com .................... request tracing
│    cockroachdb-estafette-pci.travix.com ..... a pci-scoped database console
│    gcp-iam-role-elevator.tooling.travix.com . a cloud-permission elevator
│    vsaq · sptest.infosec.dev.travix.com ..... security questionnaire + test
│    voucherui · icarusui · maat.travix.com ... internal apps (+ .staging, .development)
│
└─ estate B · no login at all   (12 hosts on *.development.travix.com · Microsoft-IIS/10.0)
     enosis-apigateway.development ....... "Enosis.ApiGateway.WebService - Development"
     enosis-auditing.development ......... "Enosis.Auditing.WebService - Development"
     enosis-orderpusher.development ...... "Enosis.OrderPusher.WebService - Development"
     enosis-pdfgeneration.development .... "Enosis.PdfGeneration.WebService - Development"
     enosis-flightnotification.development "Enosis.FlightNotification.Web - Development"
     enosis-advertisement.development .... "Enosis.Advertisement.WebService - Development"
     enosis-budgetparking.development .... "Enosis.BudgetParking.Web - Development"
     enosis-external.development ......... "Enosis.External.Root.Website - Development"
     enosis-requestbin.development ....... "Enosis.RequestBin.Api - Development"
     enosis-partnerportal.development .... "Home Page - Enosis Partner Portal"
     enosis-finhandoffcreator · -itinerarycache ... "IIS Windows Server" (default page)
     enosis-ticketingfilecontrol.development ...... 500 "Runtime Error" (asp.net error page)

Estate A is the good version. All 35 hosts return the identical Sign in - Google Accounts page served by ESF — Google's Identity-Aware Proxy, a login wall that stands in front of an app so the app itself never faces the internet. CI, log search, tracing, a PCI-scoped database console and a tool for elevating cloud permissions all sit behind it. Even the per-branch preview UIs (pla-4574-vouchermigration-voucherui.travix.com) inherit it.

Estate B is the same company with the wall left off. Twelve .NET services answer 200 on *.development.travix.com with - Development printed in the title and no login in front. Counting the siblings that answer 503, 403, 404 and one ASP.NET Runtime Error, the enosis-* family names 28-plus microservices — API gateway, auditing, order pusher, PDF generation, ticketing file control, schedule change, transactional mail. That is the org chart of a flight-booking back office, readable off DNS, with a dozen doors open on the dev copy.

Trip.com's own side is tidy by comparison — 91 of 149 probed hosts live, mostly country storefronts plus ebooking.trip.com and open.trip.com, and a few unconfigured defaults.

see the un-walled dev estate in /probes →

the twelve enosis .NET services answering 200 in "Development", in /probes

see the google login wall →

the 35 hosts fronted by one "Sign in - Google Accounts" IAP page, in /probes

read from the urls: the payload

114,396 indexed URLs, 92,299 still alive, plus 141,745 historical URLs and 17,801 crawled endpoints. Ranked the way a researcher would work them.

1 — the link is the credential. neobotnet classifies every URL parameter against a signal taxonomy; across the whole corpus exactly 11 URLs carry something that behaves like a key — 6 JSON Web Tokens, 5 other auth tokens. The highest-value shape is on ca.trip.com: /hotels/ViewOrder/<order-id>?token=<64-char>, answering 200. A hotel booking opened by link, with a sequential-looking 11-digit order id in the path and the secret in the query string. The same 64-character token shape appears on /m/passport/emailverify on www. and uk.trip.com, and five marketing-forward URLs plus one /subscribe/unsubscribe carry a JWT — signed, not encrypted, so anyone holding the URL reads the payload.

A secret in a URL travels the way URLs travel: browser history, CDN and proxy logs, and the Referer header handed to every analytics script on the landing page. That is precisely how an outside crawler ended up holding these. The shape is the finding — a secret riding where it lands in logs and history — and a 200 is not a confirmed exploit. Anything genuinely live here belongs in Trip.com's HackerOne channel, not a blog post.

see the token parameters in /urls →

token and jwt parameters riding in trip.com URLs, in /urls

2 — 156 live email links, across six brands. The e.<brand> hosts — cheaptickets, budgetair, vliegwinkel, flugladen, vayama, travix — hold 407 URLs, 156 answering 200. The path shape is /{0,1,2,16}/{4,5}/{1737,1823}/<brand-id>/<opaque-token>: no login, no query string, the token in the path is the credential. Booking mail gets forwarded, archived, pasted into a support ticket; whoever holds the link is treated as the recipient.

One of those rows is why neobotnet filters by content_type — the label the server puts on the bytes — instead of by file extension. A single e.cheaptickets.nl URL serves application/pdf at 200 with no .pdf anywhere in the path; extension-hunting misses it. Corpus-wide that lens finds 24 application/pdf URLs against 78,105 text/html, three of them on enosis-conditions-pdf.travix.com with opaque filenames and a 404 at the root. Same posture as everywhere in this series — anything genuinely live and PII-bearing goes to the program first.

see the email-link estate in /urls →

opaque-token email links on e.cheaptickets.nl, in /urls

3 — four hostnames that answer as other companies. grafana-apex-production.travix.com and grafana-apex-development.travix.com return a consumer delivery app and an unrelated portal; frontend-airlineinfo.travix.com returns a VoIP web client; origin-es-co-www.vayama.com returns a geospatial-analytics workspace. All four answer 200 behind Cloudflare. The observation is one sentence: the hostname is Travix's; the application answering it is not. That is the dangling-DNS shape — a name still pointing at infrastructure the company no longer controls — and it matters because whoever does control it speaks with the company's name in the address bar.

Titles alone are weak evidence, so neobotnet corroborates three ways. Crawled endpoints on grafana-apex-production.travix.com return /app/admin/public/scripts/ng-csv/ng-csv1.js at 200 — an AngularJS admin app, which Grafana is not. The same crawl harvested outbound links into a VoIP vendor's own documentation. And the source maps on origin-es-co-www.vayama.com — a source map is the sidecar that turns a minified bundle back into its original tree — are deck.gl and echarts-for-react: a dataviz bundle on a flight-booking hostname.

see the foreign-serving hosts in /probes →

travix-owned hostnames returning third-party application titles, in /probes

Now the walk-back that matters most. The same title census that surfaced those four also flags 35 hosts answering Sites Dashboard — and those are not takeovers. They are analytics.<cc>.<brand> and analytics-gce.<cc>.<brand> across budgetair.com, vayama.com, flugladen.de and vliegwinkel.nl: perfectly systematic, one per brand per country. The 53 analytics* hosts resolve to 12 IPs including Google Compute Engine addresses that match Travix's own hosting, and the -gce suffix is Travix's own naming convention. This is one Travix analytics app deployed uniformly. It looks like a mass hijack in a title census and it isn't — a census that skips the corroboration step files 35 false reports.

The rest of the loud signals walk back too. 22 source maps, 4 carrying original sources, 1,730 files — but all four are npm vendor bundles with empty internal paths, so zero Travix first-party source came back and "1,730 source files recovered" would have been a false headline. The PDFs on s1.travix.com and pages.trip.com are brand terms, cookie lists and published insurance policies. download.trip.com serves React-Native hot-update bundles at 200 off a public app CDN — the only leak there is module naming (rn_flight_afterservice, rn_hotel_room_floating_layer) and build numbers. The 13,758 text/plain URLs are archived 404 bodies. The 331 same-domain redirects are login-return plumbing, not open redirects. And across all 114,396 URLs: credential in url 0, cloud key 0, file path traversal 0, private ipv4 0.

what it adds up to

Ranked for a researcher working the program:

  1. the booking-view token surface — a 64-character secret in the query string of a URL that opens a hotel booking. Move it out of the query string; the disclosure channel gets this before anyone else does.
  2. the un-walled dev estate — twelve .NET services answering 200 with - Development in the title, while 35 internal tools sit behind one Google login. The wall already exists; estate B just isn't behind it.
  3. the four foreign-serving hostnames — reclaim or remove the records.
  4. the ticket-named DNS estate — 2,752 names for environments that no longer exist, publishing 30 project keys and 2,159 ticket ids. Deleting a stale DNS record is the cheapest fix on this list.

Two things stated plainly, the way this series always closes. Every item above is a signal, not a confirmed vulnerability — neobotnet surfaces the shape; confirming exploitability is the researcher's job. And the right destination for anything live is Trip.com's HackerOne program, not a blog post.

next week

neobotnet runs the same pass on a different in-scope program every week. Subscribe via RSS or browse the company of the week archive.