1

I have a proxy container that makes a curl request to an api container. Below is the curl request for the proxy container:

    $postRequest = [
        'email' => $_POST['email'],
        'password' => $_POST['password']
        ];
    pretty_var_dump($postRequest);
        
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, 'http://api:80');
        curl_setopt($curl, CURLOPT_POSTFIELDS, $post_request);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $post_request);
        $curl_response = curl_exec($curl);
        curl_close($curl);
        
        $response = json_decode($curl_response, true);

        pretty_var_dump($response);

This is the code for the api file:

<?php

// return api results
header('Content-Type: application/json; charset=utf-8');

include_once('functions.php');
include_once('config.php');


$conn = new mysqli($host, $user, $pass, $mydatabase);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} else {
    echo "Connected to MySQL server successfully!";
}


$email = $_POST['email'];
$signin_password = $_POST['password'];




$select_query = "SELECT user_password, user_id, user_email, user_status FROM user_login WHERE user_email = '{$email}'";

echo $select_query;
$result = $conn->query($select_query);


if (isset($result)) {
    $result = $result->fetch_all(MYSQLI_ASSOC);
    pretty_var_dump($result);
    if (isset($result[0])) {
        $result = $result[0];

        if (isset($result['user_password']) && $result['user_password']) {
            if ($result['user_password']) {
                if (isset($result['user_status']) && $result['user_status'] === "1" && isset($result['user_id'])) {
                    $_SESSION['loggedIn'] = $result['user_status'];
                    response(['user_id' => $result['user_id'], 'session' => $result['user_status']], 200, 'Sign in successful');
                } elseif (isset($result['user_status']) && $result['user_status'] === "2" && isset($result['user_id'])) {
                    $_SESSION['loggedIn'] = $result['user_status'];
                    response(['user_id' => $result['user_id'], 'session' => $result['user_status']], 200, 'Sign in successful');
                }
            } else {
                $_SESSION['loggedIn'] = false;
                response('N/A', 401, 'Password incorrect');
            }
        }
    } else {
        response('N/A', 401, 'Email address not found');
    }
}

For some reason the api file isn't reading the POST data from curl and so every time returns null. MYSQLI, curl have both been installed, and if the API file is manually passed correct usernames and passwords it works perfectly.

Any help would be much appreciated!

EDIT I have updated my code for the curl request however i am still recieving null values back. The api code remains unchanged. Is there something obvious here i am missing?

        $email = $_POST['email'];
        $password = $_POST['password'];

        // $data = http_build_query($postRequest);
        $data = '{"email":"'.$email.'", "password":"'.$password.'"}';

        $headers = array(
            "Content-Type: application/json",
            "Accept: application/json",
         );
        

        pretty_var_dump($data);

        
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, 'http://127.0.0.1:86');
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        $curl_response = curl_exec($curl);
        curl_close($curl);
        
        $response = json_decode($curl_response, true);

        pretty_var_dump($response);
  • 1
    **Warning:** Your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unsanitised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Aug 30 '22 at 13:39
  • 1
    https://phpdelusions.net/mysqli also contains good examples of writing safe SQL using mysqli. See also the [mysqli documentation](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) and this: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) . Parameterising your queries will also greatly reduce the risk of accidental syntax errors as a result of un-escaped or incorrectly quoted input values. If you learnt your current technique from a tutorial or book, please don't use it again. – ADyson Aug 30 '22 at 13:39
  • 1
    Also, please don't store passwords in plain text - that is another security risk. Learn about [password hashing](https://www.php.net/manual/en/faq.passwords.php) instead. See also [How to use PHP's password_hash to hash and verify passwords](https://stackoverflow.com/questions/30279321/how-to-use-phps-password-hash-to-hash-and-verify-passwords) – ADyson Aug 30 '22 at 13:40
  • `For some reason the api file isn't reading the POST data`....look closer at your curl code, you've never actually told it to send a POST request. You've set data fields for a POST, but you've never set the HTTP method. Also, setting the $postRequest data additionally as a header makes no sense at all. – ADyson Aug 30 '22 at 13:40
  • password hashing is in an amended variation of the code, the current code is being run locally to get database containers up and running for signin verification (i havent done signup yet to hash passwords) – Aidan Campbell Aug 30 '22 at 13:42
  • 1
    I see. Anyway you'll need `curl_setopt($curl, CURLOPT_POST, 1);` to tell it to send a POST – ADyson Aug 30 '22 at 13:46
  • 1
    You may also need to do `curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_request));` to ensure it sends the data correctly. – ADyson Aug 30 '22 at 13:50
  • @ADyson He is unlikely vulnerable. It's not like it's an indexed webpage. The bigger issue is he is saving the user password. – Misunderstood Aug 31 '22 at 02:59
  • 1
    @Misunderstood any script which puts raw variable data into a sql script without parameterising it is potentially vulnerable to sql injection - and other problems - and it needs fixing. You have no idea whether this page is public or not, but even if it isn't it doesn't make any difference - intranets can still harbour malicious users, accidentally installed bots and so on...you should never imagine that a firewall makes you invulnerable, it's only one defence amongst many. Also this code is so basic it would break if someone used a `'` in the email address - that's reason enough to fix it! – ADyson Aug 31 '22 at 05:48
  • @ADyson you need to get out of that SQL Injection shell. First off there are many application that are not accessible to the public that you annoy with you pasta statement. And SQL Injection is not a threat to most site that do not have $Billions at risk. How about this. I only allow users 'names" to be numeric, like account numbers. I use $account = intval($_POST['user']). Would you like to try to inject that? – Misunderstood Aug 31 '22 at 06:34
  • 1
    @Misunderstood `there are many application that are not accessible to the public` ...like I said above, not being on the internet doesn't magically make an application invulnerable. Of course you can protect against integers like that but that isn't what's happening here, so it's not relevant. And it doesn't help for strings. And of course people can easily forget to do that, so the best way to ensure protection is simply to always use parameters and prepared statements. That can sometimes also improve performance and fix other issues such as the `'` problem. It's a no-brainer. – ADyson Aug 31 '22 at 07:53

1 Answers1

0

UPDATE

I doubt you need these headers. The Accept: is ok but that is not what a Browser uses.

    $headers = array(
        "Content-Type: application/json",
        "Accept: application/json",
     );

And the Content-Type is wrong. Content-Type is included in the response header, this is the request header.

And it needs to be a key value. You just have a string. $headers = array('Accept: ' => 'application/json');

In the email header those need to be fixed.

 $data = "email=$email&password=$password";

In the response you can add

header("Content-Type: application/json");

END OF UPDATE



I just got done posting this on another question. Looks like you could use it too.

You have a problem here for sure. I doubt $post_request belongs in both the CURLOPT_POSTFIELDS and CURLOPT_HTTPHEADER.

  curl_setopt($curl, CURLOPT_POSTFIELDS, $post_request);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($curl, CURLOPT_HTTPHEADER, $post_request)

Two ways to make your post data.

$post = 'key1=value1&key2=value2&key3=value3';
$post = array('key1'=>value1,'key2'=>value2,'key3'=>'value3');

depending on the data you may need to use urlencode()

$post = urlencode($post);

I do a lot of curl these are my standard post options

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
curl_setopt($ch, CURLOPT_ENCODING,"");

these are my troubleshooting options

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);

You NEED to see the request (out) and response headers (in), so you NEED these these two options.
These two option must come out after fixing the problem.

curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);

If it's HTTPS you need this one:

curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);

I always make my own request headers. You can remove that option, it's not mandatory.

$request = array();
$request[] = "Host: www.example.com";
$request[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$request[] = "User-Agent: MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0";
$request[] = "Accept-Language: en-US,en;q=0.5";
$request[] = "Connection: keep-alive";
$request[] = "Cache-Control: no-cache";
$request[] = "Pragma: no-cache";
Misunderstood
  • 5,534
  • 1
  • 18
  • 25
  • Thanks for this, i have now updated my code however am still recieiving null values. Is there a problem on the API branch instead? – Aidan Campbell Sep 02 '22 at 00:35
  • You missed including the $request array. And you also missed the $post data – Misunderstood Sep 02 '22 at 00:43
  • @AidanCampbell Have you looked at your $curl_response? There may be a response header in there depending on the default. If you see the response header use 'curl_setopt($ch, CURLOPT_HEADER, 0);' to get rid of it. Dump both $response and $curl_response. – Misunderstood Sep 02 '22 at 00:54
  • @AidanCampbell I made an update to my answer. – Misunderstood Sep 02 '22 at 01:18
  • thanks for your help. i tried adding in the $post and $request array like you said, but nothing is being returned back at all either in the $curl_response or $response for the above code – Aidan Campbell Sep 02 '22 at 01:29
  • @AidanCampbell are you sure the port 86 in your URL is correct? Post 86 is the UDP port. Try removing the port. Then is going to get the htdocs index.php. – Misunderstood Sep 02 '22 at 01:40
  • yea its def the correct port. curl requests between the docker containers works in git bash using this address and port which is the strange thing – Aidan Campbell Sep 02 '22 at 01:45