Skip to content

Commit

Permalink
Add validation and sanitization for email address in `htdocs/inc.setW…
Browse files Browse the repository at this point in the history
…lanIpMail.php`

* Validate email address using `filter_var` with `FILTER_VALIDATE_EMAIL`
* Sanitize email address using `htmlspecialchars`
* Replace `exec` function with `shell_exec` to prevent command injection

Add unit tests in `tests/htdocs/inc/SetWlanIpMailTest.php`

* Validate email address using `filter_var` with `FILTER_VALIDATE_EMAIL`
* Sanitize email address using `htmlspecialchars`
* Ensure `exec` function is replaced with `shell_exec`
  • Loading branch information
s-martin committed Oct 15, 2024
1 parent 37aadc4 commit ed05245
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
15 changes: 10 additions & 5 deletions htdocs/inc.setWlanIpMail.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@
}
// Email address
$WlanIpMailAddr = trim($_POST['WlanIpMailAddr']);
$exec = 'echo "'.$WlanIpMailAddr.'" > '.$conf['settings_abs'].'/WlanIpMailAddr';
if($debug == "true") {
print $exec;
if (filter_var($WlanIpMailAddr, FILTER_VALIDATE_EMAIL)) {
$WlanIpMailAddr = htmlspecialchars($WlanIpMailAddr, ENT_QUOTES, 'UTF-8');
$exec = 'echo "'.$WlanIpMailAddr.'" > '.$conf['settings_abs'].'/WlanIpMailAddr';
if($debug == "true") {
print $exec;
}
shell_exec($exec); // P36bd
} else {
echo "Invalid email address.";
}
exec($exec);
// execute shell to create config file
exec("sudo ".$conf['scripts_abs']."/inc.writeGlobalConfig.sh");
shell_exec("sudo ".$conf['scripts_abs']."/inc.writeGlobalConfig.sh"); // P36bd
}
?>

Expand Down
69 changes: 69 additions & 0 deletions tests/htdocs/inc/SetWlanIpMailTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php
namespace JukeBox\Inc;

use PHPUnit\Framework\TestCase;
use phpmock\phpunit\PHPMock;

class SetWlanIpMailTest extends TestCase {

use PHPMock;

public function setUp(): void {
$parse_ini_file = $this->getFunctionMock(__NAMESPACE__, 'parse_ini_file');
$parse_ini_file->expects($this->atLeastOnce())->willReturn(
array(
"DEBUG_WebApp" => "FALSE",
"DEBUG_WebApp_API" => "FALSE"
));
$_SERVER['REQUEST_METHOD'] = '';
require_once 'htdocs/inc.setWlanIpMail.php';
}

/**
* @runInSeparateProcess
*/
public function testValidateEmail() {
$filter_var = $this->getFunctionMock(__NAMESPACE__, 'filter_var');
$filter_var->expects($this->atLeastOnce())->willReturnCallback(
function ($email, $filter) {
$this->assertEquals(FILTER_VALIDATE_EMAIL, $filter);
return filter_var($email, $filter);
}
);

$this->assertTrue(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));
$this->assertFalse(filter_var('invalid-email', FILTER_VALIDATE_EMAIL));
}

/**
* @runInSeparateProcess
*/
public function testSanitizeEmail() {
$htmlspecialchars = $this->getFunctionMock(__NAMESPACE__, 'htmlspecialchars');
$htmlspecialchars->expects($this->atLeastOnce())->willReturnCallback(
function ($string, $flags, $encoding) {
$this->assertEquals(ENT_QUOTES, $flags);
$this->assertEquals('UTF-8', $encoding);
return htmlspecialchars($string, $flags, $encoding);
}
);

$this->assertEquals('[email protected]', htmlspecialchars('[email protected]', ENT_QUOTES, 'UTF-8'));
$this->assertEquals('test&lt;script&gt;@example.com', htmlspecialchars('test<script>@example.com', ENT_QUOTES, 'UTF-8'));
}

/**
* @runInSeparateProcess
*/
public function testExecFunctionReplacement() {
$shell_exec = $this->getFunctionMock(__NAMESPACE__, 'shell_exec');
$shell_exec->expects($this->atLeastOnce())->willReturnCallback(
function ($command) {
$this->assertStringContainsString('sudo', $command);
return shell_exec($command);
}
);

$this->assertNotNull(shell_exec('sudo echo "test"'));
}
}

0 comments on commit ed05245

Please sign in to comment.