Jump to content

Fetching array of domains from external file


Moorcam
Go to solution Solved by Moorcam,

Recommended Posts

Hello folks,

I am trying to create a script that will check the current domain, compare it with an array of domains that are stored externally in domains.php. If we have a match, great. If not, show an error.

I am using CURL because of the vulnerabilities used using allow_url_include() so don't want to use that.

Here is domains.php

<?php
// domains.php

// Prevent direct access
if (basename($_SERVER['PHP_SELF']) === basename(__FILE__)) {
    die('Access denied.');
}

// Array of allowed domain names
$domains_content = [
    'test1.com',
    'test.com',
    'mywebsite.org'
];
?>

Here is the function for checking:

// This script checks if the current domain is in the allowed domains list.

// Function to fetch the external PHP file using CURL
function fetchDomains($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    
    if (curl_errno($ch)) {
        throw new Exception('CURL Error: ' . curl_error($ch));
    }
    
    curl_close($ch);
    return $response;
}

try {
    // URL of the external PHP file
    $url = 'https://www.domain/domains.php'; // Replace with the actual URL

    // Fetch the domains
    $domains_content = fetchDomains($url);
    
    // Evaluate the fetched content to get the array
    eval('?>' . $domains_content);
    
    // Get the current domain
    $current_domain = $_SERVER['HTTP_HOST'];

    // Check if the current domain is in the allowed domains
    if (!in_array($current_domain, $domains_content)) {
        throw new Exception('Error: The current domain "' . $current_domain . '" is not allowed.');
    }

    echo 'Domain check passed. Current domain: ' . $current_domain;

} catch (Exception $e) {
    // Handle exceptions and display error message
    echo 'An error occurred: ' . $e->getMessage();
}

I haven't included the actual domain I am checking for privacy reasons but you get the drift.

Here is the error I am getting:

[24-Oct-2024 00:04:58 Australia/Melbourne] PHP Warning:  in_array() expects parameter 2 to be array, string given in includes/header.php on line 85

Here is that line:

 if (!in_array($current_domain, $domains_content)) {
        throw new Exception('Error: The current domain "' . $current_domain . '" is not allowed.');
    }

If anyone can help resolve this I would appreciate it. The domain the script is hosted on is actually listed in the array.

Link to comment
Share on other sites

What you have defined for $domains_content in your first bit of posted code is irrelevant to your error, because 1) it is defined outside your function and 2) you redefine that variable shortly before the error

    // URL of the external PHP file
    $url = 'https://www.domain/domains.php'; // Replace with the actual URL

    // Fetch the domains
    $domains_content = fetchDomains($url);

So, what is the result of that call? It's apparently not an array. try adding this right after the last line above to see what is actually returned:

var_dump($domains_content);

EDIT: Correction, the error is in a block of code outside your function, so #1 in my response is not valid

Link to comment
Share on other sites

8 minutes ago, Psycho said:

What you have defined for $domains_content in your first bit of posted code is irrelevant to your error, because 1) it is defined outside your function and 2) you redefine that variable shortly before the error

    // URL of the external PHP file
    $url = 'https://www.domain/domains.php'; // Replace with the actual URL

    // Fetch the domains
    $domains_content = fetchDomains($url);

So, what is the result of that call? It's apparently not an array. try adding this right after the last line above to see what is actually returned:

var_dump($domains_content);

 

Using var_dump I get 301 error "Permanently Moved"

Link to comment
Share on other sites

47 minutes ago, Moorcam said:

Using var_dump I get 301 error "Permanently Moved"

I assume you got more than that from the var_dump. But, in any case, that response is not an array - correct? That would be why the in_array() function is failing with that error. So now you need to debug why passing your domain (which is not the same in your code above) is causing this error.

Link to comment
Share on other sites

the curl code is making a http(s) request to the URL, just like a browser would. because it is to a .php page, the php code is being executed on the target server and what you get back is whatever that page outputs. you do not get the raw php code. because you are trying to transfer data, i recommend that you use JSON and use echo json_encode($domains_content); in the domains.php code, then after you successfully receive that JSON string from the curl call, you can use json_decode() on it to get the array of data.

  • Great Answer 1
Link to comment
Share on other sites

16 minutes ago, mac_gyver said:

the curl code is making a http(s) request to the URL, just like a browser would. because it is to a .php page, the php code is being executed on the target server and what you get back is whatever that page outputs. you do not get the raw php code. because you are trying to transfer data, i recommend that you use JSON and use echo json_encode($domains_content); in the domains.php code, then after you successfully receive that JSON string from the curl call, you can use json_decode() on it to get the array of data.

domains.php:

<?php
// allowed_domains.php

// Prevent direct access
if (basename($_SERVER['PHP_SELF']) === basename(__FILE__)) {
    die('Access denied.');
}

// Array of allowed domains
$allowed_domains = [
    'example.com',
    'test.com',
    'mywebsite.org'
];

// Return the allowed domains as a JSON encoded string
echo json_encode($allowed_domains);
?>

site.php

// This script checks if the current domain is in the allowed domains list.
// Function to fetch allowed domains
function fetchAllowedDomains($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    
    if (curl_errno($ch)) {
        throw new Exception('CURL Error: ' . curl_error($ch));
    }
    
    curl_close($ch);
    
    return json_decode($response, true);
}

try {
    // URL of the external PHP file
    $url = 'https://www.site.com/domains.php';
    
    // Fetch allowed domains
    $allowed_domains = fetchAllowedDomains($url);
    
    // Get the current domain
    $current_domain = $_SERVER['HTTP_HOST'];
    
    // Check if the current domain is in the allowed domains
    if (!in_array($current_domain, $allowed_domains)) {
        throw new Exception('Error: The current domain (' . $current_domain . ') is not allowed.');
    }
    
    echo 'Domain check passed. Current domain is allowed.';
    
} catch (Exception $licenseMsg) {
    // Handle exceptions
    echo $licenseMsg->getMessage();
}

Error:

[24-Oct-2024 02:04:42 Australia/Melbourne] PHP Warning:  in_array() expects parameter 2 to be array, null given in includes/header.php on line 83

Thanks guys. Your help is appreciated.

Link to comment
Share on other sites

I'm not well versed in using cURL, but based on what you provided previously your call to the URL you are using is returning the response: 301 error "Permanently Moved"

But, you expect to be getting the JSON encoded output for the $allowed_domains array you are creating. I would assume you have tested the url in a browser and verified you are seeing the JSON content? If not, start there. If the content is correct when access via a browser then my best guess is that the web server maybe has some logic to detect programmatic access to pages and is blocking it. I'm pretty sure I've seen something like that before. But your issue has noting to do with the error you first reported. You need to figure out why your cURL request is not retrieving the JSON content you think it should be returning.

Although, this is a good opportunity to add additional error handling to your code to cover a scenario where the cURL request doesn't fail, but does not return contents you expect.

  • Thanks 1
Link to comment
Share on other sites

Ok it's weird.

Have directly accessed the file in a browser and get the array of domains. However, when I access via the script, I now get:

[24-Oct-2024 11:35:34 Australia/Melbourne] PHP Warning:  in_array() expects parameter 2 to be array, null given in includes/header.php on line 76

I have also rewritten the code to add error and exception handling:

// This script checks if the current domain is in the allowed domains list.

// Function to fetch valid domains from the external file
function fetchValidDomains($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    // Execute cURL request and handle potential errors
    $response = curl_exec($ch);
    if ($response === false) {
        throw new Exception('cURL Error: ' . curl_error($ch));
    }
    
    curl_close($ch);
    
    // Decode the JSON response and handle potential errors
    $domains = json_decode($response, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception('JSON Decode Error: ' . json_last_error_msg());
    }
    
    return $domains;
}

try {
    // Get the current domain
    $currentDomain = $_SERVER['HTTP_HOST'];

    // URL of the external PHP file
    $externalFileUrl = 'http://www.site.com/domains.php';

    // Fetch valid domains
    $validDomains = fetchValidDomains($externalFileUrl);

    // Check if the current domain is in the valid domains array
    if (!in_array($currentDomain, $validDomains)) {
        throw new Exception('Error: The current domain is not authorized.');
    }

    // If the domain is valid
    echo 'The current domain is authorized.';
} catch (Exception $e) {
    // Handle exceptions and display error message
    echo 'An error occurred: ' . $e->getMessage();
}

I'm at a loss.

Link to comment
Share on other sites

  • Solution

Ok, it now works.

I changed the domains.php file to the following:

<?php
// domains.php

// Array of domains
$domains = [
    "example.com",
    "example.org",
    "example.net",
    "example.edu"
];

// Set the content type to application/json
header('Content-Type: application/json');

// Encode the array to JSON and output it
echo json_encode($domains);
?>

Changed the domains to be encased in double quotes rather than single quotes and also set the type to application/json

Although it will not work in localhost because of local certificate errors, it does work in a live server environment.

Thank you both for your help. It's appreciated.

So, for anyone wanting this, here is the rest of the code:

<?php
// This script checks if the current domain is in the allowed domains list.

// Function to fetch domains from the external PHP file
function fetchDomains($url) {
    $ch = curl_init();
    
    // Set cURL options
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    // Execute cURL request
    $response = curl_exec($ch);
    
    // Error handling for cURL
    if (curl_errno($ch)) {
        throw new Exception('cURL Error: ' . curl_error($ch));
    }
    
    curl_close($ch);
    
    // Decode the JSON response
    $domains = json_decode($response, true);
    
    // Error handling for JSON decoding
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception('JSON Decode Error: ' . json_last_error_msg());
    }
    
    return $domains;
}

// Main execution
try {
    $url = 'https://www.site.com/domains.php'; // Replace with the actual URL of the external PHP file
    $domains = fetchDomains($url);
    
    // Get the current domain
    $currentDomain = $_SERVER['HTTP_HOST'];
    
    // Check if the current domain is in the fetched array
    if (!in_array($currentDomain, $domains)) {
        echo "Your domain, ($currentDomain) is not on the list.";
    }
} catch (Exception $e) {
    // Handle exceptions
    echo "An error occurred: " . $e->getMessage();
}
?>

 

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.