-
Notifications
You must be signed in to change notification settings - Fork 380
New CLI arguments and experimental code coverage #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 16 commits
0d110de
845b039
54772b1
164f7d8
6011f9e
f0465d4
982a12a
33a7800
579cb75
4503e31
75b6ab2
81f660c
f1825f3
9426465
de3ed7d
68ad063
44baaa3
33fe390
0f77469
366326b
dceeac7
5239677
b04709f
be17dd3
44c2f40
5a3d362
0da9d85
68de3c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,18 +21,32 @@ class TCPSocketConnection(base_socket_connection.BaseSocketConnection): | |||||
| send_timeout (float): Seconds to wait for send before timing out. Default 5.0. | ||||||
| recv_timeout (float): Seconds to wait for recv before timing out. Default 5.0. | ||||||
| server (bool): Set to True to enable server side fuzzing. | ||||||
| graceful_shutdown (bool): close() method attempts a graceful shutdown. Default: True. | ||||||
|
|
||||||
| """ | ||||||
|
|
||||||
| def __init__(self, host, port, send_timeout=5.0, recv_timeout=5.0, server=False): | ||||||
| def __init__(self, host, port, send_timeout=5.0, recv_timeout=5.0, server=False, graceful_shutdown=True): | ||||||
| super(TCPSocketConnection, self).__init__(send_timeout, recv_timeout) | ||||||
|
|
||||||
| self.host = host | ||||||
| self.port = port | ||||||
| self.server = server | ||||||
| self._serverSock = None | ||||||
| self.graceful_shutdown = graceful_shutdown | ||||||
|
|
||||||
| def close(self): | ||||||
| if self.graceful_shutdown: | ||||||
| try: | ||||||
| self._sock.shutdown(socket.SHUT_RDWR) | ||||||
| while len(self._sock.recv(1024)) > 0: | ||||||
| pass | ||||||
| except ConnectionError: | ||||||
|
SR4ven marked this conversation as resolved.
|
||||||
| pass | ||||||
| except OSError as e: | ||||||
| if e.errno == errno.ENOTCONN: | ||||||
| pass | ||||||
| else: | ||||||
| raise | ||||||
| super(TCPSocketConnection, self).close() | ||||||
|
|
||||||
| if self.server: | ||||||
|
|
@@ -84,18 +98,25 @@ def _connect_socket(self): | |||||
|
|
||||||
| def recv(self, max_bytes): | ||||||
| """ | ||||||
| Receive up to max_bytes data from the target. | ||||||
| Receive up to max_bytes data from the target. Timeout results in 0 bytes returned. | ||||||
|
|
||||||
| Args: | ||||||
| max_bytes (int): Maximum number of bytes to receive. | ||||||
|
|
||||||
| Returns: | ||||||
| Received data. | ||||||
| Received data (empty bytes array if timed out). | ||||||
|
|
||||||
| Raises: | ||||||
| BoofuzzTargetConnectionShutdown: Target shutdown connection (e.g. socket recv returns 0 bytes) | ||||||
| BoofuzzTargetConnectionAborted: ECONNABORTED | ||||||
| BoofuzzTargetConnectionReset: ECONNRESET, ENETRESET, ETIMEDOUT | ||||||
| """ | ||||||
| data = b"" | ||||||
|
|
||||||
| try: | ||||||
| data = self._sock.recv(max_bytes) | ||||||
| if len(data) == 0: | ||||||
| raise exception.BoofuzzTargetConnectionShutdown() | ||||||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While working with boofuzz, I realized that the past design choice to return My solution was to throw an exception to indicate the socket has shut down, which is more intuitive to me personally. However, this actually flips the semantics of Either way, we have some choice to make:
Edit: This change seems to be where the test failures are coming from.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the other hand, I don't know how many scripts out there would actually hit this compatibility problem.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps one tool to compare with is pwntools, which also has a recv method for which timeout returns an empty bytes, and a closed connection yields an exception: https://docs.pwntools.com/en/stable/tubes.html#pwnlib.tubes.tube.tube.recv
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm difficult choice. The default posix way would be choice 2 if I understand correctly. Raise socket.timeout and return b"" on close. However, as we are on application level I could also imagine raising an exception for both cases. Not sure what others think about this but it might be the most user friendly. You simply tell boofuzz to receive after a test case and if anything goes wrong (close/timeout/abort/reset) you get an exception. I also just found the session option Right now I favour choice 2 as anyone with basic knowledge about sockets will understand what's going on. Also it looks like that approach could easily be adapted to the current BTW how can we get EWOULDBLOCK if we use a blocking socket and catch socket.timeout before?
And why do we interpret ETIMEDOUT as BoofuzzTargetConnectionReset?
Edit: I wouldn't worry about breaking backwards compatibility. As you already said I doubt that many scripts use the boofuzz socket interface directly and rely on this specific behaviour.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, that Session option is a layer on top of the socket behavior. The only place in my scripts this would matter is in callbacks, where I sometimes have code set up to receive the next (typically valid) message. Whatever choice we make here, we can modify Session to still act the same way with
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trying to get all these options clear in my head: Part of me wants to yield an exception in both cases. I'm leaning toward matching OS socket behavior, but that behavior is a bit counterintuitive.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The table seems to be correct. Agreed, I feel exactly the same way. I think if you have worked with sockets before, the OS socket behaviour is more intuitive.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which timeout/shutdown behaviour are we going to use now? The one initially proposed in this PR or the OS like?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SR4ven The OS-like behavior. Just realized I didn't add the timeout exception though...
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright. We don't need BoofuzzTargetConnectionShutdown anymore do we. Also, do we need to adapt other connection classes to the new behaviour? UDP maybe? |
||||||
| except socket.timeout: | ||||||
| data = b"" | ||||||
| except socket.error as e: | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.