GWM :VAPT Scan Vulnerabilities

This commit is contained in:
Gowtham M 2026-01-08 16:56:43 +05:30
parent 2cd6fe3122
commit 84d99bf726
7 changed files with 403 additions and 76 deletions

View File

@ -600,6 +600,8 @@ $routes->group("employeeRest", ['filter' => ['appSignature'] ], function ($route
$routes->group("employeeRest", ["filter" => ['appSignature' , 'authJWT']], function ($routes) {
$routes->post('logout', 'RestAuthenticationController::logout');
$routes->post("ecardRequest", "ApiServiceController::ecardRequest");
$routes->get("getWellnessURL", "ApiServiceController::getWellnessURL");
@ -754,7 +756,7 @@ $routes->post("retrieveWebhookDataClaim","ClientWebHooksController::pullData_cla
//Third party ICICILombard Api Call
$routes->get('generateAuthToken','ICICILombardController::generateAuthToken');
$routes->get('generateAuthToken','FhplApiController::generateAuthToken');
$routes->get('createEnrollmentBatch','ICICILombardController::createEnrollmentBatch');
$routes->get('getEnrollmentBatchStatus','ICICILombardController::getEnrollmentBatchStatus');
$routes->get('fetchUHIDDetails','ICICILombardController::fetchUHIDDetails');

View File

@ -0,0 +1,48 @@
<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use App\Controllers\BaseController;
class ClaimsUploadController extends BaseController
{
use ResponseTrait;
protected $db;
public function __construct()
{
$this->db = \Config\Database::connect();
}
public function uploadDump()
{
$file = $this->request->getFile('file');
if (!$file || !$file->isValid()) {
return $this->respond([
'status' => 'failed',
'message' => 'Invalid file'
], 400);
}
$data = [
'client_id' => $this->request->getPost('client_id'),
'tpa_id' => $this->request->getPost('tpa_id'),
'client_policy_id' => $this->request->getPost('client_policy_id'),
'from_date' => $this->request->getPost('from_date'),
'to_date' => $this->request->getPost('to_date'),
'upload_file' => $file->getRandomName(),
// 'uploaded_by' => user_id()
];
$file->move(WRITEPATH . 'uploads/claims_dump', $data['upload_file']);
$this->db->table('claims_dump_uploads')->insert($data);
return $this->respond([
'status' => 'success',
'message' => 'Claims dump uploaded'
]);
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use App\Models\BatchFileModel;
use App\Models\EmployeePolicyModel;
use App\Models\TpaApiDataModel;
use App\Models\ClientPolicyModel;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\API\ResponseTrait;
use App\Controllers\Jobs;
class FhplApiController extends BaseController
{
use ResponseTrait;
protected $db;
protected $fhplTpaId;
public function __construct()
{
$this->db = \Config\Database::connect();
$this->fhplTpaId = getenv('FHPL_PRIMARY_KEY_CONSTANT');
}
public function generateAuthToken()
{
$url = env('FHPL_TOKEN_URL'); // example: https://uat.fhpl.net/token
// x-www-form-urlencoded body
$postData = http_build_query([
'UserName' => 'TestApi@fhpl',
'Password' => 'Fhpl@12345',
'grant_type' => 'password',
]);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET', // SAME AS POSTMAN
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json',
],
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
return $this->response->setJSON([
'status' => false,
'error' => curl_error($ch),
]);
}
curl_close($ch);
return $this->response->setJSON([
'status' => $httpCode === 200,
'http_code' => $httpCode,
'response' => json_decode($response, true),
]);
}
}

View File

@ -110,6 +110,13 @@ class RestAuthenticationController extends AdminController
if (isset($employeeData['employee_id']))
{
//check the resend otp (with in 60 seconds don't allow another otp to send)
$check = canSendOtp($employeeData);
if (!$check['allowed']) {
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
}
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Employee verified with ID = " . $employeeData['employee_id']);
log_message('error', ' ');
log_message('error', '************************ POST END ********************************');
@ -217,6 +224,12 @@ class RestAuthenticationController extends AdminController
if (isset($employeeData['employee_id'])) {
//check the resend otp (with in 60 seconds don't allow another otp to send)
$check = canSendOtp($employeeData);
if (!$check['allowed']) {
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
}
$builder = $this->employeeModel
->where('email_corporate', $email)
@ -518,6 +531,12 @@ class RestAuthenticationController extends AdminController
if ($HrData) {
//check the resend otp (with in 60 seconds don't allow another otp to send)
$check = canSendOtp($HrData);
if (!$check['allowed']) {
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
}
$sql = "UPDATE level_contacts SET otp = ? WHERE mobile = ? AND contact_type = 'client' AND is_active = 1";
@ -569,6 +588,12 @@ class RestAuthenticationController extends AdminController
if ($HrData) {
//check the resend otp (with in 60 seconds don't allow another otp to send)
$check = canSendOtp($HrData);
if (!$check['allowed']) {
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
}
$sql = "
UPDATE level_contacts
SET otp = ?
@ -2289,4 +2314,53 @@ class RestAuthenticationController extends AdminController
}
}
public function logout()
{
$authHeader = $this->request->getHeaderLine('Authorization');
if (!$authHeader) {
return $this->respond([
'status' => false,
'message' => 'Authorization token missing'
], 401);
}
// Validate JWT (your hardened function)
$result = JWTToken::validateJWT($authHeader);
if ($result['status'] !== true) {
return $this->respond([
'status' => false,
'message' => 'Invalid or expired token'
], 401);
}
$decoded = $result['decoded'];
$userId = $decoded['id'] ?? null;
if (!$userId) {
return $this->respond([
'status' => false,
'message' => 'Invalid token payload'
], 401);
}
// Identify user type
if (isset($decoded['emp_code'])) {
$model = new EmployeeModel();
} else {
$model = new LevelContactModel();
}
// Invalidate token server-side
$model->update($userId, [
'token_time_out' => null
]);
return $this->respond([
'status' => true,
'message' => 'Logged out successfully'
], 200);
}
}

View File

@ -18,67 +18,119 @@ use App\Models\LevelContactModel;
class AuthJWT implements FilterInterface
{
// public function before(RequestInterface $request, $arguments = null)
// {
// $jwt = $request->getHeader('Authorization');
// if ($jwt) {
// if (JWTToken::validateJWT($jwt)) {
// $data = JWTToken::validateJWT($jwt);
// $data = json_decode($data);
// $id = $data->decoded->id;
// if(isset($data->decoded->emp_code)){
// $model = new EmployeeModel();
// $user_data = $model->where('id', $id)->first();
// if($user_data['token_time_out'] > time()){
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
// $model->update($id, $data);
// return true;
// }else{
// // if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
// $data =["token_time_out" => ''];
// $model->update($id, $data);
// header('Content-Type: application/json');
// http_response_code(401);
// // $error = json_encode(["status" => 401, "message" => $data->message]);
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
// echo $error;
// exit;
// }
// }else{
// $model = new LevelContactModel();
// $hr_data = $model->where('id', $id)->first();
// if($hr_data['token_time_out'] > time()){
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
// $model->update($id, $data);
// return true;
// }else{
// $data =["token_time_out" => ''];
// $model->update($id, $data);
// header('Content-Type: application/json');
// http_response_code(401);
// // $error = json_encode(["status" => 401, "message" => $data->message]);
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
// echo $error;
// exit;
// }
// }
// }
// } else {
// header('Content-Type: application/json');
// http_response_code(403);
// $error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
// echo $error;
// exit();
// }
// }
public function before(RequestInterface $request, $arguments = null)
{
$jwt = $request->getHeader('Authorization');
$authHeader = $request->getHeaderLine('Authorization');
if ($jwt) {
if (JWTToken::validateJWT($jwt)) {
$data = JWTToken::validateJWT($jwt);
$data = json_decode($data);
$id = $data->decoded->id;
if(isset($data->decoded->emp_code)){
$model = new EmployeeModel();
$user_data = $model->where('id', $id)->first();
if($user_data['token_time_out'] > time()){
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
$model->update($id, $data);
return true;
}else{
// if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
$data =["token_time_out" => ''];
$model->update($id, $data);
header('Content-Type: application/json');
http_response_code(401);
// $error = json_encode(["status" => 401, "message" => $data->message]);
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
echo $error;
exit;
}
}else{
$model = new LevelContactModel();
$hr_data = $model->where('id', $id)->first();
if($hr_data['token_time_out'] > time()){
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
$model->update($id, $data);
return true;
}else{
$data =["token_time_out" => ''];
$model->update($id, $data);
header('Content-Type: application/json');
http_response_code(401);
// $error = json_encode(["status" => 401, "message" => $data->message]);
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
echo $error;
exit;
}
}
}
} else {
header('Content-Type: application/json');
http_response_code(403);
$error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
echo $error;
exit();
if (!$authHeader) {
return $this->reject(403, 'Access Forbidden');
}
$result = JWTToken::validateJWT($authHeader);
if ($result['status'] !== true) {
return $this->reject(401, $result['message']);
}
$decoded = $result['decoded'];
$id = $decoded['id'] ?? null;
if (!$id) {
return $this->reject(401, 'Invalid token payload');
}
if (isset($decoded['emp_code'])) {
$model = new EmployeeModel();
} else {
$model = new LevelContactModel();
}
$user = $model->find($id);
if (!$user || $user['token_time_out'] <= time()) {
$model->update($id, ['token_time_out' => null]);
return $this->reject(401, 'Token expired');
}
// Refresh sliding expiration
$model->update($id, [
'token_time_out' => time() + getenv('TOKENTIMEOUT')
]);
return true;
}
private function reject(int $code, string $message)
{
return service('response')
->setStatusCode($code)
->setJSON(['status' => $code, 'message' => $message])
->send();
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here after the response is sent

View File

@ -18,9 +18,12 @@ use App\Models\LevelContactModel;
class JWTToken
{
private const ALLOWED_ALG = 'HS512';
public static function encode($data =null)
{
$secret_Key ="secret";
$secret_Key = env('JWT_SECRET');
$request_data = (array)$data;
@ -47,30 +50,79 @@ class JWTToken
}
}
public static function validateJWT($jwt)
// public static function validateJWT($jwt)
// {
// $jwtParts = explode(' ', $jwt);
// // print_r($jwtParts);
// if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
// return false;
// }
// $token = $jwtParts[1];
// try {
// $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512'));
// return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
// } catch (ExpiredException $e) {
// return json_encode(['status' => false, 'message' => 'Token has expired']);
// } catch (BeforeValidException $e) {
// return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
// } catch (SignatureInvalidException $e) {
// return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
// } catch (\Exception $e) {
// return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
// }
// }
public static function validateJWT(string $authHeader)
{
$jwtParts = explode(' ', $jwt);
// 1⃣ Validate Authorization header
if (!preg_match('/^Bearer\s(\S+)$/', $authHeader, $matches)) {
return ['status' => false, 'message' => 'Invalid Authorization header'];
}
// print_r($jwtParts);
if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
return false;
}
$token = $matches[1];
$token = $jwtParts[1];
// 2⃣ Decode JWT header manually
$jwtParts = explode('.', $token);
if (count($jwtParts) !== 3) {
return ['status' => false, 'message' => 'Malformed JWT'];
}
try {
$decoded = JWT::decode($token, new Key("secret", 'HS512'));
return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
} catch (ExpiredException $e) {
return json_encode(['status' => false, 'message' => 'Token has expired']);
} catch (BeforeValidException $e) {
return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
} catch (SignatureInvalidException $e) {
return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
} catch (\Exception $e) {
return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
}
$header = json_decode(base64_decode(strtr($jwtParts[0], '-_', '+/')), true);
// 3⃣ Reject missing or NONE algorithm
if (
empty($header['alg']) ||
$header['alg'] === 'none' ||
$header['alg'] !== self::ALLOWED_ALG
) {
return ['status' => false, 'message' => 'Invalid or unsupported JWT algorithm'];
}
// 4⃣ Enforce signature validation
try {
$decoded = JWT::decode(
$token,
new Key(env('JWT_SECRET'), self::ALLOWED_ALG)
);
return [
'status' => true,
'decoded' => (array) $decoded
];
} catch (ExpiredException $e) {
return ['status' => false, 'message' => 'Token expired'];
} catch (BeforeValidException $e) {
return ['status' => false, 'message' => 'Token not yet valid'];
} catch (SignatureInvalidException $e) {
return ['status' => false, 'message' => 'Invalid token signature'];
} catch (\Exception $e) {
return ['status' => false, 'message' => 'Token validation failed'];
}
}

View File

@ -978,3 +978,29 @@ if (!function_exists('generate_ecard_download_link_based_on_tpa')) {
}
}
if (!function_exists('canSendOtp')) {
function canSendOtp(array $row, int $limitSeconds = 60): array
{
// If OTP does not exist → allow
if (empty($row['otp']) || empty($row['updated_at'])) {
return ['allowed' => true];
}
$lastUpdated = strtotime($row['updated_at']);
$currentTime = time();
// Calculate expiry time
$allowedAfter = $lastUpdated + $limitSeconds;
// If still within limit → block
if ($currentTime < $allowedAfter) {
return [
'allowed' => false,
'retry_after' => $allowedAfter - $currentTime
];
}
return ['allowed' => true];
}
}