PHP | Passing parameters into Powershell script - php

I am trying to create a PHP application which runs powershell scripts.
I have a file called "change.ps1" which is a powershell script, here is the content of that file:
Param([string]$username, [string]$password)
Import-Module ActiveDirectory
$newpwd = ConvertTo-SecureString -String "$password" -AsPlainText –Force
Set-ADAccountPassword $username -NewPassword $newpwd –Reset
Now i have a PHP page which uses the shell_exec() function to run this script and pass TWO parameters to it, which you can see above is used in the ps1 file ( $username, $password):
$psscriptpath = "c:\inetpub\htdocsscripts\change.ps1";
shell_exec("powershell.exe -executionpolicy remotesigned -File" . $psscriptpath . " -username \"" . $username . "\" -password \"" . $password . "\"");
At the moment this does not work (the page never finishes loading aka times out). So the question is, am i doing this correctly? where have i gone wrong. The theory behind this is relatively simple, use PHP to pass variables through as parameters into a powershell script.
Thanks for taking a look, and let me know if you have questions.
UPDATE:
I tried running the script directly via the cmd to see if the problem was in the script its self. Here is the error i was shown:
http://puu.sh/aXuH3/b8db154625.png
SECOND UPDATE:
I have fixed the error on the CMD, it was an encoding issue. However when i try to run the php page, i still get the time out issue:
http://puu.sh/aXEdY/22cc87310c.png

ok, seems you are missing something.
you need to point to the absolute path of the script. If you saw my message on wizpert, i did a cd command to the directory of the script to ensure the correct environment:
c:\>cd c:\my\directory\with\powershells
then you can execute your powershell with all the variables on it. Also try to do it via cmd to see if it produces any messages. If you see there is a timeout, it means that the process or is hanging or the web user does not have enough rights to execute shells.
If so, modify your php.ini or whatever let it know that the www-data user (in apache, not sure on IIS) has rights to execute commands.\
also it could be that you are executing that parameter wrongfully:
Param([string]$username, [string]$password)
Import-Module ActiveDirectory
$newpwd = ConvertTo-SecureString -String $password -AsPlainText –Force
Set-ADAccountPassword $username -NewPassword $newpwd –Reset
Make $password without quotes on the powerscript.

This is a solution for Windows 2012R2 server - Apache 2.4 - PHP 7.4
The trick is to switch the codepage in the command environment. Below shows that UTF is well revieved inside the ps1 file, since the content of the test.txt holds the correct data.
The problem arise, when the output from PowerShell goes back to the server encoded in codepage 850.
A change to codepage 65001 (UTF8) is the solution.
This is test.ps1
param([String]$p1)
$loc = $env:LOCALAPPDATA
"a${p1}b" | Out-File -FilePath "${loc}\test.txt" -Encoding utf8
chcp
chcp 65001
write-host "a${p1}b"
chcp 850
This is output from CDM.EXE
C:\PowerShell>powershell -file test.ps1 -p1 ÆØŁódźÅ€
Active code page: 850
Active code page: 65001
aÆØŁódźÅ€b
Active code page: 850
This is PHP
echo "<pre>";
$psscriptpath = "C:/powershell/test.ps1 -p1 ÆØŁódźÅ€";
echo $psscriptpath . '<br>';
echo 'From PowerShell:<br>';
$psData = shell_exec("powershell.exe -executionpolicy remotesigned -File " . $psscriptpath);
echo $psData . '<br>';
echo 'From readfile: ';
readfile(getenv('LOCALAPPDATA') . "\\test.txt");
echo "</pre>";
This is from my browser:
C:/powershell/test.ps1 -p1 ÆØŁódźÅ€
From PowerShell:
Active code page: 850
Active code page: 65001
aÆØŁódźÅ€b
Active code page: 850
From readfile: aÆØŁódźÅ€b
A final comment: Always switch back to you localized codepage after the data has been generated from some application.
I have experienced stange things to hanppend in the CMD window when it is in 65001 mode
This trick also works when using the PostgreSQl psql.exe to output data. I assume the same goes for Mysql and others.

Related

Laravel exec() produce a mysql-dump empty file

I'm using exec() for execute mysql-dump but it's generating an empty file on apache, but when i use the "php artisan serve" the file is generated correctly, the output file has the same user and group in apache and in the artisan serve.
Using: Ubuntu 14.04 and Xamp 5.6.12
$dir = substr(__DIR__, 0, 24).'database/backups/';
$newBackup = Backup::create();
$command = 'mysqldump -uroot lions > '.$dir.$newBackup->getDateTimeString().'.sql';
exec($command);
Ok, I was facing the same problem with Laravel 5.6 and running windows though. Before anything, you should make sure to include the password argument (either as --password or -p), even if its empty.
$cmd =
"mysqldump -h " . env('DB_HOST') .
" -u " . env('DB_USERNAME') .
" -p\"" . env('DB_PASSWORD') . "\"" .
" --databases " . env('DB_DATABASE');
The main issue is that even though several sources note that exec waits until the process is complete there is no way to know for sure, leaving that aside, since processes could be owned by different users it'd probably be better if you created a temporary file and then flashed the contents of the output array into it rather than hoping for mysqldump to do it for you.
$output = [];
$name = "your_random_file_name.sql";
exec($cmd, $output);
$tmppath = tempnam(sys_get_temp_dir(), $name);
$handle = fopen($tmppath, "w");
fwrite($handle, implode($output, "\n"));
Finally, write the main file to your desired location, in my case I upload it directly to an Amazon S3 bucket, and close the temporary file.
Storage::disk('myS3bucket')
->putFileAs("backups", new File($tmppath), $name);
fclose($handle);
I know it seems redundant but, as I mentioned above, there is no way to know for sure.
Indeed, in a development environment, it is customary not to set a password for the database. And that's why your command does not work.
But in a production environment, you are obliged to set a password for the database.
Try in your production environment (ie with a password!), And you will see that the script works.
I don't have a solution for this problem but I do know it should be possible to do this. If I enter the following command in my terminal the mysqldump works:
mysqldump "--user=root" "--password=" dbname > ~/Desktop/export.sql
But when I use this command in my scheduler as below, I gett an empty file.
$schedule->exec("mysqldump \"--user=".env('DB_USERNAME')."\" \"--password=".env('DB_PASSWORD')."\" ".env('DB_DATABASE')." > export.sql")->everyMinute();
Maybe there is someone who knows why this doesn't work? I'm guessing it's a permission issue, but I leak experience in this.

PHP CGI | IIS | Execute Permissions

I have a PHP page which uses the shell_exec command:
$psscriptpath = "C:\inetpub\htdocs\school_panel\scripts\change.ps1";
shell_exec("powershell.exe -executionpolicy remotesigned -File " . $psscriptpath . " -username \"" . $username . "\" -password \"" . $password . "\"");
However, when i submit the page aka have the code above executed, my page just times out ( never finishes loading until the time out timer is reached and i get this error):
http://puu.sh/aXEdY/22cc87310c.png
Now i have done some research and it appears that i need to somehow set some sort of executing script permissions/rights in IIS/PHP? mabey change some php.ini config? I really am not sure.
I have already tried adding permissions for powershell for IUSER and etc. I have even set the execution policy on powershell to remotesigned. It appears i have the FastCGI and CGI module installed on IIS.
I have also tried running the script via CMD using php and it WORKS, just not in the browser.
Regards
Your solution is as simple as this:
shell_exec("powershell.exe -executionpolicy remotesigned -File {$psscriptpath} -username {$username} -password {$password} < NUL");
You do not need to surround parameters in double quotes, and in order to prevent powershell from hanging, you need to pass < NUL at the end of the line.
The < NUL will force the output from PowerShell back to PHP.

PHP | Executing commands | Shell_exec() | Active Directory

Thanks for taking your time to read about my problem, so lets get straight into it.
My ultimate (end) goal is to be able to have a web base PHP app which lets users modify active directory for users inside a network.
I have found out commands that need to be ran via Powershell to change user passwords inside an active directory.
Now here is my current setup:
There is one main server where IIS is installed and the web application sits at.
There will be several computers connected to the network which navigate to the website and execute these commands
I have tried adding the code:
$query = shell_exec('Import-Module ActiveDirectory');
$query = shell_exec('$newpwd = ConvertTo-SecureString -String "'.$safe_password.'" -AsPlainText –Force');
$query = shell_exec('Set-ADAccountPassword "'.$safe_username.'" -NewPassword $newpwd –Reset');
Now here are my questions:
1) Once a computer runs that page and has those commands executed, are the commands going to be executed in the main server? where powershell is installed and permissions are granted. If not, my whole app wont work, are there any other solutions?
2) those commands are all powershell commands not cmd.exe commands. So does shell_exec() even run those commands in powershell, or just in cmd.exe. If it only runs in cmd then this wont work, how can i make it run via powershell?
I would appreciate if you could answer and help me out here, thanks alot.
Setup the Parameters in your PowerShell like this:
Param([string]$username, [string]$password)
Then call your script like this:
shell_exec("powershell.exe " . $psscriptpath . " -username \"" . $username . "\" -password \"" . $password . "\"");

executing a Powershell script from php

I'm trying to execute a powershell script from PHP, but it does not seem to work.
The script 'newEvent.ps1' creates an event on the Exchange server.
$psPath = "powershell.exe";
$psDIR = "C:\\wamp\\www\\ant\\assets\\ps\\";
$psScript = "newEvent.ps1";
$runScript = $psDIR. $psScript;
$runCMD = $psPath." ".$runScript." 2>&1";
echo "\$psPath $psPath <br>";
echo "\$psDIR $psDIR <br>";
echo "\$psScript $psScript <br>";
echo "\$runScript $runScript <br>";
echo "\$runCMD $runCMD <br>";
exec( $runCMD,$out,$ret);
echo "<pre>";
print_r($out);
print_r($ret);
echo "</pre>";
It outputs:
$psPath powershell.exe
$psDIR C:\wamp\www\ant\assets\ps\
$psScript newEvent.ps1
$runScript C:\wamp\www\ant\assets\ps\newEvent.ps1
$runCMD powershell.exe C:\wamp\www\ant\assets\ps\newEvent.ps1 2>&1
Array
(
[0] => File C:\wamp\www\ant\assets\ps\newEvent.ps1 cannot be loaded because the execut
[1] => ion of scripts is disabled on this system. Please see "get-help about_signing"
[2] => for more details.
[3] => At line:1 char:39
[4] => + C:\wamp\www\ant\assets\ps\newEvent.ps1 <<<<
[5] => + CategoryInfo : NotSpecified: (:) [], PSSecurityException
[6] => + FullyQualifiedErrorId : RuntimeException
[7] =>
)
If I run powershell.exe C:\wamp\www\ant\assets\ps\newEvent.ps1 on the command-line, it works fine.
This is the first time im attempting something like this. I ran Set-ExecutionPolicy RemoteSigned -Scope LocalMachine but it still gives me the same error.
In fact I ran Set-ExecutionPolicy unristricted, but it's still the same.
It looks like your command is surrounded by single-quotes. I think if you remove them, your command should run.
shell_exec returns the output from the command you run. To further diagnose, store the output in a variable, then print it out:
$output = shell_exec($runCMD);
echo '<pre>' . $output . '</pre>';
Make sure you enable running scripts. That capability is turned off by default. You have to enable the execution of scripts on each machine you want to run PowerShell scripts. Run about help_signing for more information.
Microsoft recommends running Set-ExecutionPolicy RemoteSigned -Scope LocalMachine. This allows all user accounts on a machine to run local scripts without issue, but requires confirmation to run scripts downloaded from the internet. This needs to be run in an administrative prompt. If you are running a 64-bit operating system, you'll need to do this from both a 64-bit and 32-bit shell.
To execute a script file from PHP you should follow this example:
You should start out with a simple PowerShell script. Create a text file with the name "test.ps1".
Now type the following script in this file:
Get-Process
Place the code below in a PHP file named "test.php". Remember to update the file path in the following example "C:/PATH/TO/test.ps1" with the absolute path to your own script file.
echo "<pre>";
echo Shell_Exec('powershell -InputFormat none -ExecutionPolicy ByPass -NoProfile -Command "& { . \"C:/PATH/TO/test.ps1\"; }"');
echo "</pre>";
The above code will output a list of all your running processes.
Note that I was running my script in a Windows PC and I was getting error messages because of the file path. So, I replaced all backslashes from the file path with forward slashes.
The following parameters are worthy of note:
-InputFormat none - Thanks to a bug in PowerShell, the script will never finish running or exit. This parameter provides a workaround this bug.
-ExecutionPolicy ByPass - Without this parameter, the code will throw a low privilege error message.
-NoProfile - With this parameter, your script will run faster and more predictably.
-Command - By loading your script file through the "-Command" parameter, instead of the "-File" parameter, you will have greater flexibility.
If, for example, you needed to call a function inside your script and send parameters to that function, you would need to use the "-Command" parameter.
Here is an example of how to call a function "my-function" inside your PowerShell script file and pass the parameters "-myParameter" and "-myOtherParameter" to that function with the values "10" and "15" respectivelly:
echo "<pre>";
echo Shell_Exec('powershell -InputFormat none -ExecutionPolicy ByPass -NoProfile -Command "& { . \"C:/PATH/TO/test.ps1\"; my-function -myParameter 10 -myOtherParameter 15 }"');
echo "</pre>";
Found this on another website and thought I would pass it along:
I was debugging a program that uses Windows API (Creating a Child
Process with Redirected Input and Output) to capture stdout of
Microsoft’s Windows PowerShell.
Script passed to PowerShell (-File switch) didn’t execute and
PowerShell just hanged until killed by Task Manager.
It turns out that you need to use undocumented parameter “-InputFormat
none”:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -InputFormat none -File file.ps1
This did the trick for me.
Use "-executionPolicy Unrestricted" along with the command "powershell.exe". Therefore the command will be :
powershell.exe -executionPolicy Unrestricted
Then it will surely work.

How to export full mysql database with php script...? Problem in using 'mysqldump'

i am using this command to backup my full mysql database..
$backupFile = $dbname . date("Y-m-d-H-i-s") . '.sql';
$command = "mysqldump -h$hostname -u$username -p$password $dbname > $backupFile";
system($command);
I am getting blank file.
And i am using XAMMP on windows.
I have already used exec() but also getting blank file.
And but on shell it has successfully done.
Whats wrong in this code.
The best thing you can do is check what is going wrong. You might even want to check outside of PHP to see what you are doing. So echo your $command, and look at it, see if it looks correct. Then use it on the commandline, see if you can get it to work.
Possible attention points:
Do you have any 'strange' characters (like &) in your password? You might need to escape them
Is the mysqldump command available? (is it in your PATH, or in the dir where you are running this from
Are you allowed to do any system/exec commands at all?
Is the user that runs your php code (apache?) allowed to do this command?
Is the user that runs this code allowed to write in this directory?
To test your current command, you might want to do this:
- replace your system command with an echo: echo $command;
- run the script and copy the command you see there.
- Open a terminal. (start->run->"cmd")
- goto the dir where your script is / runs.
- paste /type the command.
- check your result.
I do not know what happens when you do not have a password, but still supply the -p option. It might try and ask for a password anyway, as you've indicated you want to enter a password, but have not provided it. I do not know this for sure, that's why you might want to check it. (#wimvds confirms in the comment: if you supply a -p and no password, you'll get a "password: " dialog.)
In the commandline you can check what command you need to type to get the mysqldump to work. If that's ok, then make sure your script actually issues that command. Then test again with the script.

Categories