I'm writing a simple HTTP server and I'm getting a file does not exists return value when the file does exist
printf("%s\n", html_path);
if ((fd = open(html_path, "r")) >= 0){ //file found
stat(file_name, &st);
file_size = st.st_size;
printf("%d\n", file_size);
while (read(fd, response, RCVBUFSIZE) > 0){
}
}
else { //file not found
strcpy(response, "404 File not found\n");
send(clntSocket, response, 32, 0);
}
the print statement is to verify the path and it looks like this:
/mounts/u-zon-d2/ugrad/kmwe236/HTML/index.html
note that this path is on a server that we use at our university. it's the path that shows when I command pwd
I have confirmed that the file exists. is there something wrong with my path?
There was an error opening the file, but you don't know that it was because the file was not found because you're didn't check the value of errno.
In the else section, add the following:
else { //file not found
// copy the value of errno since other function calls may change its value
int err = errno;
if (err == ENOENT) {
strcpy(response, "404 File not found\n");
send(clntSocket, response, 32, 0);
} else {
printf("file open failed: error code %d: %s\n", err, strerror(err));
}
}
If the file does not in fact exist you'll handle the error properly. If not, you'll print an error message that tells you what did happen.
You're also calling open incorrectly. The second parameter is an int containing flags. To open a file for reading, use O_RDONLY.
open does not have the 2nd parameter as a string. You using open with the parameters of fopen.
For a webserver fopen, fprintf, fclose is a better choise then more lowlevel open, read, ...
Cheers,
Chris
You need to check where you program is executing as it will try to open the path relative from that location. To check use:
char cwd[1024];
getcwd(cwd, sizeof(cwd));
puts(cwd);
Then you can concatenate your path using:
strncat(cwd, html_path, 100);
You may find that you have to go up one directory or something to then find the file you're looking for.
Also note that if you're debugging your program via gdb it may execute from a different location from your regular build location which may make it harder to spot bugs.
Related
I have the following code as an executable that I want to exploit for a course in order to spawn a shell with elevated privileges. I am a user of levelX and the executable has setgid of levelX+1. I am not allowed to alter any of the code.
As I do not have root privileges, setguid(0) fails. I was not able to change the return address of the function or main function. Could anyone point to the right direction?
int main (int argc, char** argv)
{
if (exec(argv[1]) != 0)
{
fprintf(stderr, "Cannot execute your command\n");
return -1;
}
return 0;
}
int exec(char *command)
{
FILE *f = NULL;
char entry[64];
char line[256];
f = fopen("log", "a");
if (f == NULL)
{
fprintf(stderr, "Can't open file\n");
return -1;
}
snprintf(entry, 64, "%d: %s\n", getuid(), command);
fprintf(f, entry, NULL);
fclose(f);
f = fopen("sudoers", "r");
if (f == NULL)
{
fprintf(stderr, "Can't open\n");
return -1;
}
while(fgets(line, 256, f) != NULL)
{
if (atoi(line) == getuid())
{
if (setuid(0) == 0) {
system(command);
} else {
fprintf(stderr, "check permissions\n");
}
fclose(f);
return 0;
}
}
fprintf(stderr, "Error\n");
fclose(f);
return -1;
}
From the code you posted, it appears you are supposed to write your own sudoers file to any directory you have write access to, then run this program in that directory, so it reads your file.
So, simply write your own UID to this fake sudoers file, and then give a command parameter such as bash to get a shell. There's no need to do any buffer overflow exploitation.
Presumably the real exploitable program has suid bit set in the file permissions, so it can perform the setuid(0) call. I guess the purpose of the exercise is to demonstrate how all input needs to be sanitized when you are dealing with suid programs, including things like relative paths (which effectively take current working directory as input) like any user-supplied paths and other input.
But, since the program only has setgid bit (as said in comment), you need find something you do with just the group id. That something could be that log file write. You could create a symbolic link with file name log, pointing to whatever file you want to append to, which that group has write permissions for. Also, that file needs to have format such, that the log line format does not make the file corrupted. Remember, you can put newlines etc into command line arguments!
After all it was a format string exploit on fprintf(f, entry, NULL); inside int exec(char *command) where you overwrite the return address with %n format.
Trying to open and write to the following file path, for some reason it is not opening, I've tried several different paths and nothing has worked. I am running this from C:\
FILE* fptwo = fopen("\\C:\\Program Files\\NotMal.txt", "w");
if (fptwo != NULL)
{
printf("open progfiles successful \n");
//add this text to the file
fprintf(fptwo, "This is text");
printf("add text succuessful \n");
//close file pointer when finished
fclose(fptwo);
}
*please feel free to delete or close this question if it is answered somewhere else, I apologize for the mistakes made within this, and if it is a stupid error.
You test if you have correctly opened the file, it's good !
But it's better to know why your function call have failed.
For "fopen", you can know by looking the value of errno. (read the man about fopen).
And a "cool thing" is that you can obtain an english description by using "strerror".
So, just do :
#include <string.h> // For strerror
#include <errno.h> // For .... errno
FILE* fptwo = fopen("\\C:\\Program Files\\NotMal.txt", "w");
if (fptwo == NULL)
{
printf("Error : errno='%s'.\n", strerror(errno));
}
else
{
printf("open progfiles successful \n");
//add this text to the file
fprintf(fptwo, "This is text");
printf("add text succuessful \n");
//close file pointer when finished
fclose(fptwo);
}
Program Files is windows default software deployment folder. Better not to use that path. Better create your own test folder and test. If possible not to name folder with space.
FILE* fptwo = fopen("C:\\MyProject\\test\\NotMal.txt", "w");
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c[1000];
FILE *fptr;
if ((fptr = fopen("program.txt", "r")) == NULL)
{
printf("Error! opening file");
// Program exits if file pointer returns NULL.
exit(1);
}
// reads text until newline
fscanf(fptr,"%[^\n]", c);
printf("Data from the file:\n%s", c);
fclose(fptr);
return 0;
}
Output is Error! opening file
I have program and txt file in same dir.
How can I direct access to that file?
To diagnose, use the system command to issue a ls or dir depending on your platform. That will tell you where you are running from. Odds are it is a different location than the files you are trying to open.
As suggested in the comment, try replacing printf with perror
if ((fptr = fopen("program.txt", "r")) == NULL)
{
perror("Error");
// Program exits if file pointer returns NULL.
exit(1); // Exiting with a non-zero status.
}
perror prototype is
void perror(const char *str)
where str is the C string containing a custom message to be printed before the error message itself.
However some causes of the of the file not being read are
File is not present in the current working directory. If this is the case, rectifying the path should fix the issue.
The program might not have the permissions to read from the file usually because of a setting related to discretionary access control. Perhaps do a chmod with file?
I made a quick run of your program on TURBOC++ by Borland and it executed without complaining any sort of Warning or Error
As mentioned in the earlier posted answers, you should replace printf by perror
CURRENT REPLACE BY
printf("Error! opening file"); perror("Error! Opening File.");
As in your case of file not found printf("Error! opening file"); will result in :
Error! Opening file.
However in case of perror("Error! Opening File."); if the file program.txt does not exist, something similar to this may be expected as program output
The following error occurred: No such file or directory
The difference is obvious from above explanations.
Regarding your program, I am making an assumption that either your path to the file is wrong or there is some problem with your compiler.
Try to open your file in w+ mode also to ensure that the file exist.
I work on Xcode and I have a simple function that opens a file using open in C.
void mfs_workwith() {
char *token, *temp_token;
char *search = ".";
temp_token = (char*)malloc(sizeof(char)*strlen(cc[1]));
strcpy(temp_token, cc[1]);
if ((token = strtok(temp_token, search)) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if ((token = strtok(NULL, " \n\0")) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if (strcmp(token, "mfs") == 0) {
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
if ((file_mfs = open(filename, O_RDWR)) == -1) {
perror("open error");
} else {
printf("open successful \n");
}
}
}
The name of the file is stored in a global array and then copied into local buffers in order to tokenize and check if it has the right format (.mfs).
Then if everything is ok I make a fresh copy of the name of the file and call open with it.
My problem is that when I run my program in terminal it runs fine, prints open successful and then continues. But when I try to run it in Xcode it fails with this error:
No such file or directory
I am giving the input file.mfs which is the name of a file in the same directory.
Am I missing something obvious?
I found the problem thanks to iharob's comment. It seems xcode has a hard time opening relative paths since it uses a different file while running the program. There is a relative discussion here:
Open method opens files with full path only C++
thanks again everyone.
This:
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
is broken, it fails to allocate room for the string's terminator, so it causes buffer overflow and undefined behavior.
Also, you never need to scale by sizeof (char), that's always 1. It should be:
filename = malloc(strlen(cc[1]) + 1);
strpcy(filename, cc[1]);
or, if you have it, just:
filename = strdup(cc[1]);
When an error occurs, I would like my C code to store the error before exiting the program. Is it advised to store the stderr to a file (e.g., /home/logs.txt) or would it be advised to use a different method to keep the logs/error report (considering the programming environment is Linux). E.g., for the code below, how I could apply the method to store the logs/error message on /home/log.txt or /home/log
FILE *fp1;
fp1 = fopen("/sys/class/gpio/export","w");
if(fp1 == NULL){
fprintf(stderr, "errno:%s - opening GPIO136 failed - line 739\n ", strerror(errno));
close(fp1);
exit(1);
}
Thank you.
If stderr is always used to print out all your error message, so, you can redirect output to a specific file.
$ program 2>~/logs.txt
For a better logging tool, you can use:
syslog standard function.
log4c library.
If you want to store the error, stderr is probably not a good choice because you'll need to pipe stderr to a file every time you run the program.
If you want to write to /home/log.txt, open a FILE pointer to it and write with fprintf the same way you tried to open /sys/class/gpio/export and write to that instead of stderr. Also be sure to open the log file with append mode.
FILE *fp1;
fp1 = fopen("/sys/class/gpio/export","w");
if(fp1 == NULL){
FILE *fpErr = fopen("/home/log.txt", "a");
if(fpErr != NULL)
fprintf(fpErr, "errno:%s - opening GPIO136 failed - line 739\n ", strerror(errno));
close(fpErr);
close(fp1);
exit(1);
}