Google翻訳のURLを悪用してフィッシングサイトへ転送する手口に関するメモ。
背景
Google翻訳をフィッシングに悪用する手口は、数年前より知られている。最近また急に増えてきたが、以前とは少し手口が変わっているようなので、イマドキの手口に関してメモしておく。
説明中では、安全のためフィッシングURL内のピリオド(.
)を角カッコを付加した[.]
に置き換えてある。
Google翻訳の機能
Google翻訳には、https://translate.google.com/translate?
に続けてパラメータを指定することで、指定したWebページを翻訳する機能がある。
そのとき指定できるパラメータは、次のもの。
hl
:host languageの略で、Google翻訳ページの表示言語のコード。sl
: source languageの略で、翻訳元の言語コード。tl
:target languageの略で、翻訳先の言語コード。u
:翻訳対象のURL。client
:リクエスト元のクライアント識別子。Googleの内部的な用途で、どのサービス/アプリ/APIキーから来たのかを示す。
この「翻訳対象」であるu
に悪意あるページを指定することで、フィッシングサイトへの誘導リンクとすることが可能。2022年頃に報告が増えた手口だが、2025年3月頃から再び形を変えて増加中。
最近のフィッシングメールでは、フィッシング用のGoogle翻訳リンクでu
に指定する文字列に可読性がない。それにより、Googleやセキュリティソフトによってフィッシング判定されるのを回避しようとしているものと思われる。
解析
Google翻訳リンクの悪用例をもとに、動きを追う。
https://translate[.]google[.]jp/translate?hl=ja&sl=ja&tl=JP-JP&u=%F0%9F%84%B6%F0%9F%84%BE%F0%9F%84%BE[.]%F0%9F%85%82%F0%9F%85%84%2F%53%41%45%45%44%41%53%44%53&client=ULgEWYI
u=
の後ろにあるURLエンコードされた部分をデコードすると、次のようになる。(ピリオドは角カッコ付きのものと置き換え)
🄶🄾🄾[.]🅂🅄/SAEEDASDS
ドメイン名の部分で、アルファベットが四角囲み文字になっている。
Google翻訳では、四角囲み文字を自動的にアルファベットに置き換えている。したがって上記の値は、省略されているスキーマ部分にデフォルトとしてhttps://
を追加し、次のURLとして扱われる。
https://GOO[.]SU/SAEEDASDS
Google翻訳の機能というより、Googleでは共通的にそのような扱いをしているのかもしれない。四角囲み文字でドメイン名を記述してそのままGoogle Chromeのアドレスバーに入力しても、自動的にアルファベット変換した上でスキーマを追加して転送するから。
Safariで試したところ、そのような動作はしなかった。単純に四角囲み文字をそのまま検索文字列として検索結果を表示するだけ。自動変換は、Google関連の製品固有の動作と思われる。
このURLをcurlによりヘッダを表示させながら内容を取得してみる。
curl -Lv https://GOO[.]SU/SAEEDASDS
表示結果は、次のとおり。
* Host GOO[.]SU:443 was resolved.
* IPv6: (none)
* IPv4: 104.26.3.56, 104.26.2.56, 172.67.71.24
* Trying 104.26.3.56:443...
* Connected to GOO[.]SU (104.26.3.56) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=goo[.]su
* start date: Mar 22 06:24:42 2025 GMT
* expire date: Jun 20 07:23:24 2025 GMT
* subjectAltName: host "GOO[.]SU" matched cert's "goo[.]su"
* issuer: C=US; O=Google Trust Services; CN=WE1
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://GOO[.]SU/SAEEDASDS
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: GOO[.]SU]
* [HTTP/2] [1] [:path: /SAEEDASDS]
* [HTTP/2] [1] [user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36]
* [HTTP/2] [1] [accept: */*]
> GET /SAEEDASDS HTTP/2
> Host: GOO[.]SU
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< date: Sat, 10 May 2025 01:10:59 GMT
< content-type: text/html; charset=UTF-8
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=tzU%2BnsFJu2xbrnAyblfdeG1cbJ%2BsUn2BnJkEhuV39sfV%2FFxGIvIf8zIwZkEQnuXtWvw2AdfiMGeN4UQTfWahtc1yG%2BHVzT2qBqFqogvH0hw%2Bycdin59IfKI%3D"}],"group":"cf-nel","max_age":604800}
< server: cloudflare
< vary: Accept-Encoding
< x-powered-by: PHP/8.2.13
< cache-control: private, must-revalidate
< pragma: no-cache
< expires: -1
< cf-ray: 93d58f572fb183c1-NRT
< cf-cache-status: DYNAMIC
< set-cookie: block_ads=1; HttpOnly; SameSite=Lax; Secure; Path=/; Max-Age=60; Expires=Sat, 10 May 2025 01:11:59 GMT
< set-cookie: XSRF-TOKEN=AVHHXi4VqT2UYVlkwqBbPMWI7TuZen1nngdjfE5T; SameSite=Lax; Secure; Path=/; Max-Age=67200; Expires=Sat, 10 May 2025 19:50:59 GMT
< set-cookie: goosu_session=A3zHiNbcmAHhwu0485r2gMN4LW2AQWnLjmcMiO46; HttpOnly; SameSite=Lax; Path=/; Max-Age=67200; Expires=Sat, 10 May 2025 19:50:59 GMT
< alt-svc: h3=":443"; ma=86400
< server-timing: cfL4;desc="?proto=TCP&rtt=13064&min_rtt=11096&rtt_var=3733&sent=7&recv=10&lost=0&retrans=0&sent_bytes=2878&recv_bytes=642&delivery_rate=233783&cwnd=239&unsent_bytes=0&cid=ef4d673aa05373a3&ts=876&x=0"
<
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicons/favicon-16x16.png">
<link rel="manifest" href="/img/favicons/site.webmanifest">
<link rel="mask-icon" href="/img/favicons/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="theme-color" content="#ffffff">
<meta name="robots" content="none" />
<title>icloudcard</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta property="og:title" content="" />
<meta property="og:description" content="" />
<meta property="og:image" content="" />
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-TRGNQBDL');</script>
<!-- End Google Tag Manager -->
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-TRGNQBDL"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
</head>
<body class="vh-100" x-data="{ botInfo: null }" x-init="(async () => {
const botdPromise = import('https://openfpcdn.io/botd/v1').then((Botd) => Botd.load())
botdPromise
.then((botd) => botd.detect())
.then((result) => botInfo = result)
.catch((error) => console.error(error))
})()">
<script>
var pixels = 0;
if (!pixels) {
window.location = 'https://mxksauqsx[.]net';
} else {
setTimeout(function () {
window.location = 'https://mxksauqsx[.]net';
}, 600)
}
</script>
</body>
</html>
* Connection #0 to host GOO[.]SU left intact
まずGOO[.]SU
から小文字可したドメイン名goo[.]su
にWebサーバ内で自動転送される。
転送先のWebページでは、JavaScript内でwindow.location
にURLを設定することにより、さらに転送している。
この転送先を先ほどと同様に、curlで取得してみる。
curl -Lv https://mxksauqsx[.]net
表示結果は、次のとおり。
* Host mxksauqsx[.]net:443 was resolved.
* IPv6: 2606:4700:3037::ac43:d50d, 2606:4700:3036::6815:3dbc
* IPv4: 172.67.213.13, 104.21.61.188
* Trying [2606:4700:3037::ac43:d50d]:443...
* Connected to mxksauqsx[.]net (2606:4700:3037::ac43:d50d) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=mxksauqsx[.]net
* start date: May 9 10:16:04 2025 GMT
* expire date: Aug 7 11:11:20 2025 GMT
* subjectAltName: host "mxksauqsx[.]net" matched cert's "mxksauqsx[.]net"
* issuer: C=US; O=Google Trust Services; CN=WE1
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://mxksauqsx[.]net/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: mxksauqsx[.]net]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: mxksauqsx[.]net
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< date: Sat, 10 May 2025 01:14:36 GMT
< content-type: text/html
< server: cloudflare
< last-modified: Fri, 09 May 2025 11:02:15 GMT
< nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800}
< report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=R7xmlg0RKlcNPtUIqm2NFZRz%2FZx7B%2BjyTpKu0KX8vOShMLI8UmzHw8fi5ICfqQFF3Etlf8gNRNc2k4Gy2V1XwBBVY67jVHeZvxJsQ5u9VvBZHS8585X0TgvrgRr9X9jDWWXqf6VX0J65IRY7"}]}
< accept-ranges: bytes
< cf-cache-status: DYNAMIC
< cf-ray: 93d594ab5d2ed789-NRT
< alt-svc: h3=":443"; ma=86400
<
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=https://mxksauq[.]xyz/ISNhua8HUAhs7a/">
<title> </title>
</head>
<body>
</body>
* Connection #0 to host mxksauqsx[.]net left intact
</html>%
METAタグを使ってhttps://mxksauq[.]xyz/ISNhua8HUAhs7a/
に転送していることがわかる。このhttps://mxksauq[.]xyz/ISNhua8HUAhs7a/
が本命のフィッシングサイト。
まとめ
2025年3月以降に増加中のGoogle翻訳を悪用したフィッシングサイトへの誘導リンクは、次のように何段階もの転送を経ている。
- Google翻訳に渡すURLは、ドメイン名を四角囲み文字にした上でURLエンコード。
- Googleでは四角囲み文字も自動的にアルファベット変換。
- ドメイン名は大文字と小文字を区別しないため、Webサーバ上で小文字のドメイン名に自動転送。
- 転送先では、JavaScriptにより転送。
- 転送先で、さらにHTMLのMETAタグにより転送。
- フィッシングサイト。
転送しまくりだが、実際に経由したホストは次のとおり。
goo[.]su
(IP: 104.26.2.56, Cloudflare)mxksauqsx[.]net
(IP: 104.21.61.188, Cloudflare)mxksauq[.]xyz
(IP: 43.164.131.18, Tencent/Aceville)
最初の二つは転送しているだけで、フィッシングサイト本体ではない。このため、通報しても対処がされない。
転送用サイトとフィッシングサイト本体でホスティングサービスを使い分けているのは、対処されにくくするための手口と思われる。フィッシングサイトを閉鎖させるためには、最終的に転送される本体サイトを通報する必要あり。
とても面倒くさい。