C# process with an input and output file - c#

When creating a new process you can give some StartInfo with it before you start the process.
But how would one give the input of/output to parameter.
the output to is achievable through a File.WriteAllLines() with the output of the command.
But now the following must me achieved:
C:\Windows\System32\inetsrv\appcmd.exe add site /in < iisSite.xml
But when we give the
add site /in < iisSite.xml
with the arguments method of StartInfo appcmd thinks it is a parameter for it's program.
See this error
Failed to process input: The parameter
'd:\import\iisSite.xml' must begin with a / or - (HRESULT=80070057).
So we need somehow the same parsing as the command prompt would do it.
What could be possible is something like ReadAllLines and use that as an input, but I thought maybe there is a better solution.
Any suggestions?
Thanks in advance!

Stream redirection like that is a feature of the command processor cmd. If you want to do that then you need to invoke it and send your arguments. See EDIT2 and EDIT3 in this post.
EDIT
And direct from Raymond

using < is not the way to do it. Use >
so for example: appcmd.exe add site /in > iisSiteExport.xml
and have your program spit out all the output as if it was printing to the Console

Related

Why input redirection works by default for sudo and not for passwd? (.NET)

Simple F# script:
#!/usr/bin/env fsharpi
open System
open System.Diagnostics
let Exec (command: string, arguments: string, echo: bool) =
let psi = new System.Diagnostics.ProcessStartInfo(command)
psi.Arguments <- arguments
psi.UseShellExecute <- false
if (echo) then
Console.WriteLine("{0} {1}", command, arguments)
let p = System.Diagnostics.Process.Start(psi)
p.WaitForExit()
p.ExitCode
Exec("sudo", "-k ls -lha /root", true)
Exec("passwd", "myusername", true)
(But actually this is a generic ".NET on Linux" question I guess, because you could write the same in C#)
Why the first Exec() call works and the second one doesn't?
The first one calls sudo properly, and sudo asks me for my password (I can even fail to type it, and it asks it to me again, so it's not related to number of carrier returns employed in stdin).
However, the second one only allows me to write one character and suddenly drops out. It seems to not redirect characters to passwd properly, as the latter doesn't let me write the complete password, and fails saying that passwords don't match.
Can someone explain this?
By default, passwd usually doesn't use standard I/O (mostly for security reasons). You can check the man page for your passwd to see if there's an option to enable stdio - e.g. passwd --stdin. If not, you'll need to use a different utility, like chpasswd.
All in all, nothing to do with .NET. You couldn't do the same thing from your shell either :) Passwords aren't for applications or scripts - they're for users.

OS Command Injection from Process.Start

My application is using Process.Start for opening another application to run. VeraCode [a security software scanning tool] reported this command as OS Command Injection Vulnerable. I would like to get some comment. I have found a lot of information on the web regarding to filter the input or to constraint the program name; however, I am curious to see if there's any other alternatives of using Process.Start?
Edit:
Thanks for the comment, here is one of the sample, and yes, it is getting input from users:
public static void Run(string fileName, string arguments, bool waitForExit)
{
Process p = Process.Start(fileName, arguments);
if (waitForExit)
p.WaitForExit();
}
Thanks!
This is a command injection vulnerability because you have not filtered out the users input from the function and directly appended to the process.start()
Due to this, the tool has marked it as a vulnerability.
To avoid this issue you should use regex method to filter out the bad characters and depending on what that function is going to do when it gets run.
for eg. you function is created only to check from this path c:/users/docs.txt
then that function should not get executed for c:/admin/docs.txt.
This is how you need to validate before sending the user data directly into the process.
For more information refer this awesome link : https://dotnet-security-guard.github.io/SG0001.htm
or
https://www.veracode.com/security/dotnet/cwe-78
The Process class is nothing else then a Managed wrapper class the the Native Create Process and its Variations like Create Process As User .
Process MSDN
Process
SourceCode
I don't think that there is another way to start a process than this, because every other solution would also call the WinAPI function. ( because this function (or its overloads and Variations) is the only way to start a process in Windows).
Personally, I have not heard anything about a problem with Process.Start please clarify the problem
regards
I ran into this as well. You need to set the UseShellExecute property to false. Then Veracode will not consider it a vulnerability.
using (WinProcess myProcess = new WinProcess())
{
myProcess.StartInfo.FileName = "notepad.exe";
myProcess.StartInfo.Arguments = Path.GetFileName(fullPath);
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(fullPath);
myProcess.StartInfo.RedirectStandardOutput = false;
myProcess.Start();
}

Start a command line including arguments from C#

I need to start a complete command line like "app.exe /arg1:1 /arg2:true" from my C# app.
Process.Start and ProcessStartInfo needs to have the filename and arguments property set. Is there a way to mimic a true shell-like execute (like the one when you press WIN+R)?
Yes, you can launch cmd.exe with the full command-line you want to send as the arguments.
info.FileName = "cmd.exe";
info.Arguments = "app.exe /arg1:1 /arg2:true";
ProcessStartInfo.UseShellExecute makes Process.Start behave exactly like the Shell:
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute.aspx
I've found the solution I've been looking for: Executing another program from C#, do I need to parse the "command line" from registry myself?
Thanks again for your help!

Strange XML modification when input and output it in console app using Visual Studio

I have a simple console app that was creted in c# using VisualStudio. It has a input parameter and return it to output.
This is the code:
static void Main(string[] args)
{
string msg = args[0];
Console.WriteLine(msg);
}
Then I try to pass a param that contain a xml as string: "<messages><message>message</message></messages>". There is nothing wrong if I will use console for calling application. But in the case when I trying to debug such application I have added parameter string to Command line arguments on the Debug tab.
After this I have got unexpected output like:
^<messages^>^<message^>message^</message^>^</messages^>
Why we have such output and how to overcome this? Thanks in advance.
The simplest solution for this issue should be replacing unwilling characters like here:
static void Main(string[] args)
{
string msg = args[0];
Console.WriteLine(msg.Replace("^","");
}
But the reason of such behavior placed somewhere in the core of the operation system. Windows handle this situation like launch a batch file from command line with parameters. Following the link that was presented in the answer of #Artem K. you can find out that here is two way to overcome such situation. Unfortunately, no one work with this issue. Possible, because Visual Studio add something from yourself in the question how to pass args for launching batch.
How to avoid cmd.exe interpreting shell special characters like < > ^
in Shell, the < and > has special meanings concidering steam redirection..
what makes dir /w > myDirectory.txt possible or tree | more Etc...
Follow #Artem Koshelev post to get around that.

system() to c# without calling cmd.exe

how to translate system("") to C# without calling cmd.exe?
edit: i need to throw something like "dir"
If I correctly understood your question, you're looking for Process.Start.
See this example (from the docs):
// Opens urls and .html documents using Internet Explorer.
void OpenWithArguments()
{
// url's are not considered documents. They can only be opened
// by passing them as arguments.
Process.Start("IExplore.exe", "www.northwindtraders.com");
// Start a Web page using a browser associated with .html and .asp files.
Process.Start("IExplore.exe", "C:\\myPath\\myFile.htm");
Process.Start("IExplore.exe", "C:\\myPath\\myFile.asp");
}
Edit
As you said you needed something like the "dir" command, I would suggest you to take a look at DirectoryInfo. You can use it to create your own directory listing. For example (also from the docs):
// Create a DirectoryInfo of the directory of the files to enumerate.
DirectoryInfo DirInfo = new DirectoryInfo(#"\\archives1\library");
DateTime StartOf2009 = new DateTime(2009, 01, 01);
// LINQ query for all files created before 2009.
var files = from f in DirInfo.EnumerateFiles()
where DirInfo.CreationTimeUtc < StartOf2009
select f;
// Show results.
foreach (var f in files)
{
Console.WriteLine("{0}", f.Name);
}
As other folks noted, it's Process.Start. Example:
using System.Diagnostics;
// ...
Process.Start(#"C:\myapp\foo.exe");
I need to throw something like "dir"
If you need to run DIR, then you need to call cmd.exe as dir is internal to cmd.exe
Not sure if I understand your question. Are you looking for Process.Start?
Do you actually want the equivalent? You may not depending on what exactly you're trying to do.
For example calling copy from the command line has a C# equivalent itself, File.Copy, for dir there's a whole Directory class for getting info (these are a quick 2 out of thousands of examples). Depending on what you're after, C# most likely has a library/function for the specific command you're trying to run, usually a more robust method as well, instead of a global handler.
If the global "invoke this" is what you're after, then as the other answers suggest, using the System.Diagnostics.Process class is your best bet.
If you want to execute a command-line (cmd.exe) command, such as "dir" or "time" or "mkdir", pass the command as an argument to cmd.exe with the flag /C.
For example,
cmd.exe /C dir
or
cmd.exe /C mkdir "New Dir"

Categories