Ravindra BagaleCourses & study guides Track your progress

Labs · Cyber Security

Lab: Set Up LEMP with PHP-FPM on Your Server and Switch Off PHP Error Display on the Live Site

Beginner40 minYour EC2 server with Nginx (Lab 7) · PHP-FPM · curl

Course: Cyber Security · Chapter 9: PHP, LAMP and LEMP Step by Step

Chapter 9 builds LAMP and LEMP step by step; this lab makes the PHP part safe for a live site.

Chala mitrano! A PHP error message on a live website is a free gift to an attacker: it shows folder paths, file names and sometimes database details. Today we see that leak with our own eyes on our own server, then close it the right way: hide errors from visitors, keep them in a log for us. Chala!

Suppose we are…

Suppose we are a PHP developer at a small agency that builds order pages for restaurants listed on Zomato. On the first day live, a typo shows Warning: Undefined variable $total in /usr/share/nginx/html/order.php on line 12 to every customer. Now strangers know our folder structure. Good teams set display_errors = Off on live servers and read errors from a log file instead.

Goal of this lab

By the end you will have:

  • A working LEMP stack part: Linux + Nginx + PHP-FPM (FastCGI Process Manager, the program that runs PHP for Nginx).
  • Seen a PHP warning leak a file path, then hidden it.
  • display_errors = Off, log_errors = On and expose_php = Off, and the error written to a log only you can read.

What you need (all free)

  • Your free-tier EC2 Amazon Linux 2023 server with Nginx (Lab 7), HTTP 80 open to My IP.
  • 35–40 minutes.

Safety and ethics

Never leave phpinfo() or test pages on a real website; delete them after the lab. Practise on your own server only.

Part 1: add PHP-FPM

  1. SSH to the server and install PHP-FPM:

    sudo dnf install -y php-fpm php-cli
    sudo systemctl enable --now php-fpm
    sudo nginx -t && sudo systemctl restart nginx
    

    On Amazon Linux 2023 the php-fpm package already adds the Nginx config that sends .php files to PHP-FPM.

  2. Create a test page:

    echo '<?php echo "PHP works: " . PHP_VERSION; ?>' | sudo tee /usr/share/nginx/html/hello.php
    curl http://localhost/hello.php
    

    What you should see: PHP works: 8.x.x.

Part 2: see the leak

  1. Check the current settings:

    php -i | grep -E "^display_errors|^log_errors|^expose_php"
    
  2. To see the danger, switch errors on for a moment, the way a developer might on a test box:

    sudo sed -i 's/^display_errors = .*/display_errors = On/' /etc/php.ini
    sudo systemctl restart php-fpm
    echo '<?php echo "Total: " . $total; ?>' | sudo tee /usr/share/nginx/html/order.php
    curl -i http://localhost/order.php
    

    What you should see: Warning: Undefined variable $total in /usr/share/nginx/html/order.php on line 1, and a header X-Powered-By: PHP/8.x.x. The path and the PHP version are both leaks.

Part 3: close it the right way

  1. Back up the config, then set the safe values:

    sudo cp /etc/php.ini /etc/php.ini.bak
    sudo sed -i 's/^display_errors = .*/display_errors = Off/' /etc/php.ini
    sudo sed -i 's/^log_errors = .*/log_errors = On/' /etc/php.ini
    sudo sed -i 's/^expose_php = .*/expose_php = Off/' /etc/php.ini
    sudo systemctl restart php-fpm
    
  2. Test again:

    curl -i http://localhost/order.php
    

    What you should see: HTTP/1.1 200 OK, the text Total: with no warning, and no X-Powered-By header.

  3. Find where the error went. PHP-FPM on Amazon Linux 2023 writes the site's errors to its pool log:

    sudo tail -n 5 /var/log/php-fpm/www-error.log
    

    What you should see: PHP Warning: Undefined variable $total in /usr/share/nginx/html/order.php on line 1. Only you, with sudo, can read it.

  4. Delete the test pages: sudo rm /usr/share/nginx/html/hello.php /usr/share/nginx/html/order.php.

Ravindra Bagale's Tip

Display errors on your laptop or test server, never on live. On live, log errors and read the log. One more habit: when you are done with a test page, rm it the same minute. Old info.php pages are found on real servers every day!

Common mistakes

Mistake What happens Fix
Editing php.ini but not restarting PHP-FPM Old settings stay active sudo systemctl restart php-​fpm
Restarting only Nginx PHP settings do not change PHP-FPM reads php.ini, not Nginx
display_​errors = Off and log_errors = Off Errors disappear completely and bugs are hard to find Keep log_errors = On
Leaving phpinfo() or test files online Full server details for anyone Delete test files right after use
502 Bad Gateway after install PHP-FPM is not running sudo systemctl status php-​fpm, then start it

Self-check checklist

0 of 5 done

Try-at-home challenge

PHP-FPM can force a setting for one pool so that a developer cannot switch it back on from code. Find the line in /etc/php-fpm.d/www.conf that does this for display_errors and turn it on.

Check your answer

Run grep -n "display_errors" /etc/php-fpm.d/www.conf. You will find a commented line ;php_flag[display_errors] = off. Change it to php_admin_flag[display_errors] = off (the admin version cannot be changed with ini_set() in code), save, and run sudo systemctl restart php-fpm.

Clean up to avoid charges

Keep the server for Lab 10 if you continue today. Otherwise: EC2 → Instances → Instance state → Terminate (delete) instance.

Samjla ka? Errors on screen for you, in the log for live. Aata pudhe jaauya: Chapter 10 adds MySQL, and we give it a least-privilege user.