С чего всё началось
Все мы знаем, что у ВК есть API, и я уверен, что большинство людей пыталось им воспользоваться в своих целях. Лично у меня полно проектов, связанных с ним: штук 5 мощных ботов, составление масштабных датасетов из постов групп и т.д. И не удивительно, что мои знакомые просили меня пару раз выкачать песни из вложений диалога, фотографии или же сохранить текст переписок с каким-нибудь человеком в отдельный файл.
Но однажды пришло «оно», и с того момента выполнение таких небольших просьб перестало быть тривиальной задачей:
И вот, пару дней назад, чтобы раз и навсегда избавиться от этой проблемы, я решил написать свою обёртку через http запросы, притворяясь обычным пользователем, дабы иметь такой же мощный инструмент, как официальный API для раздела messages.
Переходим к делу
Итак, начал я с авторизации. Вооружившись сниффером https и Firefox-ом, я смог пройти все «ступеньки» авторизации и получить финальные куки. С этого момента оставалось только понять, как именно делаются запросы. Было выяснено, что большинство данных получается POST запросом от https://vk.com/wkview.php, просто каждый раз меняются параметры для разных ситуаций. Мне удалось написать функции для выкачки абсолютно всех видов вложений, но не будем вдаваться в подробности этого, потому что в один момент всё кардинально изменилось.
Ссылка на файл для получения куки авторизации (Писал только для двухфакторной аутентификации, так как она стоит у большинства людей)
Неожиданное открытие
Я работал на ноутбуке, когда ко мне подошёл знакомый и спросил, чем я занимаюсь. Так как у меня не получилось ему объяснить всю проблему быстро на пальцах, я открыл официальную документацию на разделе messages, и обомлел, когда увидел, что находится под главным описанием у этих «запрещённых» методов:
Нет, вы поймите меня правильно, я не первый раз вижу эту возможность. Я много раз пользовался ею у других методов, но я даже и подумать не мог, что функция «пример запроса» останется у методов раздела messages. И ещё более сильным было моё удивление, когда я проснифферил трафик. Это были просто обычные запросы к API, только на сайте , у которых лишь слегка отличались названия параметров в веб-форме и был какой-то хэш-айди.
За несколько минут я понял, что хэш-айди — это просто строка, находящаяся в атрибуте data-hash тэга кнопки, а ещё через пару минут я уже вовсю пытался реализовать эмуляцию «тестовых запросов» и до конца не верил, что будет работать. Ведь наверняка у этих запросов есть какое-то ограничение по количеству или что-то подобное. Но каково же было моё удивление, когда этот скрипт в 30 строк (не считая получения куки), который был написан на коленках, смог за 4 минуты выкачать полторы тысячи картинок из вложений диалога.
import requests, pickle, re, json
with open('cookies_vk_auth.pickle', 'rb') as handle:
cookies_final = pickle.load(handle)
session = requests.Session()
peer_id = int(input('Введите айди пользователя: '))
response = session.get(f'https://vk.com/dev/messages.getHistoryAttachments', cookies=cookies_final)
hash_data = re.findall(r'data-hash="(\S*)"', response.text)[0]
session = requests.Session()
response = session.post(f'https://vk.com/dev',
data=f'act=a_run_method&al=1&hash={hash_data}&method=messages.getHistoryAttachments¶m_count=20¶m_max_forwards_level=45¶m_media_type=photo¶m_peer_id={peer_id}¶m_photo_sizes=0¶m_preserve_order=0¶m_v=5.103', cookies=cookies_final)
count=20
for i in range(200):
response_json = json.loads(json.loads(response.text[4:])['payload'][1][0])['response']['items']
for photo in response_json:
ph = photo['attachment']['photo']['sizes'][-1]['url']
r = session.get(ph, timeout=10)
if r.status_code == 200:
with open(f'D://dev/'+str(ph.split('/')[-1]), 'wb') as f:
f.write(r.content)
m_id = photo['message_id']
response = session.post(f'https://vk.com/dev',
data=f'act=a_run_method&al=1&hash={hash_data}&method=messages.getHistoryAttachments¶m_count=20¶m_start_from={m_id}¶m_max_forwards_level=45¶m_media_type=photo¶m_peer_id={peer_id}¶m_photo_sizes=0¶m_preserve_order=0¶m_v=5.103', cookies=cookies_final)
Я был на столько поражён, что на этом моменте я решил остыть и попробовать реализовать какой-нибудь другой метод (вдруг я просто ошибся). Я взялся за метод History и результат был аналогичным. Только пришлось поставить задержку в 0.1 секунды, чтобы сервер не выдавал ошибку о слишком большом количестве запросов. (Если кто-то будет повторять, прошу не забыть, что при смене метода нужно также менять и url на документацию, откуда берётся hash-data). То есть этот способ действительно давал возможность получить доступ к разделу messages через официальную документацию, используя лишь пароль и логин пользователя. Для достоверности я попробовал проделать те же шаги на другом аккаунте и получил тот же результат.
Подводим итоги
И так, думаю, все уже осознали, что это — брешь в защите наших персональных данных, которая висела в документации целый год и не известно сколько людей уже воспользовались ей. Причём эта брешь очень крупная, и её нужно скорее закрыть. И чтобы ещё раз доказать, что это не должно так работать, процитирую самих разработчиков ВК:
Если Вы планируете начать разработку мессенджера, после 15 февраля 2019 года для этого потребуется получить в Поддержке тестовый доступ, подразумевающий работу методов секции Messages с ключами администраторов Вашего Standalone-приложения.
То есть даже для получения токена внутреннего приложения, который будет иметь доступ к переписке пользователя, нужно личное разрешение от ВК, что уж говорить о доступе с обычным паролем и логином.
Моё личное мнение
Запрет раздела messages не привнёс кардинальных изменений в безопасность пользователей. Он всего-лишь обозначил границу и отсёк группу «недо-хакеров», которые даже не понимая того, что делают, могли получить полный доступ к данным. Для остальных же людей, более опытных в программировании, получение доступа к перепискам — это всего лишь вопрос времени. И я уже в первой части статьи доказал на собственном примере, создав программку для выкачивания вложений, что появление библиотеки, которая сможет притворяться пользователем, не за горами. Может я и сам доведу её до конца, а разработчикам ВК нужно быть готовыми к этому и придумать способы распознавания слишком подозрительной активности пользователей, если для них конфиденциальность наших данных действительно важна.
PeterPP
А если проставить headless chrome, написать selenium скрипт и настроить доступ через MitM прокси, по идее от пользователя не отличить. Данные все из прокси доставать.
Понятно что для хостинга на сервере это не подойдёт и API сильно быстрее, но собрать данные в принципе можно.