char *BuildName(char *path, char *name)
{ char buffer[256];
sprintf(buffer,"%s/%s",path,name);
return buffer;
}
name = BuildName("/home/mark",".cshrc");
fp = fopen(name,"w");
Describe an explain a safe way to open the file for a system
process. Describe what can go wrong in this kind of simple operation.
man 2 chmod man statChange your security kit program file appl.cpp so that it contains the following:
main ()
{ FILE *fp;
struct stat statbuf;
umask(0); // Change this and remove it...see what happens
if ((fp = fopen("newfile","w")) == NULL)
{
perror("fopen");
return error;
}
fprintf(fp,"This is an example file.");
fclose(fp);
// Now check permissions
if (stat("newfile",&statbuf) == -1)
{
perror("stat");
return error;
}
printf("The file perms on the file are %o\n",statbuf.st_mode & 07777);
chmod("newfile",0755);
if (stat("newfile",&statbuf) == -1)
{
perror("stat");
return error;
}
printf("The file perms on the file are now %o\n",statbuf.st_mode & 07777);
}
Compile and run this program. Try deleting the umask line from the program
and changing the value of umask in your shell instead:
% umask 0 % ./appl % umask 022 % ./appl % umask 077 % ./applRemember to delete the file newfile in between, to see the effect of file creation. This inheritance of file attributes can cause problems!
main()
{ FILE *pp;
char line[1024];
line[0] = '\0';
if ((pp = popen("ls -al","r")) == NULL)
{
printf("cannot open\n");
exit(0);
}
while(!feof(pp))
{
fgets(line,1024,pp);
printf("comm: %s",line);
}
printf("Done with program\n");
pclose(pp);
}
Notice how the program does not specify a path for the command
ls, but the program compiles and runs anyway. The reason for
this is that an implicit Bourne shell is used to interpret the
command, and the user path includes a command ls.
Now change
popen() -> cfpopen() pclose() cfpclose()in the program and note that the command is no longer executed. Instead a blank stream is opened, to the command which was not found. Although this is slightly dubious behaviour, it indicates that no shell is now involved in the attempt at execution of the command.
Note: a path should always be specified. Check what happens if you link the command ls to your current working directory like this:
ln -s /bin/ls ./lsRerun the programs and verify that the exec functions which work behind the scenes for (cf)popen look for programs, which do not have explicit paths, in the current directory. This also provides scope for errors.
To complete this exercise, you will need three windows, one for running each process: a sender, a receiver and an attacker. You should compile the programs below. You do not need the Security Kit to do this, it should be enough to compile with
gcc -o prog1 prog1.cand so on.
Here is the sender program. It is an extremely simpified program which generates a stream of data. To make the order of things clear, it simply outputs a number of line numbers. These are sent into a file called pipe_simul, which is our representation of a pipe between the programs. For instance, it might be a Unix pipe (inter-process communication) or it might be a network connection between server and client.
#include <stdio.h>
main()
{ FILE *fp;
int i;
char line[1024];
for (i = 0; i < 10; i++)
{
if ((fp = fopen("pipe_simul","a")) == NULL)
{
exit(1);
}
fprintf(fp,"Line %d\n",i);
fclose(fp);
sleep(5); /* simulate context switch or delay between packets */
}
}
Here is the receiver program. It reads the data stream from the pipe
and outputs the data on the screen.
#include <stdio.h>
main()
{ FILE *fp;
char line[1024];
fp = fopen("pipe_simul","r");
while (!feof(fp))
{
fgets(line,1023,fp);
printf("read: %s\n",line);
sleep(5); /* Context switch */
}
fclose(fp);
}
Compile these programs and run them, one in each window. Start the first
program first. You should see how the first program transmits data and how
the second receives the data. Look through the programs and make sure that
you understand how this happens.
Now delete the file pipe_simul and start again. This time, when the processes are running, try typing the following into the third window:
echo "Attack by a man in the middle" >> pipe_simulYou should see that the data appear in the output of the second process, after a short time. If you like, you can increase the rate of transfer by reducing the sleep time. Do you see how this can be used to spoof a challenge-response system?
The point is this: as long as the middle man process has access to the medium by which the data are transferred, it is easy for an attacker to try this kind of attack.. In the case of internet connections, every host has access to the internet. Of course, the attacker needs some prior knowledge of the type of transactions taking place. Also, it gets harder to make a successful attack as we turn up the transfer rate. Here it was trivial, in reality everything is much more time-critical.