rsmusllp / king-phisher

Phishing Campaign Toolkit
BSD 3-Clause "New" or "Revised" License
2.23k stars 538 forks source link

Csrf not working properly #124

Closed Zarcolio closed 8 years ago

Zarcolio commented 8 years ago

Issue Description

When I try to use the CSRF functionality, I get a 404 error and UndefinedError 'dict object' has no attribute 'username'

Reproduction Steps

  1. Create 2 pages: (1) index.html ( http://13.74.186.137 ): containing <form action="redirect.html"> (2) redirect.html: containing: {% do request.parameters.update({ 'j_username': request.parameters['username'], 'j_password': request.parameters['password'] }) %} {{ make_csrf_page('https://fqdn.nextpage.com', request.parameters) }}
  2. enter fake email address + password in index.html and submit

    Environment Details

Linux kingphisher2 4.4.0-24-generic 43-Ubuntu SMP Wed Jun 8 19:27:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux.

Error Details / Stack Trace

/var/log/king-phisher.log:

2016-06-15 19:12:39,776 AdvancedHTTPServer ERROR jinja2 template /var/www/redirect.html render failed: UndefinedError 'dict object' has no attribute 'username'

And in the browser a 404 is given:

Error 404: Page Not Found Sorry, the page you were looking for doesn't exist.

Am I doing something wrong or is this a bug?

Love the tool btw :D

wolfthefallen commented 8 years ago

Ocraz,

Looks like you have the CSRF function set up correctly. This issue is more then likely in your landing page. Make sure that the username and password fields variable names are "username" and "password" ( Harvesting Creds ). Then have the submit function refresh to the CSRF page. This way the King Phisher server records the necessary data to preform the CSRF prior to posting the request to the target server.

My recommendation is to set the refresh to a blank page currently, and send yourself a test email to see if the username and password is getting captured into your King Phisher data base.

Zarcolio commented 8 years ago

Thanks for your answer! It seems an apology is in order: I did it correctly in the first place, but after trying some stuff, I accidentally left the incorrect names for the input types. However, after changing it back, I get:

Exception happened during processing of request from ('aa.bb.cc.dd', 13606) Traceback (most recent call last): File "/usr/lib/python2.7/SocketServer.py", line 596, in process_request_thread self.finish_request(request, client_address) File "/usr/local/lib/python2.7/dist-packages/AdvancedHTTPServer.py", line 669, in finish_request super(AdvancedHTTPServerNonThreaded, self).finish_request(_args, _kwargs) File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request self.RequestHandlerClass(request, client_address, self) File "/opt/king-phisher/king_phisher/server/server.py", line 120, in init super(KingPhisherRequestHandler, self).init(_args, _kwargs) File "/usr/local/lib/python2.7/dist-packages/AdvancedHTTPServer.py", line 743, in init super(AdvancedHTTPServerRequestHandler, self).init(_args, _kwargs) File "/usr/lib/python2.7/SocketServer.py", line 652, in init self.handle() File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle self.handle_one_request() File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request method() File "/opt/king-phisher/king_phisher/server/server.py", line 182, in _do_http_method http_method_handler(_args, _kwargs) File "/usr/local/lib/python2.7/dist-packages/AdvancedHTTPServer.py", line 1119, in do_POST self.dispatch_handler(self.query_data) File "/usr/local/lib/python2.7/dist-packages/AdvancedHTTPServer.py", line 954, in dispatch_handler self.respond_file(file_path, query=query) File "/opt/king-phisher/king_phisher/server/server.py", line 434, in respond_file template_module = template.make_module(template_vars) File "/usr/local/lib/python2.7/dist-packages/jinja2/environment.py", line 1033, in make_module return TemplateModule(self, self.new_context(vars, shared, locals)) File "/usr/local/lib/python2.7/dist-packages/jinja2/environment.py", line 1090, in init self._body_stream = list(template.root_render_func(context)) File "/var/www/redirect.html", line 10, in root File "/usr/local/lib/python2.7/dist-packages/jinja2/runtime.py", line 196, in call return __obj(_args, *_kwargs) File "/opt/king-phisher/king_phisher/server/pages.py", line 100, in make_csrf_page return markupsafe.Markup(page) File "/usr/local/lib/python2.7/dist-packages/markupsafe/init.py", line 74, in new return text_type.new(cls, base) UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 523: ordinal not in range(128)

In my browser I get an error " the connection to the server was reset while the page was loading."

I've been getting credentials in the database according to the client, so that isn't really an issue. I haven't been able to get the CSRF functionality to work as would like to. That's the last remaining issue on my list :)

Thanks again!

zeroSteiner commented 8 years ago

That error message usually indicates that there is an invalid character in the page template, something that's not UTF-8. Which version of King Phisher are you running, those encoding issues should have all been resolved already.

You should open your redirect.html and ensure that it contains only valid UTF-8 characters.

Zarcolio commented 8 years ago

According to docs/source/change_log.rst I'm using version 1.3.0

Saving it again with Notepad++ made the stack trace disappear :) So far so good, but the error " the connection to the server was reset while the page was loading." still remains... Any ideas?

zeroSteiner commented 8 years ago

Sounds like there still might be an issue in the server page. Can you please check the server logs as you reproduce that error? Also, this is on the CSRF page after you submit the credentials that you get this error correct?

Zarcolio commented 8 years ago

When I submit the form:

Yes correct, the error "the connection to the server was reset while the page was loading" appears after I submit the form on the landing page (index.html), so on the CSRF page (redirect.html)

zeroSteiner commented 8 years ago

It sounds like the index.html page is not POSTing the credentials to the redirect.html page. The index should have the HTML for the user to enter their credentials and have the redirect.html page specified as the target. This redirect.html page then allows the server to log the credentials and then creates an HTML form to forward them onto the CSRF target.

If you're not even getting a line in the log file regarding the redirect.html page being requested then it sounds like there's a problem with the index.html page not forwarding the user to it via the form.

Zarcolio commented 8 years ago

How strange:

zeroSteiner commented 8 years ago

Are you referring to the landing page as the index.html with the form or redirect.html with the CSRF post? Regardless of any of the HTML (you could have a simple text file) if the username and password query parameters are sent with a valid message or visit id, they will be recorded for the campaign. Can you post the contents of your index.html and redirect.html as well as the setting for your landing page?

Zarcolio commented 8 years ago

Yes, I am: Landing page = index.html CSRF page = redirect.html

index.html: <html> <body> <form method="post" action="redirect.html"> <input name="username"> <input name="password" type="password"> <input name="submit" type="submit" value="Submit"> </body> </html>

and the redirect.html:

{% do request.parameters.update({ 'username_csrf': request.parameters['username'], 'password_csrf': request.parameters['password'] }) %} {{ make_csrf_page('http://kenniscel.nl', request.parameters) }}

With the basic landing page, the error "the connection to the server was reset while the page was loading" seems to have been replaced with a bank screen. This blank screen has source:

<!DOCTYPE html> <html lang="en-US"> <body onload="document.getElementById('yFYXNJiR5T9k').submit()"> <form id="yFYXNJiR5T9k" action="http://kenniscel.nl" method="POST"> <input type="hidden" name="username" value="test" /> <input type="hidden" name="j_username" value="test" /> <input type="hidden" name="password" value="test" /> <input type="hidden" name="j_password" value="test" /> <input type="hidden" name="submit" value="Submit" /> </form> </body> </html>

But it doesn't submit...

For reference, the complex landing page has been renamed to index-complex.html So there's something strange with the complex landing page (I'll find that one out myself later on).

Zarcolio commented 8 years ago

Is there a reason why attacking with CSRF is done with JavaScript? Why not have the form onder the landing page submit the form to the CSRF vulnerable target page and make the username and password values in the forms configurable by a Jinja2 command on the same page? For example:

{{ username('custom_username_field') }} {{ password('custom_password_field') }}

<form id="login_form" action="https://www.facebook.com/login.php method="post" > <input type="email" name="custom_username_field" /> <input type="password" name="custom_password_field" /> <input value="Submit" type="submit" /> </form>

This way it's easier to configure and won't be blocked by plugins like NoScript or browsers like Lynx ;) On my machines this setup doesn't seem to submit to the target page with Windows10/Firefox 47.0, Windows10/Internet Explorer 11 or with Ubuntu 14.04/Firefox 46.0.1

zeroSteiner commented 8 years ago

Because Javascript is how the HTML form is automatically submitted. Using the form you provided, the user would have to manually submit the form. If you wanted to do it that way you're certainly free too, you would just need to pull the username and password parameters using the Jinja variable request.parameters. The make_csrf function is only provided for convenience.

Zarcolio commented 8 years ago

I get that the JavaScript is required to submit the form on the CSRF page. But that's not what I meant. What I meant is, why not submit the original form that is filled in by the visitor of the landing page, to the page the visitor thinks he/she's visiting? For example:

wolfthefallen commented 8 years ago

If the information is not submitted to the local HTML file. The king phisher server will not save the data in the King Phisher database. The csrf function utilizes this is formation when creating the response to send to the third party. On Jun 16, 2016 17:17, "Ocraz" notifications@github.com wrote:

I get that the JavaScript is required to submit the form on the CSRF page. But that's not what I meant. What I meant is, why not submit the original form that is filled in by the visitor of the landing page, to the page the visitor thinks he/she's visiting? For example:

  • Visitor visits landing page.
  • Visitor fills in form with credentials.
  • This form is submitted to the third-party website instead of to a local HTML file

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/securestate/king-phisher/issues/124#issuecomment-226616481, or mute the thread https://github.com/notifications/unsubscribe/AIngnfmWzRHO-uyBhvxAsBbDY61Dl_hoks5qMb1OgaJpZM4I3KUv .

Zarcolio commented 8 years ago

Of course, the server has no way of seeing that the client submits the form.

Zarcolio commented 8 years ago

I think I found why the JavaScript is not submitting the form. When I open the JavaScript console with F12, I see an error:

TypeError: document.getElementById(...).submit is not a function

This is because there's a hidden input field named "submit" But when renaming this input field to something else, it still won't submit because there's no submit button. But if I replace the line: <input type="hidden" name="submit" value="Submit" /> with <input type="submit" name="submit2" value="Submit" /> It works! Hurray!

But it leaves a nasty button :p So it got me thinking, how about:

This way:

To make it a little clearer, I've attached a PoC: http://13.74.186.137/facebook_landing.html which submits to http://13.74.186.137/facebook_csrf.html

zeroSteiner commented 8 years ago

What OS and browser are you using? I can take a look at why the form is not being submitted correctly and possibly expose a button if that's the reason. At this time however, cloning the landing page into the CSRF page is not something I'm interested in pursuing.

Zarcolio commented 8 years ago

I tried:

I found out about it at Stackoverflow.

As for the cloning of the landing page, I can imagine such a thing would involve a lot of work. Would it be feasible to make the CSRF page customizable (for example by inserting the necessary values with Jinja2 into a existing HTML page)? That way I can either clone the landing page myself or create a custom "Please wait" page.

zeroSteiner commented 8 years ago

If you want to create a custom CSRF page you can make your own in HTML and Jinja.

<!DOCTYPE html>
<html lang="en-US">
  <body onload="document.getElementById('yFYXNJiR5T9k').submit()">
    <form id="yFYXNJiR5T9k" action="http://wherever.com/" method="post" >
      <input type="hidden" name="password" value="{{ request.parameters['password'] }}" />
    </form>
  </body>
</html>

I did just notice something however and that is that the line you referenced <input type="hidden" name="submit" value="Submit" /> is only added to the CSRF form because it's passed from the original landing page.

Zarcolio commented 8 years ago
  1. Sweet! I'll take a look at this later on!
  2. Hmm, when I try to use the button tag, this fixes the problem for Firefox, but Internet Explorer doesn't submit the form at all :(
Zarcolio commented 8 years ago

Awesome sauce!!! Got King Phisher to work the way I want it to :) Thanks you guys for the good support and this awesome tool!

zeroSteiner commented 8 years ago

Our pleasure, does this issue need to remain open? It's unclear to me if there are any outstanding bugs / questions remaining.

Zarcolio commented 8 years ago

Everything's clear now and I don't have any outstanding bugs :) The issue can be closed.