Repository: cowrie/cowrie

Issue:
`curl` prints errors to honeypot attacker
**Describe the bug**
When using the command 'curl canhazip.com' inside the honeypot, rather than working the shell instead throws a Python exception:
```
'NoneType' object has no attribute 'strip'
```

**To Reproduce**
Steps to reproduce the behavior:
1. Use Cowrie 1.5.2, 1.9.7, or v2.0.0
2. Connect using an account/password which provides an emulated shell
3. enter the command `curl canhazip.com`
This output is produced:
```
root@server:~# curl
curl: try 'curl --help' or 'curl --manual' for more information
root@server:~# curl http://canhazip.com
'NoneType' object has no attribute 'strip'
root@server:~# curl canhazip.com
'NoneType' object has no attribute 'strip'
```
**Expected behavior**
I would expect that the public IP address of the honeypot be returned.

**Server (please complete the following information):**
 - OS: 
 - Python: [e.g. Python 3.6.6, output of python -V]

**Additional context**
Seems like the issue may be here: https://github.com/cowrie/cowrie/blob/bf422e424c683cffef883243ac50ff1afbcff51c/src/cowrie/commands/curl.py#L50



Discussion:
I added self.write commands around both usages of "strip" in that file and neither appears to be the culprit. Something in handling the URL perhaps?
The problem is line 328 
```        self.write(error)```
This prints the error to the end user. This should obviously be fixed :)
The actual `strip` error his here in shell/fs.py

```
2019-10-30T15:37:59.094869Z [twisted.python.log#error] Traceback (most recent call last):
2019-10-30T15:37:59.095219Z [twisted.python.log#error]   File "/Users/michel/src/cowrie-env/lib/python3.7/site-packages/twisted/internet/tcp.
py", line 327, in connectionLost
2019-10-30T15:37:59.095913Z [twisted.python.log#error]     protocol.connectionLost(reason)
2019-10-30T15:37:59.096223Z [twisted.python.log#error]   File "/Users/michel/src/cowrie-env/lib/python3.7/site-packages/twisted/web/client.py", line 229, in connectionLost
2019-10-30T15:37:59.098157Z [twisted.python.log#error]     self.factory._disconnectedDeferred.callback(None)
2019-10-30T15:37:59.098555Z [twisted.python.log#error]   File "/Users/michel/src/cowrie-env/lib/python3.7/site-packages/twisted/internet/defer.py", line 460, in callback
2019-10-30T15:37:59.099354Z [twisted.python.log#error]     self._startRunCallbacks(result)
2019-10-30T15:37:59.099685Z [twisted.python.log#error]   File "/Users/michel/src/cowrie-env/lib/python3.7/site-packages/twisted/internet/defer.py", line 568, in _startRunCallbacks
2019-10-30T15:37:59.099970Z [twisted.python.log#error]     self._runCallbacks()
2019-10-30T15:37:59.100251Z [twisted.python.log#error] --- <exception caught here> ---
2019-10-30T15:37:59.100527Z [twisted.python.log#error]   File "/Users/michel/src/cowrie-env/lib/python3.7/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
2019-10-30T15:37:59.100803Z [twisted.python.log#error]     current.result = callback(current.result, *args, **kw)
2019-10-30T15:37:59.101076Z [twisted.python.log#error]   File "/Users/michel/src/cowrie/src/cowrie/commands/curl.py", line 319, in success
2019-10-30T15:37:59.101516Z [twisted.python.log#error]     self.fs.update_realfile(self.fs.getfile(outfile), hashPath)
2019-10-30T15:37:59.101808Z [twisted.python.log#error]   File "/Users/michel/src/cowrie/src/cowrie/shell/fs.py", line 221, in getfile
2019-10-30T15:37:59.102701Z [twisted.python.log#error]     pieces = path.strip('/').split('/')
2019-10-30T15:37:59.103045Z [twisted.python.log#error] builtins.AttributeError: 'NoneType' object has no attribute 'strip'```

Resolving patch:
diff --git a/src/cowrie/commands/curl.py b/src/cowrie/commands/curl.py
--- a/src/cowrie/commands/curl.py
+++ b/src/cowrie/commands/curl.py
@@ -309,23 +309,22 @@ def success(self, data, outfile):
                                   shasum=shasum,
                                   destfile=self.safeoutfile)
 
-        # Link friendly name to hash
-        # os.symlink(shasum, self.safeoutfile)
-
-        # FIXME: is this necessary?
-        # self.safeoutfile = hashPath
-
-        # Update the honeyfs to point to downloaded file
-        self.fs.update_realfile(self.fs.getfile(outfile), hashPath)
-        self.fs.chown(outfile, self.protocol.user.uid, self.protocol.user.gid)
+        # Update the honeyfs to point to downloaded file if output is a file
+        if outfile:
+            self.fs.update_realfile(self.fs.getfile(outfile), hashPath)
+            self.fs.chown(outfile, self.protocol.user.uid, self.protocol.user.gid)
+        else:
+            with open(hashPath, 'rb') as f:
+                self.writeBytes(f.read())
 
         self.exit()
 
     def error(self, error, url):
 
+        log.msg(error.printTraceback())
         if hasattr(error, 'getErrorMessage'):  # Exceptions
-            error = error.getErrorMessage()
-        self.write(error)
+            errormsg = error.getErrorMessage()
+        log.msg(errormsg)
         self.write('\n')
         self.protocol.logDispatch(eventid='cowrie.session.file_download.failed',
                                   format='Attempt to download file(s) from URL (%(url)s) failed',


Test patch: