Найти - Пользователи
Полная версия: Декодирование перехваченных http пакетов
Начало » Python для экспертов » Декодирование перехваченных http пакетов
1 2 3 4
akolesnikov
Здравствуйте. Возникла необходимость перехвата http пакетов, проходящих через комп.

Первый вопрос. Возможно ли как-то ограничивать отправку запросов через интернет, т.е. создать что-то типа программной премодерации?

И второй. С простыми пакетами http вопросов нет - impacket и pcapy отлично все хватают. Но многие сайты используют gzip. Каким образом возможно декодировать такой пакет? zlib.decompress выдает ошибку

Прикрепить пример пакета не получается, выложу заголовки:
HTTP/1.1 200 OK
Date: Sat, 16 Oct 2010 14:03:43 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.3.2-1ubuntu4.5
X-Pingback: http://knigoff.net/xmlrpc.php
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20988
Keep-Alive: timeout=15, max=74
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
После заголовков начинается бинарщина (видимо тело запроса в gzipe).
Заранее спасибо.
Андрей Светлов
Первый вопрос совсем непонятен. Попробуйте задать его по другому.

Для работы с gzip используйте gzip.GzipFile.
В fileobj протолкните ваш StringIO с телом ответа.

Не путайтесь в терминологии. http - потоковый протокол. Запрос и ответ могут лежать в нескольких TCP пакетах. То, что вы назвали “пакетом” весь остальной мир зовет http response.
akolesnikov
Спасибо за корректировку. Попробую переформулировать.
Сниффер отлавливает запросы, но не ограничивает их передачу. Как реализовать скрипт, который будет проверять все запросы (грубо говоря, на наличие определенной строки внутри), и, в зависимости от результата, разрешать или запрещать передачу этого запроса? Файервол получается, что-ли.

А для gzip используем что-то типа этого?
query=gzip.GzipFile('', 'rb', 9, StringIO.StringIO(request))
Т.е.: считываем content-length, оставляем от запроса только конец длиной content-length, обрабатываем это gzip-ом (приведенный мною выше код). На выходе должны получить декодированный запрос. Так все?
Андрей Светлов
Именно что firewall (или http proxy) - и никак иначе.

Не нужно отступать от конца ответа. Нужно обрабатывать content-length байт с начала тело. Тело ответа идет после заголовков и двух CRLF.
А еще существует режим отдачи по chunk - он немного иначе кодируется.

Что-то, сдается, вы слишком уж замахнулись. Написать-то все можно - но сначала следует хорошо изучить основы.
akolesnikov
Да, вы правы. Никогда прежде не работал с http на таком уровне. Для проекта необходимо мониторить сетевую активность и запоминать подозрительные запросы. К сожалению, сходу не смог найти в гугле подходящую справочную информацию.
Про chunk читал, пока это не первоочередная задача. Гораздо важнее разобраться с gzip.
Подскажите, пожалуйста. Что-то не получается. Получаю ответ сервера таким образом (сократил ненужное):

def decodePayload(payload): 
decoder = Decoders.EthDecoder()
eth = decoder.decode(payload)
ip = eth.child()
tcp = ip.child()
try:
if tcp.get_RST()!=1:
data = tcp.get_data_as_string()
return data
else:
return None
except:
return None

def calculate(query):
query=gzip.GzipFile('', 'rb', 9, StringIO.StringIO(query))
query=query.read()
print query

keyword="Content-Type: text/html"
cap = pcapy.open_live('wlan0', 10000000, 1, 0)
cap.setfilter('tcp')
(header, payload) = cap.next()
while header:
decoder = Decoders.EthDecoder()
eth = decoder.decode(payload)
if keyword in eth.get_packet():
result=decodePayload(payload)
if result:
calculate(result)
(header, payload) = cap.next()
При этом я пробовал и как вы говорили, т.е. весь query декодировать gzip'ом, и так, как я писал вначале - брать только конец длиной content-length. Все приводит к “IOError: Not a gzipped file”.
К чему я отрезаю кусок с конца: ведь вначале идут всякие заголовки ответа сервера (“HTTP/1.1 200 OK, Server: nginx/0.7.67” и т.д.). При отрезании остается точно нужная часть - то, что после заголовков.

PS. zlib.decompress(packet) также выдает “zlib.error: Error -3 while decompressing data: incorrect header check”
zheromo
я делаю так - все работает

f = StringIO(body)
gzip_f = GzipFile(filename='', mode='r', fileobj=f)
new_body = gzip_f.read()
gzip_f.close()
f.close()
akolesnikov
zheromo
я делаю так - все работает

f = StringIO(body)
gzip_f = GzipFile(filename='', mode='r', fileobj=f)
new_body = gzip_f.read()
gzip_f.close()
f.close()
Приведенный вами пример идентичен моему примеру.

Я так понимаю, я неправильно получаю само тело ответа http, поэтому и ошибки.
zheromo
akolesnikov
zheromo
я делаю так - все работает

f = StringIO(body)
gzip_f = GzipFile(filename='', mode='r', fileobj=f)
new_body = gzip_f.read()
gzip_f.close()
f.close()
Приведенный вами пример идентичен моему примеру.

Я так понимаю, я неправильно получаю само тело ответа http, поэтому и ошибки.
Попробуйте так
data = body.split('\n\n',1)[1]
Некторые сервера не изменяют Content-Length после упаковки, т.е. стоит размер распакованных данных
а так будет по стандарту - пустая строка завершает список хидеров
zheromo
Еще можно посмотреть в сторону Zorp - это модульный фаервол с анализатором различных протоколов, причем модули и прочее пишутся на Питоне.
akolesnikov
zheromo
спасибо. Ваш пример тоже не помогает - “Not a gzipped file” (само собой, в хидере есть “Content-Encoding: gzip”

Приведите, пожалуйста, рабочий элементарный пример декодирования gzip'ом перехваченного http ответа.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB