Repository: cowrie/cowrie

Issue:
Unable to curl or wget URL with hostname
If you try to download anything via curl or wget and url contains hostname not ip address it crashes.

I am pretty sure it is because of https://github.com/cowrie/cowrie/pull/1557/commits/0b3b257e0ecf10b5b4d381d724cf4c3e23f0ed81 and https://github.com/cowrie/cowrie/pull/1557/commits/ff6bfdcdb75fefbc35ac19fad7c98c0f69da48b7

Line:         # TODO: need to do full name resolution.


Example:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@czbrqobpvmssd01:~# wget notino.czConnection to czbrqobpvmssd01 closed by remote host.
Connection to czbrqobpvmssd01 closed.




2021-05-28T14:13:00.312387Z [HoneyPotSSHTransport,9,172.16.23.9] Unhandled Error
	Traceback (most recent call last):
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/python/log.py", line 101, in callWithLogger
	    return callWithContext({"system": lp}, func, *args, **kw)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/python/log.py", line 85, in callWithContext
	    return context.call({ILogContext: newCtx}, func, *args, **kw)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/python/context.py", line 118, in callWithContext
	    return self.currentContext().callWithContext(ctx, func, *args, **kw)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/python/context.py", line 83, in callWithContext
	    return func(*args, **kw)
	--- <exception caught here> ---
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/internet/posixbase.py", line 687, in _doReadOrWrite
	    why = selectable.doRead()
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/internet/tcp.py", line 246, in doRead
	    return self._dataReceived(data)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/internet/tcp.py", line 251, in _dataReceived
	    rval = self.protocol.dataReceived(data)
	  File "/home/cowrie/cowrie/src/cowrie/ssh/transport.py", line 141, in dataReceived
	    self.dispatchMessage(messageNum, packet[1:])
	  File "/home/cowrie/cowrie/src/cowrie/ssh/transport.py", line 145, in dispatchMessage
	    transport.SSHServerTransport.dispatchMessage(self, message_num, payload)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/ssh/transport.py", line 747, in dispatchMessage
	    self.service.packetReceived(messageNum, payload)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/ssh/service.py", line 47, in packetReceived
	    return f(packet)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/ssh/connection.py", line 265, in ssh_CHANNEL_DATA
	    channel.dataReceived(data)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/ssh/session.py", line 174, in dataReceived
	    self.client.transport.write(data)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/ssh/session.py", line 230, in write
	    self.proto.dataReceived(data)
	  File "/home/cowrie/cowrie/src/cowrie/insults/insults.py", line 125, in dataReceived
	    insults.ServerProtocol.dataReceived(self, data)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/insults/insults.py", line 520, in dataReceived
	    self.terminalProtocol.keystrokeReceived(ch, None)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/recvline.py", line 436, in keystrokeReceived
	    m()
	  File "/home/cowrie/cowrie/src/cowrie/shell/protocol.py", line 328, in handle_RETURN
	    return recvline.RecvLine.handle_RETURN(self)
	  File "/home/cowrie/cowrie/cowrie-env/lib64/python3.6/site-packages/twisted/conch/recvline.py", line 494, in handle_RETURN
	    self.lineReceived(line)
	  File "/home/cowrie/cowrie/src/cowrie/shell/protocol.py", line 189, in lineReceived
	    self.cmdstack[-1].lineReceived(line)
	  File "/home/cowrie/cowrie/src/cowrie/shell/honeypot.py", line 116, in lineReceived
	    self.runCommand()
	  File "/home/cowrie/cowrie/src/cowrie/shell/honeypot.py", line 325, in runCommand
	    self.protocol.call_command(pp, cmdclass, *cmd_array[0]["rargs"])
	  File "/home/cowrie/cowrie/src/cowrie/shell/protocol.py", line 309, in call_command
	    HoneyPotBaseProtocol.call_command(self, pp, cmd, *args)
	  File "/home/cowrie/cowrie/src/cowrie/shell/protocol.py", line 198, in call_command
	    obj.start()
	  File "/home/cowrie/cowrie/src/cowrie/commands/wget.py", line 122, in start
	    self.deferred = self.download(self.url, self.outfile)
	  File "/home/cowrie/cowrie/src/cowrie/commands/wget.py", line 157, in download
	    if ipaddress.ip_address(host).is_private:
	  File "/usr/lib64/python3.6/ipaddress.py", line 54, in ip_address
	    address)
	builtins.ValueError: 'notino.cz' does not appear to be an IPv4 or IPv6 address



Discussion:

Resolving patch:
diff --git a/src/cowrie/output/virustotal.py b/src/cowrie/output/virustotal.py
--- a/src/cowrie/output/virustotal.py
+++ b/src/cowrie/output/virustotal.py
@@ -65,6 +65,7 @@ class Output(cowrie.core.output.Output):
     agent: Any
     scan_url: bool
     scan_file: bool
+    url_cache: Dict[str, float] = {}  # url and last time succesfully submitted
 
     def start(self):
         """
@@ -293,6 +294,10 @@ def scanurl(self, entry):
         """
         Check url scan report for a hash
         """
+        if entry["url"] in self.url_cache:
+            log.msg("output_virustotal: url {} was already successfully submitted".format(entry["url"]))
+            return
+
         vtUrl = f"{VTAPI_URL}url/report".encode("utf8")
         headers = http_headers.Headers({"User-Agent": [COWRIE_USER_AGENT]})
         fields = {
@@ -341,13 +346,16 @@ def processResult(result):
             j = json.loads(result)
             log.msg("VT: {}".format(j["verbose_msg"]))
 
+            # we got a status=200 assume it was successfully submitted
+            self.url_cache[entry["url"]] = datetime.datetime.now()
+
             if j["response_code"] == 0:
                 log.msg(
                     eventid="cowrie.virustotal.scanurl",
                     format="VT: New URL %(url)s",
                     session=entry["session"],
                     url=entry["url"],
-                    is_new="true",
+                    is_new="true"
                 )
                 return d
             elif j["response_code"] == 1 and "scans" not in j:
@@ -377,7 +385,7 @@ def processResult(result):
                 )
                 log.msg("VT: permalink: {}".format(j["permalink"]))
             elif j["response_code"] == -2:
-                log.msg("VT: response=1: this has been queued for analysis already")
+                log.msg("VT: response=-2: this has been queued for analysis already")
                 log.msg("VT: permalink: {}".format(j["permalink"]))
             else:
                 log.msg("VT: unexpected response code: {}".format(j["response_code"]))


Test patch: