{"action":"opened","number":890,"pull_request":{"url":"https://api.github.com/repos/EmpireProject/Empire/pulls/890","id":160345632,"html_url":"https://github.com/EmpireProject/Empire/pull/890","diff_url":"https://github.com/EmpireProject/Empire/pull/890.diff","patch_url":"https://github.com/EmpireProject/Empire/pull/890.patch","issue_url":"https://api.github.com/repos/EmpireProject/Empire/issues/890","number":890,"state":"open","locked":false,"title":"http Listener now evades Nessus plugin 99592","user":{"login":"s0lst1c3","id":5394955,"avatar_url":"https://avatars3.githubusercontent.com/u/5394955?v=4","gravatar_id":"","url":"https://api.github.com/users/s0lst1c3","html_url":"https://github.com/s0lst1c3","followers_url":"https://api.github.com/users/s0lst1c3/followers","following_url":"https://api.github.com/users/s0lst1c3/following{/other_user}","gists_url":"https://api.github.com/users/s0lst1c3/gists{/gist_id}","starred_url":"https://api.github.com/users/s0lst1c3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s0lst1c3/subscriptions","organizations_url":"https://api.github.com/users/s0lst1c3/orgs","repos_url":"https://api.github.com/users/s0lst1c3/repos","events_url":"https://api.github.com/users/s0lst1c3/events{/privacy}","received_events_url":"https://api.github.com/users/s0lst1c3/received_events","type":"User","site_admin":false},"body":"About a month ago, Tenable released a Nessus plugin for identifying Empire http listeners. Since the plugin uses signature-based methods, I figured it wouldn’t be terribly difficult to evade. \r\n\r\nTenable also released a blog post that describes how the plugin works and how the signature is constructed. It’s actually a pretty interesting read (link included below), but I’ll do my best to give you the _tl;dr_ version as well.\r\n\r\n__Blog Post:__\r\n[https://www.tenable.com/blog/identifying-empire-http-listeners](https://www.tenable.com/blog/identifying-empire-http-listeners)\r\n\r\n__Nessus Plugin 99592:__\r\nhttps://www.tenable.com/plugins/index.php?view=single&id=99592\r\n\r\n## Summary of the Issue\r\n\r\nTenable's blog post states that while “a lot of work has gone into making agents difficult to find . . . less has been done to hide listeners.”\r\n\r\nThe blog post then demonstrates that the following attributes can be used to create a signature for the Empire http Listener:\r\n\r\n- The 404 page uses hardcoded Werkzeug error message\r\n- The 404 page is always 233 bytes\r\n- Content for most 200 responses is a hardcoded default page\r\n- Empire uses atypical cache-control headers\r\n- Making a request to the _/_ route always results in a 404 response, while making a request to any other route results in a 200 response and hardcoded default page.\r\n\r\nThe last point is particularly interesting. There is no route defined for _/_. This means that anytime a user makes a request to _/_, he or she gets the hardcoded Werkzeug 404 response as shown in the console output below.\r\n\r\n```\r\n┌─[root@somberlain] - [~/Empire/lib/listeners] - [8550]\r\n└─[$] curl -i http://10.10.10.100/\r\nHTTP/1.0 404 NOT FOUND\r\nContent-Type: text/html\r\nContent-Length: 233\r\nCache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: 0\r\nServer: Microsoft-IIS/7.5\r\nDate: Thu, 28 Dec 2017 05:06:07 GMT\r\n\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\r\n<title>404 Not Found</title>\r\n<h1>Not Found</h1>\r\n<p>The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.</p>\r\n```\r\n\r\nOn the other hand, making a request to any other route (including /index.html) results in a 200 response containing a hardcoded default page.\r\n\r\n```\r\n┌─[root@somberlein] - [~/Empire/lib/listeners] - [8551]\r\n└─[$] curl -i http://10.10.10.100/asdfasdfasdf                                                             [23:06:07]\r\nHTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 173\r\nCache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: 0\r\nServer: Microsoft-IIS/7.5\r\nDate: Thu, 28 Dec 2017 05:07:16 GMT\r\n\r\n<html><body><h1>It works!</h1><p>This is the default web page for this server.</p><p>The web server software is running but no content has been added, yet.</p></body></html>\r\n```\r\n\r\nThis behavior really makes the Empire http Listener stand out, since most production servers would do the opposite (_/_ and  /index.html would result in a default page, /* would result in a 404 error).\r\n\r\n## Fixing the Problem\r\n\r\nI was able to evade the signature based detections used by the Nessus plugin by adding the following enhancements to the http Listener:\r\n\r\n- The http Listener behaves more like a “real” web server (which makes its signature more generic)\r\n- The Content-Length for default and error pages is now randomly set on startup\r\n\r\nTo make the http Listener seem more like a generic web server, I first added a route for / and /index.html. When users make a request to either of these routes, they are presented with a 200 response containing the default index page for IIS 7.5.\r\n\r\n![empire-iis-index](https://user-images.githubusercontent.com/5394955/34403112-31ca2e8c-eb74-11e7-90bd-abd3fec9669d.png)\r\n\r\nHowever, when users attempt to access any route other than / or /index.html, they are now presented with a generic IIS 404 page.\r\n\r\n![empire-listener-404-page](https://user-images.githubusercontent.com/5394955/34403121-48e7c4c6-eb74-11e7-9808-8184e9882291.png)\r\n\r\nThis makes the http Listener behave identically to a generic IIS server, and eliminates easily identifiable hardcoded content (such as the Werkzeug 404 text).\r\n\r\nTo make it difficult to fingerprint the http Listener based on Content-Length, we simply append a whitespace buffer to the end of the index and 404 pages. The length of this whitespace buffer is randomly generated on startup but consistent across all requests.\r\n\r\nI decided not to do anything about the cache-control headers, since cache-control headers vary enough across websites to make doing so unnecessary.\r\n\r\n## Results\r\n\r\nAside from running basic unit tests on my code, I also made sure that the enhancements do an adequate job of evading the Nessus plugin. The results are shown below.\r\n\r\nIn the following screenshot, we perform a Nessus scan using plugin 99592 against a host running an Empire http Listener. As you can see, the plugin detects the http Listener.\r\n\r\n![empire-nessus-before](https://user-images.githubusercontent.com/5394955/34403161-94be42d0-eb74-11e7-8eb9-179c84d2e063.png)\r\n\r\nNext, we perform the same Nessus scan, but this time against a host running the enhanced Empire http Listener. Notice how the enhancements allow the Listener to successfully avoid detection. \r\n\r\n![nessus-plugin-after](https://user-images.githubusercontent.com/5394955/34403438-3fe318ce-eb76-11e7-8466-c1c9de85d158.png)\r\n\r\n","created_at":"2017-12-28T07:25:32Z","updated_at":"2017-12-28T07:25:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/EmpireProject/Empire/pulls/890/commits","review_comments_url":"https://api.github.com/repos/EmpireProject/Empire/pulls/890/comments","review_comment_url":"https://api.github.com/repos/EmpireProject/Empire/pulls/comments{/number}","comments_url":"https://api.github.com/repos/EmpireProject/Empire/issues/890/comments","statuses_url":"https://api.github.com/repos/EmpireProject/Empire/statuses/8c4f7c613ef116df7a18947c9b13f8739c77fd64","head":{"label":"s0lst1c3:dev","ref":"dev","sha":"8c4f7c613ef116df7a18947c9b13f8739c77fd64","user":{"login":"s0lst1c3","id":5394955,"avatar_url":"https://avatars3.githubusercontent.com/u/5394955?v=4","gravatar_id":"","url":"https://api.github.com/users/s0lst1c3","html_url":"https://github.com/s0lst1c3","followers_url":"https://api.github.com/users/s0lst1c3/followers","following_url":"https://api.github.com/users/s0lst1c3/following{/other_user}","gists_url":"https://api.github.com/users/s0lst1c3/gists{/gist_id}","starred_url":"https://api.github.com/users/s0lst1c3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s0lst1c3/subscriptions","organizations_url":"https://api.github.com/users/s0lst1c3/orgs","repos_url":"https://api.github.com/users/s0lst1c3/repos","events_url":"https://api.github.com/users/s0lst1c3/events{/privacy}","received_events_url":"https://api.github.com/users/s0lst1c3/received_events","type":"User","site_admin":false},"repo":{"id":115593740,"name":"Empire","full_name":"s0lst1c3/Empire","owner":{"login":"s0lst1c3","id":5394955,"avatar_url":"https://avatars3.githubusercontent.com/u/5394955?v=4","gravatar_id":"","url":"https://api.github.com/users/s0lst1c3","html_url":"https://github.com/s0lst1c3","followers_url":"https://api.github.com/users/s0lst1c3/followers","following_url":"https://api.github.com/users/s0lst1c3/following{/other_user}","gists_url":"https://api.github.com/users/s0lst1c3/gists{/gist_id}","starred_url":"https://api.github.com/users/s0lst1c3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/s0lst1c3/subscriptions","organizations_url":"https://api.github.com/users/s0lst1c3/orgs","repos_url":"https://api.github.com/users/s0lst1c3/repos","events_url":"https://api.github.com/users/s0lst1c3/events{/privacy}","received_events_url":"https://api.github.com/users/s0lst1c3/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/s0lst1c3/Empire","description":"Empire is a PowerShell and Python post-exploitation agent.","fork":true,"url":"https://api.github.com/repos/s0lst1c3/Empire","forks_url":"https://api.github.com/repos/s0lst1c3/Empire/forks","keys_url":"https://api.github.com/repos/s0lst1c3/Empire/keys{/key_id}","collaborators_url":"https://api.github.com/repos/s0lst1c3/Empire/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/s0lst1c3/Empire/teams","hooks_url":"https://api.github.com/repos/s0lst1c3/Empire/hooks","issue_events_url":"https://api.github.com/repos/s0lst1c3/Empire/issues/events{/number}","events_url":"https://api.github.com/repos/s0lst1c3/Empire/events","assignees_url":"https://api.github.com/repos/s0lst1c3/Empire/assignees{/user}","branches_url":"https://api.github.com/repos/s0lst1c3/Empire/branches{/branch}","tags_url":"https://api.github.com/repos/s0lst1c3/Empire/tags","blobs_url":"https://api.github.com/repos/s0lst1c3/Empire/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/s0lst1c3/Empire/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/s0lst1c3/Empire/git/refs{/sha}","trees_url":"https://api.github.com/repos/s0lst1c3/Empire/git/trees{/sha}","statuses_url":"https://api.github.com/repos/s0lst1c3/Empire/statuses/{sha}","languages_url":"https://api.github.com/repos/s0lst1c3/Empire/languages","stargazers_url":"https://api.github.com/repos/s0lst1c3/Empire/stargazers","contributors_url":"https://api.github.com/repos/s0lst1c3/Empire/contributors","subscribers_url":"https://api.github.com/repos/s0lst1c3/Empire/subscribers","subscription_url":"https://api.github.com/repos/s0lst1c3/Empire/subscription","commits_url":"https://api.github.com/repos/s0lst1c3/Empire/commits{/sha}","git_commits_url":"https://api.github.com/repos/s0lst1c3/Empire/git/commits{/sha}","comments_url":"https://api.github.com/repos/s0lst1c3/Empire/comments{/number}","issue_comment_url":"https://api.github.com/repos/s0lst1c3/Empire/issues/comments{/number}","contents_url":"https://api.github.com/repos/s0lst1c3/Empire/contents/{+path}","compare_url":"https://api.github.com/repos/s0lst1c3/Empire/compare/{base}...{head}","merges_url":"https://api.github.com/repos/s0lst1c3/Empire/merges","archive_url":"https://api.github.com/repos/s0lst1c3/Empire/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/s0lst1c3/Empire/downloads","issues_url":"https://api.github.com/repos/s0lst1c3/Empire/issues{/number}","pulls_url":"https://api.github.com/repos/s0lst1c3/Empire/pulls{/number}","milestones_url":"https://api.github.com/repos/s0lst1c3/Empire/milestones{/number}","notifications_url":"https://api.github.com/repos/s0lst1c3/Empire/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/s0lst1c3/Empire/labels{/name}","releases_url":"https://api.github.com/repos/s0lst1c3/Empire/releases{/id}","deployments_url":"https://api.github.com/repos/s0lst1c3/Empire/deployments","created_at":"2017-12-28T06:41:15Z","updated_at":"2017-12-28T06:41:19Z","pushed_at":"2017-12-28T06:50:53Z","git_url":"git://github.com/s0lst1c3/Empire.git","ssh_url":"git@github.com:s0lst1c3/Empire.git","clone_url":"https://github.com/s0lst1c3/Empire.git","svn_url":"https://github.com/s0lst1c3/Empire","homepage":"http://www.powershellempire.com/","size":19654,"stargazers_count":0,"watchers_count":0,"language":"PowerShell","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"EmpireProject:dev","ref":"dev","sha":"1781f20856bd21b56a9d5ccbd788e92723d64a05","user":{"login":"EmpireProject","id":25492515,"avatar_url":"https://avatars3.githubusercontent.com/u/25492515?v=4","gravatar_id":"","url":"https://api.github.com/users/EmpireProject","html_url":"https://github.com/EmpireProject","followers_url":"https://api.github.com/users/EmpireProject/followers","following_url":"https://api.github.com/users/EmpireProject/following{/other_user}","gists_url":"https://api.github.com/users/EmpireProject/gists{/gist_id}","starred_url":"https://api.github.com/users/EmpireProject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EmpireProject/subscriptions","organizations_url":"https://api.github.com/users/EmpireProject/orgs","repos_url":"https://api.github.com/users/EmpireProject/repos","events_url":"https://api.github.com/users/EmpireProject/events{/privacy}","received_events_url":"https://api.github.com/users/EmpireProject/received_events","type":"Organization","site_admin":false},"repo":{"id":40262072,"name":"Empire","full_name":"EmpireProject/Empire","owner":{"login":"EmpireProject","id":25492515,"avatar_url":"https://avatars3.githubusercontent.com/u/25492515?v=4","gravatar_id":"","url":"https://api.github.com/users/EmpireProject","html_url":"https://github.com/EmpireProject","followers_url":"https://api.github.com/users/EmpireProject/followers","following_url":"https://api.github.com/users/EmpireProject/following{/other_user}","gists_url":"https://api.github.com/users/EmpireProject/gists{/gist_id}","starred_url":"https://api.github.com/users/EmpireProject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EmpireProject/subscriptions","organizations_url":"https://api.github.com/users/EmpireProject/orgs","repos_url":"https://api.github.com/users/EmpireProject/repos","events_url":"https://api.github.com/users/EmpireProject/events{/privacy}","received_events_url":"https://api.github.com/users/EmpireProject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/EmpireProject/Empire","description":"Empire is a PowerShell and Python post-exploitation agent.","fork":false,"url":"https://api.github.com/repos/EmpireProject/Empire","forks_url":"https://api.github.com/repos/EmpireProject/Empire/forks","keys_url":"https://api.github.com/repos/EmpireProject/Empire/keys{/key_id}","collaborators_url":"https://api.github.com/repos/EmpireProject/Empire/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/EmpireProject/Empire/teams","hooks_url":"https://api.github.com/repos/EmpireProject/Empire/hooks","issue_events_url":"https://api.github.com/repos/EmpireProject/Empire/issues/events{/number}","events_url":"https://api.github.com/repos/EmpireProject/Empire/events","assignees_url":"https://api.github.com/repos/EmpireProject/Empire/assignees{/user}","branches_url":"https://api.github.com/repos/EmpireProject/Empire/branches{/branch}","tags_url":"https://api.github.com/repos/EmpireProject/Empire/tags","blobs_url":"https://api.github.com/repos/EmpireProject/Empire/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/EmpireProject/Empire/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/EmpireProject/Empire/git/refs{/sha}","trees_url":"https://api.github.com/repos/EmpireProject/Empire/git/trees{/sha}","statuses_url":"https://api.github.com/repos/EmpireProject/Empire/statuses/{sha}","languages_url":"https://api.github.com/repos/EmpireProject/Empire/languages","stargazers_url":"https://api.github.com/repos/EmpireProject/Empire/stargazers","contributors_url":"https://api.github.com/repos/EmpireProject/Empire/contributors","subscribers_url":"https://api.github.com/repos/EmpireProject/Empire/subscribers","subscription_url":"https://api.github.com/repos/EmpireProject/Empire/subscription","commits_url":"https://api.github.com/repos/EmpireProject/Empire/commits{/sha}","git_commits_url":"https://api.github.com/repos/EmpireProject/Empire/git/commits{/sha}","comments_url":"https://api.github.com/repos/EmpireProject/Empire/comments{/number}","issue_comment_url":"https://api.github.com/repos/EmpireProject/Empire/issues/comments{/number}","contents_url":"https://api.github.com/repos/EmpireProject/Empire/contents/{+path}","compare_url":"https://api.github.com/repos/EmpireProject/Empire/compare/{base}...{head}","merges_url":"https://api.github.com/repos/EmpireProject/Empire/merges","archive_url":"https://api.github.com/repos/EmpireProject/Empire/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/EmpireProject/Empire/downloads","issues_url":"https://api.github.com/repos/EmpireProject/Empire/issues{/number}","pulls_url":"https://api.github.com/repos/EmpireProject/Empire/pulls{/number}","milestones_url":"https://api.github.com/repos/EmpireProject/Empire/milestones{/number}","notifications_url":"https://api.github.com/repos/EmpireProject/Empire/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/EmpireProject/Empire/labels{/name}","releases_url":"https://api.github.com/repos/EmpireProject/Empire/releases{/id}","deployments_url":"https://api.github.com/repos/EmpireProject/Empire/deployments","created_at":"2015-08-05T18:25:57Z","updated_at":"2017-12-28T07:05:10Z","pushed_at":"2017-12-28T03:49:30Z","git_url":"git://github.com/EmpireProject/Empire.git","ssh_url":"git@github.com:EmpireProject/Empire.git","clone_url":"https://github.com/EmpireProject/Empire.git","svn_url":"https://github.com/EmpireProject/Empire","homepage":"http://www.powershellempire.com/","size":19654,"stargazers_count":2517,"watchers_count":2517,"language":"PowerShell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":889,"mirror_url":null,"archived":false,"open_issues_count":13,"license":{"key":"bsd-3-clause","name":"BSD 3-clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":889,"open_issues":13,"watchers":2517,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/EmpireProject/Empire/pulls/890"},"html":{"href":"https://github.com/EmpireProject/Empire/pull/890"},"issue":{"href":"https://api.github.com/repos/EmpireProject/Empire/issues/890"},"comments":{"href":"https://api.github.com/repos/EmpireProject/Empire/issues/890/comments"},"review_comments":{"href":"https://api.github.com/repos/EmpireProject/Empire/pulls/890/comments"},"review_comment":{"href":"https://api.github.com/repos/EmpireProject/Empire/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/EmpireProject/Empire/pulls/890/commits"},"statuses":{"href":"https://api.github.com/repos/EmpireProject/Empire/statuses/8c4f7c613ef116df7a18947c9b13f8739c77fd64"}},"author_association":"NONE","merged":false,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"maintainer_can_modify":true,"commits":1,"additions":104,"deletions":18,"changed_files":2}}
{"actor":{"display_login":"s0lst1c3"}}