FEAT_VAPT_FILE_RESTRICTION&FORM_SANITIZATION
This commit is contained in:
parent
332c412d0f
commit
7be77dacd5
@ -16,6 +16,8 @@ use App\Filters\AuthClientApi;
|
||||
use App\Filters\CommissionApiFilter;
|
||||
use App\Filters\VerifyAppSignature;
|
||||
use App\Filters\Cors;
|
||||
use App\Filters\SecurityInputFilter;
|
||||
use App\Filters\GlobalPostFileUploadGuard;
|
||||
|
||||
use App\Filters\AuthJWT;
|
||||
|
||||
@ -43,6 +45,8 @@ class Filters extends BaseConfig
|
||||
'CommissionApiFilter'=> CommissionApiFilter::class,
|
||||
'appSignature' => VerifyAppSignature::class,
|
||||
'Cors' => Cors::class,
|
||||
'SecurityInputFilter' => SecurityInputFilter::class,
|
||||
'GlobalPostFileUploadGuard' => GlobalPostFileUploadGuard::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -56,6 +60,8 @@ class Filters extends BaseConfig
|
||||
'before' => [
|
||||
'HttpRequestLog' => ['except' => 'cli/*'],
|
||||
'Cors',
|
||||
'SecurityInputFilter',
|
||||
'GlobalPostFileUploadGuard'
|
||||
// 'csrf',
|
||||
// 'invalidchars',
|
||||
],
|
||||
|
||||
@ -519,6 +519,7 @@ class ClientController extends AdminController
|
||||
public function updateEmpAndPolicyStatus()
|
||||
{
|
||||
$return = $this->clientPolicyModel->updateStatus();
|
||||
print_rr($return);
|
||||
$this->myLogger->logme('error', 'Client Policy Status Update Count: {data}', ['data' => $return['client']]);
|
||||
$this->myLogger->logme('error', 'Employee Policy Status Update Count: {data}', ['data' => $return['emp']]);
|
||||
}
|
||||
|
||||
@ -1492,6 +1492,7 @@ class EmployeeController extends AdminController
|
||||
|
||||
//new step check in S3 if yes then fetch from S3 bucket
|
||||
$s3_key = 'ecard_'.$get_emp_code_and_client_policy_id['name'].'('.$get_emp_code_and_client_policy_id['emp_code'].')'.'_'.$get_emp_code_and_client_policy_id['tpa_id'].'.pdf';
|
||||
$s3_key = $this->sanitizeFilePart($s3_key);
|
||||
// echo $s3_key;die();
|
||||
$s3 = \Config\Services::getS3Service();
|
||||
if($s3->exists($s3_key) && $mode != 2) //2 => for bulk generate so skip s3 check and generate PDF
|
||||
@ -3346,7 +3347,8 @@ class EmployeeController extends AdminController
|
||||
|
||||
public function initiateWellnessOnboard($client_policy_id)
|
||||
{
|
||||
$r = Jobs::addJob(['job_name' => 'initiateWellnessOnboardJob','payload' => ['client_policy_id' => $client_policy_id]]);
|
||||
$r = Jobs::addJob(['job_name' => 'initiateWellnessOnboardJob','payload' => ['client_policy_id' => $client_policy_id]]);
|
||||
//$this->initiateWellnessOnboardJob(['client_policy_id' => $client_policy_id]);
|
||||
return $this->respond(['status' => true, 'code' => 200, 'message' => 'Process started'], 200);
|
||||
}
|
||||
|
||||
@ -3377,7 +3379,7 @@ class EmployeeController extends AdminController
|
||||
// echo '==============================';die();
|
||||
// $data = '[{"id":12847,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"test name","relationship":"SELF","emp_code":"TEST_EMP_001","email_corporate":"test@gmail.com","mobile":"9797976565","dob":"1975-08-09"},{"id":12846,"employee_id":"TEST_EMP_001","client_policy_id":null,"tpa_id":null,"uhid":null,"batch_code":null,"status":"active","pre_existing_alignments":null,"age_band":null,"basic_cover_si":"0","date_coverage":"2025-01-01","policy_end_date":"2025-12-31","days":"0","premium":"0","rata_premimum":"0","gst":"0","si_enhancement_date":null,"date_of_exit":null,"reason_for_exit":null,"claim_status":"0","created_by":null,"created_at":null,"updated_by":null,"updated_at":null,"is_active":"1","rand_string":null,"ecard_sent_status":"0","payable_employee":"0","file_id":null,"wellness_onboard":"0","name":"dependent 1","relationship":"SON","emp_code":"TEST_EMP_001","email_corporate":"dependent1@gmail.com","mobile":"9898989898","dob":"2001-08-09"}]';
|
||||
// $data = (array)json_decode($data,true);
|
||||
// print_r($data);
|
||||
// print_r(count($data));
|
||||
// echo '==============================';die();
|
||||
if(is_array($data) && count($data))
|
||||
{
|
||||
@ -3406,7 +3408,7 @@ class EmployeeController extends AdminController
|
||||
$familiesPayload[$empCode] = $this->buildFamilyPayload($empCode, $members);
|
||||
}
|
||||
|
||||
// print_r($familiesPayload);die();
|
||||
// print_rr($familiesPayload);die();
|
||||
$apiResponse = $this->sendFamiliesToWellnessApi($familiesPayload);
|
||||
// print_r($apiResponse);
|
||||
$updatedData = $this->updateWellnessOnboardResponseToDB($apiResponse);
|
||||
@ -3439,7 +3441,7 @@ class EmployeeController extends AdminController
|
||||
{
|
||||
// Use the first member as primary reference for policy level data
|
||||
$primary = $members[0];
|
||||
|
||||
// print_rr($primary);die();
|
||||
// Map DB fields to your required "policyDetails" structure
|
||||
$policyStartDate = $primary['cp_policy_start_date'] ?? null;
|
||||
// $policyStartDate = '2025-01-01';
|
||||
@ -3495,6 +3497,7 @@ class EmployeeController extends AdminController
|
||||
public function sendFamiliesToWellnessApi(array $familiesPayload): array
|
||||
{
|
||||
// CI4 HTTP client
|
||||
// print_rr($familiesPayload);die();
|
||||
$client = \Config\Services::curlrequest();//die();
|
||||
$endpointUrl = getenv('WELLNESS_ONBOARD_ENDPOINT_URL');
|
||||
// Custom headers
|
||||
@ -3504,7 +3507,7 @@ class EmployeeController extends AdminController
|
||||
];
|
||||
|
||||
foreach ($familiesPayload as $empCode => &$family) {
|
||||
|
||||
// print_rr($family);die();
|
||||
try {
|
||||
$response = $client->post($endpointUrl, [
|
||||
'headers' => $headers,
|
||||
@ -3522,6 +3525,8 @@ class EmployeeController extends AdminController
|
||||
'rawBody' => $body,
|
||||
'data' => $decoded,
|
||||
];
|
||||
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
// In case of exception, store error info
|
||||
$family['apiResponse'] = [
|
||||
@ -3531,6 +3536,8 @@ class EmployeeController extends AdminController
|
||||
'error' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
// print_rr($body );die();
|
||||
}
|
||||
|
||||
unset($family); // break reference
|
||||
|
||||
147
app/Filters/GlobalPostFileUploadGuard.php
Normal file
147
app/Filters/GlobalPostFileUploadGuard.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Filters\FilterInterface;
|
||||
use Config\Services;
|
||||
use finfo;
|
||||
|
||||
class GlobalPostFileUploadGuard implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* Max file size (in bytes) → 25MB
|
||||
*/
|
||||
protected int $maxFileSize = 25 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* Allowed MIME types mapped to extensions
|
||||
*/
|
||||
protected array $allowedMimeMap = [
|
||||
'image/jpeg' => ['jpg', 'jpeg'],
|
||||
'image/png' => ['png'],
|
||||
'image/gif' => ['gif'],
|
||||
'image/webp' => ['webp'],
|
||||
'image/svg+xml' => ['svg'],
|
||||
'application/pdf' => ['pdf'],
|
||||
'application/msword' => ['doc'],
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'],
|
||||
'application/vnd.oasis.opendocument.text' => ['odt'],
|
||||
'text/rtf' => ['rtf'],
|
||||
'application/rtf' => ['rtf'],
|
||||
'application/vnd.ms-excel' => ['xls'],
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'],
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => ['ods'],
|
||||
'text/csv' => ['csv'],
|
||||
'application/csv' => ['csv'],
|
||||
'text/plain' => ['txt', 'csv'],
|
||||
];
|
||||
|
||||
protected array $blockedExtensions = [
|
||||
'php', 'phtml', 'pht', 'phar', 'php3', 'php4', 'php5', 'php7', 'php8', 'phps',
|
||||
'cgi', 'fcgi', 'pl', 'py', 'rb', 'lua', 'tcl', 'go', 'rs', 'jar', 'class',
|
||||
'exe', 'dll', 'com', 'bat', 'cmd', 'msi', 'vbs', 'ps1', 'scr',
|
||||
'sh', 'bash', 'zsh', 'apk', 'app', 'deb', 'rpm', 'bin', 'run',
|
||||
'js', 'mjs', 'jsp', 'asp', 'aspx', 'cer', 'swf',
|
||||
'env', 'ini', 'user.ini', 'htaccess', 'htpasswd', 'conf', 'config', 'log', 'sql',
|
||||
'zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz', 'iso',
|
||||
'lnk', 'url', 'reg', 'sys', 'drv', 'vxd', 'tmp', 'bak', 'old', 'backup', 'key', 'pem'
|
||||
];
|
||||
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
if ($request->getMethod() !== 'post') {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = $request->getFiles();
|
||||
if (empty($files)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($files as $inputName => $fileData) {
|
||||
$this->validateFileInput($fileData, $inputName);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateFileInput($fileData, string $inputName): void
|
||||
{
|
||||
if (is_array($fileData)) {
|
||||
foreach ($fileData as $file) {
|
||||
$this->validateSingleFile($file, $inputName);
|
||||
}
|
||||
} else {
|
||||
$this->validateSingleFile($fileData, $inputName);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateSingleFile($file, string $inputName): void
|
||||
{
|
||||
$request = Services::request();
|
||||
$clientIp = $request->getIPAddress();
|
||||
$uri = $request->getUri()->getPath();
|
||||
|
||||
if (!$file->isValid()) {
|
||||
if ($file->getError() === UPLOAD_ERR_INI_SIZE || $file->getError() === UPLOAD_ERR_FORM_SIZE) {
|
||||
$this->block("File exceeds server-side size limit", $clientIp, $uri, $inputName, $file->getClientName(), 'unknown', 'unknown', 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$originalName = $file->getClientName();
|
||||
$extension = strtolower($file->getExtension());
|
||||
$mime = $file->getMimeType();
|
||||
$size = $file->getSize();
|
||||
|
||||
// --- 1. Fixed Null Byte & Path Traversal Check ---
|
||||
if (preg_match('/\0|[\/\\\]/', $originalName)) {
|
||||
$this->block("Malicious filename characters", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
|
||||
// --- 2. Double Extension Attack Check ---
|
||||
if (preg_match('/\.(php|phtml|phar|exe|sh|bat|cmd|js|jsp|asp|aspx|py|pl)\./i', $originalName)) {
|
||||
$this->block("Double extension attack", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
|
||||
// --- 3. Forbidden Extension ---
|
||||
if (in_array($extension, $this->blockedExtensions, true)) {
|
||||
$this->block("Forbidden extension", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
|
||||
// --- 4. File Size Limit ---
|
||||
if ($size > $this->maxFileSize) {
|
||||
$this->block("File too large", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
|
||||
// --- 5. MIME Allow-list Check ---
|
||||
if (!array_key_exists($mime, $this->allowedMimeMap)) {
|
||||
$this->block("MIME type not allowed ($mime)", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
|
||||
// --- 6. MIME-Extension Consistency ---
|
||||
if (!in_array($extension, $this->allowedMimeMap[$mime], true)) {
|
||||
$this->block("MIME-extension mismatch", $clientIp, $uri, $inputName, $originalName, $mime, $extension, $size);
|
||||
}
|
||||
}
|
||||
|
||||
private function block(string $reason, string $ip, string $uri, string $field, string $filename, string $mime, string $ext, int $size): void
|
||||
{
|
||||
log_message('critical',
|
||||
'[UPLOAD_BLOCKED] {reason} | IP: {ip} | URI: {uri} | Field: {field} | File: {file} | MIME: {mime} | EXT: {ext} | SIZE: {size}',
|
||||
['reason'=>$reason, 'ip'=>$ip, 'uri'=>$uri, 'field'=>$field, 'file'=>$filename, 'mime'=>$mime, 'ext'=>$ext, 'size'=>$size]
|
||||
);
|
||||
|
||||
$response = Services::response();
|
||||
$response->setStatusCode(403)
|
||||
->setJSON([
|
||||
'status' => 'error',
|
||||
'message' => 'File upload rejected: Security policy violation.',
|
||||
'debug' => (ENVIRONMENT === 'development') ? $reason : null
|
||||
])
|
||||
->send();
|
||||
exit;
|
||||
}
|
||||
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {}
|
||||
}
|
||||
129
app/Filters/SecurityInputFilter.php
Normal file
129
app/Filters/SecurityInputFilter.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use CodeIgniter\Filters\FilterInterface;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Services;
|
||||
|
||||
class SecurityInputFilter implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* High-confidence XSS patterns only
|
||||
* (low false-positive set)
|
||||
**/
|
||||
|
||||
protected array $xssPatterns = [
|
||||
// Script execution
|
||||
'/<\s*script\b/i',
|
||||
'/<\/\s*script\s*>/i',
|
||||
|
||||
// JavaScript execution vectors
|
||||
'/javascript\s*:/i',
|
||||
'/vbscript\s*:/i',
|
||||
'/data\s*:\s*text\/html/i',
|
||||
|
||||
// Inline event handlers (strong signal)
|
||||
'/on\w+\s*=\s*["\']?/i',
|
||||
|
||||
// Dangerous HTML tags
|
||||
'/<\s*iframe\b/i',
|
||||
'/<\s*object\b/i',
|
||||
'/<\s*embed\b/i',
|
||||
'/<\s*applet\b/i',
|
||||
|
||||
// Image-based execution
|
||||
'/<\s*img\b[^>]*on\w+/i',
|
||||
|
||||
// SVG-based execution (modern bypass)
|
||||
'/<\s*svg\b/i',
|
||||
'/<\s*math\b/i',
|
||||
|
||||
// Meta refresh redirect
|
||||
'/<\s*meta\b[^>]*http-equiv\s*=\s*["\']?refresh/i',
|
||||
|
||||
// HTML injection via src/href
|
||||
'/<\s*\w+\b[^>]*(src|href)\s*=\s*["\']?\s*(javascript|data)\s*:/i'
|
||||
];
|
||||
|
||||
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
$logger = Services::mylogger();
|
||||
$response = Services::response();
|
||||
|
||||
// Collect all user-controlled input
|
||||
$inputs = array_merge(
|
||||
$request->getGet(),
|
||||
$request->getPost()
|
||||
);
|
||||
|
||||
if (empty($inputs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($inputs as $field => $value) {
|
||||
if (is_array($value)) {
|
||||
$value = json_encode($value);
|
||||
}
|
||||
|
||||
// Step 1: Canonicalization (VERY IMPORTANT)
|
||||
$canonical = $this->canonicalize($value);
|
||||
|
||||
// Step 2: Trim (hygiene)
|
||||
$canonical = trim($canonical);
|
||||
|
||||
// Step 3: Detection (signal-only)
|
||||
if ($this->detectXss($canonical)) {
|
||||
|
||||
// 🔐 Log intent, not data
|
||||
$logger->logme('critical','SECURITY_BLOCKED_REQUEST - '. json_encode([
|
||||
'ip' => $request->getIPAddress(),
|
||||
'method' => $request->getMethod(),
|
||||
'uri' => current_url(),
|
||||
'field' => $field,
|
||||
'attack' => 'XSS_PATTERN',
|
||||
'length' => strlen($canonical),
|
||||
'hash' => hash('sha256', $canonical),
|
||||
]));
|
||||
|
||||
// ⛔ Block request
|
||||
return $response
|
||||
->setStatusCode(403)
|
||||
->setJSON([
|
||||
'status' => 403,
|
||||
'error' => 'Forbidden',
|
||||
'message' => 'Malicious input detected'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalization prevents encoded bypass
|
||||
*/
|
||||
private function canonicalize(string $value): string
|
||||
{
|
||||
$value = urldecode($value);
|
||||
$value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
|
||||
// Remove invisible control characters
|
||||
return preg_replace('/[\x00-\x1F\x7F]/u', '', $value);
|
||||
}
|
||||
|
||||
private function detectXss(string $value): bool
|
||||
{
|
||||
foreach ($this->xssPatterns as $pattern) {
|
||||
if (preg_match($pattern, $value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -9,35 +9,70 @@
|
||||
<label for="zip_folder">Zip Folder (inside zip to deploy)</label>
|
||||
<select name="zip_folder" id="zip_folder">
|
||||
<option value="web/">web/</option>
|
||||
<option value="dist/">dist/</option>
|
||||
<!-- <option value="dist/">dist/</option> -->
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="s3_bucket">S3 Bucket</label>
|
||||
<select name="s3_bucket" id="s3_bucket">
|
||||
<option value="benefits-app-bucket">benefits-app-bucket</option>
|
||||
<option value="other-bucket">other-bucket</option>
|
||||
<option value="uat-benefits-app-bucket">UAT Benefits</option>
|
||||
<option value="uat-hr-app-bucket">UAT HR</option>
|
||||
<option value="benefits-app-bucket">Live Benefits</option>
|
||||
<option value="live-hr-app-bucket">Live HR</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="s3_prefix">S3 Prefix</label>
|
||||
<input type="text" name="s3_prefix" id="s3_prefix" value="hr/">
|
||||
<input type="text" name="s3_prefix" id="s3_prefix" value="/*">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="cf_distribution_id">CloudFront Distribution ID (optional)</label>
|
||||
<input type="text" name="cf_distribution_id" id="cf_distribution_id" value="E1MKRK4U5MZ3BD">
|
||||
<!-- <input type="text" name="cf_distribution_id" id="cf_distribution_id" value="E1MKRK4U5MZ3BD"> -->
|
||||
<select name="cf_distribution_id" id="cf_distribution_id">
|
||||
<option value="EUBZ8CDSV9KZZ">UAT Benefits</option>
|
||||
<option value="E9TNPRI9ITM1M">UAT HR</option>
|
||||
<option value="E1MKRK4U5MZ3BD">Live Benefits</option>
|
||||
<option value="E3TE01DPKHTD8B">Live HR</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="cf_paths">
|
||||
CloudFront Invalidation Paths (comma or newline separated, e.g. <code>/hr/*,/hr/special/*</code>)
|
||||
</label>
|
||||
<input type="text" name="cf_paths" id="cf_paths" value="/hr/*">
|
||||
<input type="text" name="cf_paths" id="cf_paths" value="/*">
|
||||
<!-- If you prefer multi-line, use <textarea> instead of <input> -->
|
||||
</div>
|
||||
|
||||
<button type="submit">Deploy</button>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const bucketToDistributionMap = {
|
||||
'uat-benefits-app-bucket': 'EUBZ8CDSV9KZZ',
|
||||
'uat-hr-app-bucket': 'E9TNPRI9ITM1M',
|
||||
'benefits-app-bucket': 'E1MKRK4U5MZ3BD',
|
||||
'live-hr-app-bucket': 'E3TE01DPKHTD8B'
|
||||
};
|
||||
|
||||
const s3BucketEl = document.getElementById('s3_bucket');
|
||||
const cfDistributionEl = document.getElementById('cf_distribution_id');
|
||||
|
||||
s3BucketEl.addEventListener('change', function () {
|
||||
const selectedBucket = this.value;
|
||||
|
||||
if (bucketToDistributionMap[selectedBucket]) {
|
||||
cfDistributionEl.value = bucketToDistributionMap[selectedBucket];
|
||||
} else {
|
||||
// Optional: reset if no mapping found
|
||||
cfDistributionEl.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-select on page load (useful for edit forms)
|
||||
s3BucketEl.dispatchEvent(new Event('change'));
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -5,6 +5,27 @@ Options -Indexes
|
||||
# Rewrite engine
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
## ADDED for - block any script execution inside folder of public
|
||||
<If "%{REQUEST_URI} =~ m#/(logo|add_image_upload|e_card_imgs|assets|claim_sample_forms|sample_import_excel|writable)/#">
|
||||
Deny from all
|
||||
# Disable PHP engine
|
||||
<IfModule mod_php.c>
|
||||
php_flag engine off
|
||||
</IfModule>
|
||||
|
||||
# Disable CGI and other executable handlers
|
||||
Options -ExecCGI
|
||||
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgi
|
||||
|
||||
# Block access to any script-like files entirely
|
||||
<FilesMatch "\.(php|php5|php7|phtml|pl|py|cgi|asp|aspx|sh|rb)$">
|
||||
ForceType text/plain
|
||||
#Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
</If>
|
||||
|
||||
|
||||
# Turning on the rewrite engine is necessary for the following rules and features.
|
||||
# FollowSymLinks must be enabled for this to work.
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user