Using environmental variable to execute a different file - c

I am a little bit stuck. I have a C program which includes the environmental variable $USER. The goal is to use the environmental variable to execute a different file using command injection.
I already tried different ways of declaring USER.
e.g.: Declaring USER as
env USER=">/dev/null ; cat /home/Steve/Public/file2.txt".
Unfortunately, that did not work.
C program:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
// Execute any shell command
void execute(char *cmd)
{
execl("/bin/bash", "bash", "-p", "-c", cmd, NULL);
}
void sanitise(char *password)
{
int i,j;
char tmp[15];
// remove non-alphabet characters from passwords
j=0;
for(i=0; i < 15; ++i)
if(password[i] >= 'a' && password[i] <= 'z') {
tmp[j]=password[i];
++j;
} else break;
tmp[j] = '\0';
strcpy(password, tmp);
}
int authenticate(char *str)
{
char stored_password[15]="";
char pass[15];
char path[128] = "/home/Steve/private/password";
int i;
FILE *fpp;
int auth=0;
fpp = fopen(path, "r");
if(fpp == NULL)
{
printf("Password file %s not found\n", path);
exit(1);
}
fgets(stored_password, 15, fpp);
sanitise(stored_password);
strcpy(pass, str);
sanitise(pass);
if(strcmp(stored_password,pass) == 0)
auth=1;
else {
auth=0;
}
fclose(fpp);
return auth;
}
int main(int argc, char* argv[], char *envp[])
{
char error[256] = "/home/Steve/Public/errormessage.sh $USER ";
char pass[15];
if(argc < 2)
{
printf("Usage: %s password\n", argv[0]);
return 0;
}
// copy only 15 characters from user input, to prevent stack smashing
strncpy(pass, argv[1], 15);
pass[14]='\0';
if(!authenticate(pass)) {
// Log all failed attempts
printf("Wrong password. This incident has been logged.\n");
strcat(error, pass);
execute(error); // Execute script to log events
return 0;
}
// Display 'secret-file2'
execute("cat /home/Steve/Public/file2.txt");
return 0;
}
The goal would be to make the program output the file from the variable USER and not the initial file path declared in the error char. Ideally, without changing the C program at all.
Can anyone please tell me what I am missing here?

If you wish to use your C program with a fresh seted ${USER} variable "env -i" is what you should use.
Example: env -i USER='injected code' name_of_c_program

If that's what the program is doing, it will execute the following command:
/home/Steve/Public/errormessage.sh $USER <provided-password>
Since you control the provided password (that is, you can pass what you want in argv[1] as long as it's max 14 characters), you can just execute another bash shell as well, and then use it to run any command you want. There really is no need to tamper with $USER.
$ ./program '; bash'
Wrong password. This incident has been logged.
$ <--- another bash shell has now started
$ cat /home/Steve/Public/file2.txt
...contents of file2.txt...
If you want to run it with a single command, this should work:
echo 'cat /home/Steve/Public/file2.txt' | ./program '; bash'

Use 'getenv' library function to get the value of environment variable(USER). And then run the command using 'system(path)'.

#include <stdlib.h>
...
char path[256] = "/home/Steve/Public/file1.sh ";
strcat( path, getenv("USER") );
//char path[256];
//sprintf(file,"%s%s","/home/Steve/Public/file1.sh ",getenv("USER"));
...

Related

Beginner Q -ARGV and multiple files

Good afternoon, Old man trying to learn new tricks here,
I have been given an assignment that I am trying to work my way through but I am stuck as I don't fully understand the argv[]
I have 4 files I want to read from and eventually use malloc and realloc but thats further down.
My initial plan was to try read one file and get it onto the command line. I had it opening but made that many changes that now I'm lost.
Think my problem lies with argv[4] as i dont understand it, when I put 4 it goes into theloop and errors but with 1 it just bombs out.
If someone can point me in the direction I am going wrong here it would be great
Thanks
struct Person { char lname[20]; char fname[20]; int id; };
int i, N;
struct Person *student;
int main(int argc, char *argv[])
{
FILE *outputfile;
printf("Please enter the name of the file to open: ");
scanf("%s", argv[4]);
outputfile = fopen(argv[4], "r") ;
if (outputfile==NULL){
perror(argv[1]);
fprintf(stderr,"Error while opeining file\n");
exit(-1);
}
You don't have to use argv[]. Argv is an array of strings that store the arguments passed in when running the executable. If you run the executable like this: ./a.out, then argv only contains one element, which is the path of the executable itself. If you run the program like this, and you try to access argv[4], it does not give you an error, but if you debug it using GDB, it will output the following: warning: Invalid parameter passed to C runtime function.
You could pass in a file on the command line like this: ./a.out yourfile.txt. In this case, argv[0] will be the path of the executable a.out, and argv[1] will be the string "yourfile.txt".
It might be easier to completely drop the use of argv and store the user input for the filename in a string. You can then pass that string as an argument to fopen. This would look something like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char fileName[30];
char ch;
printf("Please enter a file name\n");
scanf("%s", fileName);
FILE *outputFile = fopen(fileName, "r");
if(outputFile == NULL) {
printf("Could not open %s\n", fileName);
exit(-1);
}
}
Use constants (NAME_LEN) instead of hard-coding magic values.
Prefer multiple lines for your struct. It's easier to read and version control systems prefer lines for diffs.
Avoid global variables.
Do a boundary check using argc (count of elements in argv) before you read argv. argv[0] is the name of your program, argv[1] is the first argument.
Treat argv as read-only, i.e. don't do scanf("%s", argv[4]).
Prefer to initialize variables instead of declaring and assigning a value separately. It's easy to forget setting a variable before use which leads ot undefined behavior. Initialization might be faster, too.
Your file handle is called outputfile but with fopen() you use the mode of r for reading. Either mode should be w or you want to change the variable name to inputfile.
#include <stdio.h>
#include <string.h>
#define NAME_LEN 20
struct Person {
char lname[NAME_LEN];
char fname[NAME_LEN];
int id;
};
int main(int argc, char *argv[]) {
char filename[FILENAME_MAX];
if(argc > 4) {
strcpy(filename, argv[4]);
} else {
printf("filename? ");
fgets(filename, FILENAME_MAX, stdin);
filename[strcspn(filename, "\n")] = '\0';
}
FILE *outputfile = fopen(filename, "w");
if(!outputfile) {
// ...
}
fclose(outputfile);
}
and you would run your program with either:
$ ./a.out dummy dummy dummy output.txt
or
$ ./a.out
filename? output.txt
It sounds as if you are expected to provide 4 file names as command line parameters. In which case you should be doing this:
#include <stdio.h>
int main (int argc, char *argv[])
{
const int files = 4;
if(argc != files+1)
{
printf("Usage: myprog file1 file2 file3 file4");
return 0;
}
FILE* fp [files];
for(int i=0; i<files; i++)
{
fp[i] = fopen(argv[i+1], "r");
...
}
...
}

Call bash command within C file with a variable

I hope my question is clear. I need to read a file in C, store the contents of the file and then use this variable in a bash script.
For example, there is a file called "test.txt" which contains "aaa". Here is the call in C:
#include <signal.h>
#include <time.h>
char ch;
FILE *fp;
int main(int argc, char **argv) {
fp = fopen("test.txt", "r");
char contents[9] = "";
if( fp == NULL ) {
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
int i = 0;
while( ( ch = fgetc(fp) ) != EOF ) {
contents[i]=ch;
i++;
}
contents[9]=0;
fclose(fp);
system( "echo 'hi'");
puts(contents);
}
Now I need to use a bash script to read the file name that has the "aaa" in its name.
system("cat /home/user/$contents.txt");
I have tried finding some other solutions but I have only encountered popen so far that I failed to implement. If I used bash, its a very simple one liner, thus why I am trying to implement it. Are there any other options?
If I understand your question correctly, maybe you can pass contents to bash via environment variable.
http://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access
here's an example code:
#include <stdlib.h>
int main(){
char * message = "hello";
setenv("contents", message, 1);
system("echo $contents");
}
the output of this script is
hello

Caesar Cipher C program - format %i expects argument of type int * but has type int

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, const char *argv[])
{
argc++;
int number;
printf("Enter word you would like encoded\n");
scanf ("%s %i", argv[0], atoi(&argv[1]));
printf("%s", argv[1]);
int len = strlen(argv[1]);
for (int i = 0; i < len; i++)
{
char offsetWord;
offsetWord = atoi(argv[i])+len;
putchar(offsetWord);
}
putchar('\n');
return 0;
}
I am trying to make a C Caesar cipher program that compiles from a Linux command line. The requirements:
1) ./rotn
abcdef
nopqrs)
2) ./rotn dog
Gur dhvpx oebja sbk whzcf bire gur ynml qbt.
3) Writing to a file via "rotn".
./rotn dog fox
$ cat fox
Gur dhvpx oebja sbk whzcf bire gur ynml qbt.
4) using various shifts
./rotn -8 dog
Bpm ycqks jzwev nwf rcuxa wdmz bpm tihg lwo.
This is as far as I've gotten. I have been bogged down with compiling errors. The one I'm having right now is "warning format %i expects argument of type int * but argument 3 has type of int.
Any suggestions?
As already pointed out in the comments, you have mixed up a few things:
argc and argv are the arguments passed to the program when it is called. There is always at least one argument, argv[0], the name of the program. You should use this information to parse your command line.
scanf scans formatted input from stdin. You don't really need formatted input here, you can read a whole line with fgets or you can read a single character with fgetc. You store the scanned data in new variables; don't reuse argv for that.
A program that interprets your command line might look like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int shift = 13; // default shift
const char *infile = NULL; // default is stdin
const char *outfile = NULL; // default is stdout
int i = 1;
if (i < argc && argv[i][0] == '-') {
shift = atoi(&argv[i][1]);
if (shift <= 0) {
fprintf(stderr, "Illegal shift.\n");
exit(1);
}
i++;
}
if (i < argc) {
infile = argv[i];
i++;
}
if (i < argc) {
outfile = argv[i];
i++;
}
if (i < argc) {
fprintf(stderr, "Illegal extra argument.\n");
exit(1);
}
printf("shift: %d\n", shift);
if (infile) printf("infile: %s\n", infile);
if (outfile) printf("outfile: %s\n", outfile);
// now use this inforation in your program
return 0;
}
Of course, you must still implement the encoder itself. Here are some hints:
stdin is a valid file handle, so you could use that if the user hasn't specified a file name or a handle returned from fopen(infile, "r") otherwise. You can test whether the user has specified a file name with if (infile) ... Remember to close the file when it isn't stdin, though.
The same logic can be used for the output file, except that you must open the file in write mode "w" and that you should use fprintf or fputc.

Print in text instead of binary format in cat implementation

The implementation of the cat program is printing in binary format on the Ubuntu terminal. I am using the stdout macro (object of type FILE*).
#include <stdio.h>
main(int argc, char** argv)
{
FILE *fp;
void add(FILE*, FILE*);
if (argc==1)
add(stdin,stdout);
else
while(--argc>0)
{
if ((fp=fopen(*++argv,"r"))==NULL)
{
printf("cat:can't open %s\n",*argv);
return 1;
}
else
{
add(fp,stdout); // printing all the file content on the screen.
fclose(fp);
}
return(0);
}
}
void add(FILE*p,FILE*q)
{
int c;
while((c=fgetc(p))!=EOF)
{
fputc(c,q);
}
}
Now, how can I print in text format instead of binary format?
The error is in how you loop over the arguments. Stripping your code of the actual file processing and replacing it with a print statement (and also nicely indenting it), we get:
if (argc == 1)
printf("stdin\n");
else
while (--argv > 0) {
printf("'%s'\n", *++argv);
}
You have mistyped argc for argv in your code. That means you decrement the pointer to the first argument and then increment it again before processing the file. Effectively, you end up processing argv[0] over and over. That file is the program itself, which is binary and contains many non-printable characters.
You should chzange the loop to
while (--argc > 0) {
printf("'%s'\n", *++argv);
}
or use a pedestrian for loop:
for (int i = 1; i < argc; i++) {
printf("'%s'\n", argv[i]);
}
program has no any error only typo mistake argv instead argc rest all is good even than above suggested answer

reading command line argument

can anyone point me to the problem over here? This compiles but it won't print anything. I need to compare the string from command line argument with the string "hello".
Thanks!
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc == 0)
{
printf("No arguments passed!\n");
}
char *str = argv[1];
if(strcmp("hello", str)==0)
{
printf("Yes, I find it");
}
else
{
printf("nothing");
}
return 0;
}
My ESP suggests that you're running this in an interactive editor/debugger, such as Microsoft Studio. You probably haven't configured the environment to pass any command-line parameters, so you expect to see nothing as your output.
However, you access argv[1], which does not exist, creating a seg-fault, and the program aborts before there is any output.
To fix this, check the value of argc first, and make sure you don't access invalid memory.
Also, I recommend putting a \n at the end of each printf to help flush any buffered output to the console.
int main(int argc, char *argv[])
{
if (argc == 0)
{
printf("No arguments passed!\n");
}
else if(strcmp("hello", argv[1])==0)
{
printf("Yes, I find it\n");
}
else
{
printf("nothing\n");
}
return 0;
}
When you run this, you should see:
$prompt: myprogram
No arguments passed!
$prompt: myprogram hello
Yes, I find it
$prompt: myprogram world
nothing
The problem is the command you're using to run it. As you commented:
i run program > test hello or > test hi and the output is nothing
The > is redirecting output, and ends up giving you no command line arguments. What you want is simply program hello without the output redirection.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 2 || 0 != strcmp("hello", argv[1]))
printf("nothing\n");
else
printf("yes, found it\n");
return 0;
}
and output
bash-3.2$ gcc 1.c -o 1
bash-3.2$ ./1 hello1
nothing
bash-3.2$ ./1 hello
yes, found it
bash-3.2$ ./1
nothing
Try calling your program something different to 'test'

Resources