У нас неловкая, постоянная ситуация с получением нежелательных комментариев в нашем корпоративном пространстве Podio с помощью функции Email to Item .Мы получаем спам спорадически, в некоторые дни мы получаем пару сотен из них.Удаление пользователя-нарушителя из рабочей области Podio не помогает.Мы, конечно, связались со службой поддержки Podio, но они не могут помочь.
Я предполагаю, что другие имеют или уязвимы в том же нарушении.Кажется, Кирстен Кэмпбелл-Моррис сообщил в 2014 году о том же нарушении.
Наш анализ состоит в том, что уведомление электронной почты, которое отправляет Подио, было захвачено, и используются уникальные адреса для ответа.Согласно нашему анализу (и теории), это уязвимость только для записи.
В нашем случае спам-элементы легко классифицировать как спам / хам: все они принадлежат одному пользователю ? и всегда поступают черезфункция отправки по электронной почте.Кроме спама, нам никогда не нужна эта функция, и мы были бы рады полностью избавиться от этой плохо управляемой функции.
Мы наметили три альтернативных решения в хронологическом порядке разработки:
- Программа периодической очистки
- Программа JavaScript, работающая на DOM
- Конечная точка веб-крюка
Описание остальных (1. и2.), но мы бы предпочли использовать последнюю идею (3.), используя webhooks .Идея состоит в том, чтобы создать один или несколько comment-create
хуков для всех приложений в нашей рабочей области.Он получит HTTP-запрос на создание комментария, аутентифицируется с помощью API Podio, получит соответствующий комментарий, решит, является ли он спамом или нет, и при необходимости удалит его (как сказано, решение о том, что является спамом, в нашем случае является простым).
Я реализовал эту идею как минимальную Lumen конечную точку API.При получении запроса webhook со следующей полезной нагрузкой JSON
{
"item_id": "yyyyyyyyy",
"hook_id": "zzzzzzz",
"type":"comment.create"
}
он передается PodioComment::get()
для принятия решения.
Проблема заключается в том, что операция удаления [PodioComment::delete()](https://developers.podio.com/doc/comments/delete-a-comment-22347) receives a
PodioForbiddenError`, хотя он аутентифицируется с помощью токена от пользователя ?.
трассировка стека PHP
PodioForbiddenError
in Podio.php line 319
at Podio::request('DELETE', '/comment/xxxxxxxx', array()) in Podio.php line 358
at Podio::delete('/comment/xxxxxxxx') in PodioComment.php line 46
at PodioComment::delete(xxxxxxxx) in CommentController.php line 116
Что здесь происходит?Я не аутентифицируюсь должным образом?Я могу выполнять другие задачи, например получать комментарии и другие элементы Podio, и Podio::setup()
и Podio::authenticate_with_app()
запускаются успешно, с идентификатором клиента и секретом, а также идентификатором приложения и токеном.
Наша текущая теория заключается в том, что Email to Item - это отдельное приложение (со своим собственным app_id
).Если это правильно, как мы можем аутентифицировать это приложение, чтобы удалить из него комментарии?Если нет, что еще мы можем сделать, чтобы удалить спам-комментарии?Как мы можем проверить, какие разрешения имеет наша пользовательская программа для различных элементов Podio?
Подробная информация о решениях 1. и 2.
Эскиз решения 1. Программа периодической очистки (не работает)
Первый (1.) из них - это программа PHP, написанная с PHP-клиентом Podio и планировавшаяся как cronjob.Идея заключалась в том, чтобы периодически - скажем, каждые 6 часов - проверять подлинность, сканировать все элементы на наличие новых комментариев и удалять их, если они считаются спамом.Это не сработало, потому что, хотя программа работала на ключах API пользователя-администратора, у нее не было разрешения на удаление комментариев, сделанных пользователем ?.
Эскиз решения 2. Программа JavaScript, работающая на DOM(работает, если поддерживается вручную)
Это хак с скрапсингом и автоматическим нажатием кнопок в веб-интерфейсе.
Мы авторизируемся как пользователь ?, перейдем к потоку их активности, откроем инструменты разработчика браузераСкопируйте и вставьте следующую программу в консоль и перейдите на кофе.Это обходит проблемы аутентификации (1.) и (3.), но неудобно в работе и подвержено ошибкам.
// Add the user id to remove in here. There is a good chance it is
// a six-digit number
var spamUid = 'xxxxxx';
// Consider only comments made after this date
var spamDate = new Date(2018, 04, 01);
var spamUserUrl = 'https://podio.com/users/' + spamUid;
var mnum = {
'January': 0,
'February': 1,
'March': 2,
'April': 3,
'May': 4,
'June': 5,
'July': 6,
'August': 7,
'September': 8,
'October': 9,
'November': 10,
'December': 11
}
var titleToDate = (title) => {
re = /(\s*\d*) ([A-Za-z]*) (\d{4}) (\d*):(\d*)/;
[, D, M, Y, h, m] = re.exec(title);
d = new Date(Y, mnum[M], D, h, m);
return d;
}
var throttling = 2000;
var spamComments = jQuery('.comment')
.filter((i, c) => jQuery(c).find('.comment_byline > a')[0].href == spamUserUrl)
.filter((i, c) => jQuery(c).find('.timestamp > time')[0].title != "")
.filter((i, c) => titleToDate(jQuery(c).find('.timestamp > time')[0].title) > spamDate);
console.log("Found " + spamComments.length + " comments to delete");
spamComments.each((i, c) => {
c.style.border = '5px red dotted';
setTimeout(() => {
console.log("deleting ?", c);
jQuery(c).find('.js-delete-comment').click();
jQuery('.confirm-button')[0].click();
}, i * throttling);
});