Hey everyone? Hopefully, you were able
to find the vulnerable code,
and in this case logical flaw in this code.
I'll walk through how I got there,
and we'll talk about
some of the issues with this code base.
But we will go ahead and patch it even though
it won't be the best patch that we can do.
So the issue here is that,
there is no back end to this.
Obviously, this is just for
a test case to demonstrate a very simple use case.
So whether developers or Webgoat did this,
they created a map.
They're storing secret question zero,
and secret question one inside of a map.
Now, realistically you wouldn't be doing
this in memory for thousands or millions of users,
every time your application goes up or down,
you can have to reset all those questions.
You would probably have a persistent stores
like a database that you would get this information from.
So given that we're
working within the confines of Webgoat,
and how Webgoat was engineered to
demonstrate a point to get that point across.
We're going to fix this flaw,
the logic of this flaw.
Encode here. Now, realistically speaking,
you would probably use a framework to do this.
You wouldn't want to write this all
from scratch yourself.
But we'll walk through the flaw
together and just see what we can find.
So the verify account,
the very first thing that it does,
is checks to see if the result that they send
is within the range of what they would expect,
if not return false.
That's a pretty sane thing to do.
They would also check to see if
security question zero was answered
properly based on what they know
security question zero's answer to be.
Remember they put those in the map right up here.
If the answer is" No"
to any of those, they would return false.
That's a fairly same thing to do as
well, and then lastly,
they do the same thing for question one,
and if you answer those things falsely,
it will return false.
So within those three cases,
you will not be able to log in.
However, they fail open.
Meaning. If the question that we submit
is not question zero, or question one.
Regardless of what the answer is,
is that they return true.
So what we want to do is,
we want to change this, so that we returned false,
unless they answered the questions properly.
So how would you go about fixing this?
So I'm going to comment this code out for now,
just so that it's not in that way,
and I'm going to say,
I'm going to return false.
Just to start with, this is
going to be the very last thing that gets executed.
I am not going to fail open.
I'm going to fail close.
So if for some reason even if my logic is broken,
and I'm not appropriately qualifying questions,
maybe I should be returning true.
Maybe I didn't think of an edge case.
That's okay. We can recover
from that. We'll get a bug report.
We can fix this.
But I'm not going to fail open.
I'm going to fail close.
So the very first thing that they had was some code
that essentially checks to make
sure that the questions have been created properly,
and validated, and all those things.
I am going to leave that in there.
The second part was to make sure if question zero,
if a map contains a particular question,
and it asked that the question was not answered properly.
So I think we're going to want to return true for these,
and we're going to turn that not into a positive.
So I'm going to take this body.
It's a very long one.
So as long as we have the key,
and they're doing this,
so you don't get a NullPointerException,
and the question zero was
properly answered, we're going to return true.
You got the right answer,
and we're going to do the same thing for that.
I'm just going to copy for question zero,
and I'm going to modify this zero to a one.
I did that with a shortcut,
but essentially it's identical
to checking for question zero,
but now I'm checking here for question
one, and I'm saying,
make sure I have the key,
and as long as I have the key,
that means I have the answer.
Check my answer against the answer I expect to have.
Now, this is a little wonky,
but just work with it because
it has to work for Webgoat and how Webgoat was written.
So let's think through our logic here.
We know that we want to make sure our map is set up,
and it's working properly.
Realistically, wouldn't be working against a map.
You could just pull, pull
something like this from a database,
but we're going to leave that in there,
knowing that this is test code,
and it's for educational purposes.
We know that our answer
zero needs to be answered correctly,
and now we know our security question zero has,
I'm sorry, security question one
has to be answer correctly.
So only in these two cases,
will I return true,
and if those two cases are not met for any reason,
I'm just going to return false.
So I'm going take this out, and let's give it a try.
In fact, we can scroll up here,
and we know what the answers are
for security question zero and one.
So after we test the cases that where we break it,
we can actually test the cases where we don't break it.
All right. Let's go ahead and open our Firefox.
Going to open it up, in private browsing modes,
so we don't hold any of the history of
this authentication flaws, authentication bypass.
So we were already successful in working through this.
So I'm going to reset the lesson,
and refresh the page. All right.
So let's see if our burp is running,
going to close some of these windows from yesterday,
and then clear out some of this, perfect.
So we are going through the proxy,
and I'm going to turn on interception.
I'm going to make sure that
I'm only intercepting for posts.
So I'm going to turn this off.
Go in my interception,
intercept does on, refresh the page,
nothing should get in our accepted,
because nothing was opposed by
refreshing a page which we just did a simple get.
I do test_1 and test_2 and we submit that,
and that did get caught by our interceptor.
We remember from exploiting this,
we simply change security question zero
to 22 or some other question, and 44.
So the expectation here is that if I forward this,
that it will not let me go and reset my password,
and you notice that
it says "Not quite, Please try again".
Now, we want also to make sure that we
didn't break the functionality.
So I'm going to come and copy the actual answers to
the questions from a code.
Anybody Sherlock Holmes fans here, right,
going to submit those,
and it's caught by interceptor,
so I'm just going to let it go through,
and they caught it.
They found out that we looked at
the source code to get those answers.
They know that we didn't actually break through this.
So that's great.
So we have now officially patch this.
I want to close a video with saying
that I know this seems a little wonky.
This is Webgoat was meant to be a task.
So some of the surrounding,
construction, and engineering, and architecture around,
how this problem is setup,
is not normally how we would go about it.
That's okay because we're
again trying to fix a logical flaw,
and the lesson here is to always
fail close rather than failing open.