<aside> 🦸🏻 Автор: Дима Богер, [email protected]
</aside>
На входе в задачу — ссылка на сайт в облаке, принципиальная схема приложения и слухи про утечки в голанге. Причем и слухи об утечке, и схему приложения прикрепили уже позже.
Две виртуалки в облаке: одна обслуживает запросы к админке, а другая к публичной версии сайта. Админка за Google IAP, поговорим про это чуть дальше.
Подсказок негусто, поэтому начинаем копаться в сайте и хосте. Сайт довольно простой, и состоит из одного SPA приложения, загружаемого из /
. Пройдёмся по всему что там есть:
Форма ввода, отправляющая PUT /api/order
, возвращающая ID заказа нашей еды.
Запрос на создание ордера и его ответ
Параллельно запускаем набор волшебника из dirsearch (ищет открытые URL сайта с чем-нибудь интересным) и nmap (сканирует порты). Сверху на сайте есть вкладка admin, и она ведёт себя очень интересно:
cloud-eats-admin
который закрыт Identity Aware Proxy, то есть доступен только после входа в разрешенный гугл-аккаунт 😱Т.к. мы можем спокойно почитать исходники всего SPA, то посмотрим что вообще делает закрытая часть приложения:
t.prototype.componentDidMount = function() {
p.default.dev || window.location.host === p.default.adminIap || window.location.replace("https://" + p.default.adminIap + "/"); // REDIRECT GUARD
}
3051: function(e, t, n) {
... // ADMIN API
t.putOrder = function(e, t) {
return fetch("/api/order", {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
address: e,
phone: t
})
})
}
,
t.getOrders = function() {
var e = o.default.dev ? {
headers: {
"x-dev-email": o.default.email
}
} : {};
return fetch("/api/admin/orders", e)
}
,
t.getUsers = function() {
var e = o.default.dev ? {
headers: {
"x-dev-email": o.default.email
}
} : {};
return fetch("/api/admin/users", e)
}
,
t.getFiles = function() {
var e = o.default.dev ? {
headers: {
"x-dev-email": o.default.email
}
} : {};
return fetch("/api/admin/files", e)
}
,
t.getMe = function() {
var e = o.default.dev ? {
headers: {
"x-dev-email": o.default.email
}
} : {};
return fetch("/api/admin/me", e)
}
},
3329: (e,t)=>{
t.default = { // SPA CONFIG
adminIap: "cloud-eats-admin.2537ly.space",
dev: !1,
email: "accounts.google.com:[email protected]"
}
}
Что мы видим:
GET /api/admin/files
GET /api/admin/me
GET /api/admin/users
GET /api/admin/orders