http, пушистый с boofuzz
Я искал библиотеку фаззинга и случайно увидел "boofuzz", хотя нет примеров того, как использовать библиотеку для фаззинга http.
Это единственный код, который я вижу на их странице GitHub, но они говорят, что он был взят из Sulley (старая библиотека Fuzzing):
import sys
sys.path.insert(0, '../')
from boofuzz.primitives import String, Static, Delim
class Group(object):
blocks = []
def __init__(self, name, definition=None):
self.name = name
if definition:
self.definition = definition
def add_definition(self, definition):
assert isinstance(definition, (list, tuple)), "Definition must be a list or a tuple!"
self.definition = definition
def render(self):
return "".join([x.value for x in self.definition])
def exhaust(self):
for item in self.definition:
while item.mutate():
current_value = item.value
self.log_send(current_value)
recv_data = self.send_buffer(current_value)
self.log_recv(recv_data)
def __repr__(self):
return '<%s [%s items]>' % (self.__class__.__name__, len(self.definition))
# noinspection PyMethodMayBeStatic
def send_buffer(self, current_value):
return "Sent %s!" % current_value
def log_send(self, current_value):
pass
def log_recv(self, recv_data):
pass
s_static = Static
s_delim = Delim
s_string = String
CloseHeader = Group(
"HTTP Close Header",
definition=[
# GET / HTTP/1.1\r\n
s_static("GET / HTTP/1.1\r\n"),
# Connection: close
s_static("Connection"), s_delim(":"), s_delim(" "), s_string("close"),
s_static("\r\n\r\n")
]
)
OpenHeader = Group(
"HTTP Open Header",
definition=[
# GET / HTTP/1.1\r\n
Static("GET / HTTP/1.1\r\n"),
# Connection: close
Static("Connection"), Delim(":"), Delim(" "), String("open"),
Static("\r\n\r\n")
]
)
# CloseHeader = Group("HTTP Close Header")
# CloseHeader.add_definition([
# # GET / HTTP/1.1\r\n
# s_static("GET / HTTP/1.1\r\n"),
# # Connection: close
# s_static("Connection"), s_delim(":"), s_delim(" "), s_string("close"),
# s_static("\r\n\r\n")
# ])
Зачем им это публиковать, если это чужой библиотечный код? И есть ли хорошее объяснение того, как работать с библиотекой boofuzz?
1 ответ
Если вы пользуетесь Google "форматом протокола http", первым результатом будет этот учебник по HTTP. Если вы прочитаете там несколько страниц, вы можете получить довольно хорошее описание формата протокола. Исходя из этого, я написал следующий fuzz-скрипт, исходный код здесь:
#!/usr/bin/env python
# Designed for use with boofuzz v0.0.9
from boofuzz import *
def main():
session = Session(
target=Target(
connection=SocketConnection("127.0.0.1", 80, proto='tcp')
),
)
s_initialize(name="Request")
with s_block("Request-Line"):
s_group("Method", ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE'])
s_delim(" ", name='space-1')
s_string("/index.html", name='Request-URI')
s_delim(" ", name='space-2')
s_string('HTTP/1.1', name='HTTP-Version')
s_static("\r\n", name="Request-Line-CRLF")
s_static("\r\n", "Request-CRLF")
session.connect(s_get("Request"))
session.fuzz()
if __name__ == "__main__":
main()
Хотя меня на некоторое время споткнули, потому что у меня был только один CRLF. После проверки RFC 2616 (раздел 5) становится ясно, что этот пример должен заканчиваться двумя CRLF.
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
[...]
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Очевидно, что этот нечеткий скрипт не подходит для покрытия всего протокола. Несколько вещей, которые можно добавить:
- Заголовки HTTP (их много)
- Специализированные форматы для каждого метода HTTP
- Тело сообщения (например, на POST)
- Какой-то способ выбрать действительные URI для конкретного целевого сервера
- Сообщать о предупреждениях на основе ответа сервера (может быть шумно, но ошибки на сервере обычно указывают на... ошибки)