An unusual behaviour when using printf() after scanf() - c

I am using scanf() to get the password from the user and store it in password variable which has a size of 20 bytes. I check the entered password against the the correctPassword and if they match, boolean variable pass will be changed to true.
So, when I enter a password which is longer than 20 chars, a buffer overflow happens and the value of pass becomes non-zero (ie true). However, when I use printf() to print the address of variable pass no buffer overflow happens even-though I use a password which is longer than 20 chars.
here is the code that leads to overflow:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main (int argc, char *argv[]) {
char password[20];
char correctPassword[] = "random";
bool pass = false;
printf("enter your password: ");
scanf("%s", password);
if (strcmp(password, correctPassword) == 0) {
// compare the two strings,strcmp() returns 0 if two strings values are the same.
pass = true;
}
if (pass) {
printf("Connecting you to the central system...\n");
} else {
printf("Password is wrong! entry denied\n");
}
printf("%d\n", pass);
return 0;
}
when password entered is in this case 40 chars long(ASCII value of a is 97), value of pass changes to 97(true).
enter your password: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Connecting you to the central system...
97
here is the same code but with one extra line at the end to print the address of variable pass:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main (int argc, char *argv[]) {
char password[20];
char correctPassword[] = "random";
bool pass = false;
printf("enter your password: ");
scanf("%s", password);
if (strcmp(password, correctPassword) == 0) {
// compare the two strings,strcmp() returns 0 if two strings values are the same.
pass = true;
}
if (pass) {
printf("Connecting you to the central system...\n");
} else {
printf("Password is wrong! entry denied\n");
}
printf("%d\n", pass);
printf("%x\n", &pass);
return 0;
}
In this case password entered is 40 chars long but pass is still 0 (false).
enter your password: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Password is wrong! entry denied
0
61fec4
So, my question is how could adding only
printf("%x\n", &pass);
leads to no buffer-overflow as expected?

scanf("%s", password) is a security flaw: any input word longer than 19 bytes will cause scanf() to write beyond the end of the array, triggering undefined behavior.
Undefined behavior can have unpredictable side effects, which can be visible or not. The output of 97 is a mild side effect, but a long enough input will corrupt the return address and cause a segmentation fault upon returning from main() and a cleverly constructed input might allow an attacker to execute arbitrary code. Changing the program likely changes the side effects as the allocation of the local variables may be different for example when you take the address of &pass. None of this is predictable.
Note also that printf("%x\n", &pass); has undefined behavior too because %x expects an unsigned int, not a bool *, you should write printf("%p\n", (void *)&pass);
There is a simple way to prevent this by passing a length field to scanf():
scanf("%19s", password);
Note however that you should also check the return value to detect premature end of file and you should also flush the rest of the input line.
Here is a modified version:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]) {
char password[20];
char correctPassword[] = "random";
bool pass = false;
int c;
printf("enter your password: ");
if (scanf("%19s", password) != 1) {
printf("invalid input\n");
return 1;
}
/* read and discard the rest of the line */
while ((c = getchar()) != EOF && c != '\n')
continue;
if (strcmp(password, correctPassword) == 0) {
// compare the two strings,strcmp() returns 0 if two strings values are the same.
pass = true;
}
if (pass) {
printf("Connecting you to the central system...\n");
} else {
printf("Password is wrong! entry denied\n");
}
printf("%d\n", pass);
return 0;
}

Related

gets vs fgets for overflow in program

i have the following c program. when i enter input as bytebyte it is giving the wrong input due to buffer overflow.
this is the program
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
// Use a struct to force local variable memory ordering
struct {
char buff[5];
char perf;
} localinfo;
localinfo.perf = 0;
if(strcmp(localinfo.perf, "byte")){
printf ("\n Wrong Password \n");
}
else {
printf ("\n wrong Password\n");
localinfo.perf = 1; // Set a flag denoting correct password
}
//IF password matches
// GIVE root or admin rights to user
if(localinfo.pass){
printf ("\n Congratulations! Root privileges given to the user!\n");
}
return 0;
}
The correct password is byte, if enter byte it works fine.
if i enter bytebyte due to bufferoverflow the pass is modified as 1. and user is getting admin privileges.
if enter bytebyte as input output is
wrong password
Simply never use gets function, It is dangerous and obsolete.
Use fgets instead
fgets(localinfo.buff, sizeof(localinfo.buff), stdin);
To be sure that the whole line was read check if the last character is '\n'. If not assume that something is wrong and wrong password was entered.
Try this
#include <stdio.h>
#include <string.h>
int main(void) {
struct {
char buff[10];
char pass;
}
localinfo;
localinfo.pass = 0;
printf("\n Enter the password:\n");
scanf("%[^\n]s", localinfo.buff);
if (strcmp(localinfo.buff, "byte")) {
printf("\n Wrong Password \n");
} else {
printf("\n Correct Password\n");
localinfo.pass = 1;
}
if (localinfo.pass) {
printf("\n Congratulations! Root privileges given to the user!\n");
}
return 0;
}

C Program Crashes in Visual Studio

I am getting this error whenever I run my code in visual Studio:
#include <stdio.h>
#include <ctype.h>
int main() {
char username[10];
printf("Enter Username: ");
scanf_s("%[^\n]", &username);
while (isupper(username)) {
if (username == '-') {
printf("Username cannot contain UpperCase Letters");
}
}
}
Error Image
I don't think you can pass whole array to isupper. Also if you don't want to return anything instead of int main() use void main() or just return 0 in the end or when you want to end after your program executed successfully. As for using scan_s or scanf or getline or whatever I won't say anything because its a different matter and your syntax of scanf_s is certainly wrong.
Also following code will not check for any buffer overflow (not a good practice, you will see even though we gave size 20 char array, this code will work even for larger input which is certainly not a good thing). So you can either limit the size of input or better to read an entire line via fgets() (or getline() if available) and parse the string yourself.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(){
char username[20];
printf("Enter Username: ");
// scanf("%[^\n]", username); <--- Instead of this
scanf_s("%20c", username, 20); // <----Try Using this
int i=0;
while (i<strlen(username)) {
if (isupper(username[i])) {
printf("Username cannot contain UpperCase Letters\n");
return 0;
}
i++;
}
return 0;
}
My first guess would be that your while is an endless loop, try to do it like this:
int i;
for(i=0; i<strlen(username);i++){
if(isupper(username[i])){
printf("Username cannot contain UpperCase Letters");
}
}

C Program suddenly exits after first input when using printf()

I tried this code but after entering the first input it exits. This code works fine though when the printf("hello world"); is commented out or deleted. The compiler doesn't explain anything and it doesn't show any error so I dont know the solution. What is the reason behind this?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdbool.h>
bool login(bool logStatus) // takes in loggedIn value
{
char correctUsername[16] = "admin";
char correctPassword[16] = "admin123";
char *inputUsername;
char *inputPassword;
int i, checkUsername, checkPassword;
printf("Enter your username : \n");
fgets(inputUsername, 16, stdin); /* Get user input for username */
inputUsername[strlen(inputUsername) - 1] = '\0';
// scanf("%s", &inputUsername);
printf("Enter your password : \n");
fgets(inputPassword, 16, stdin); /* Get user input for password */
inputPassword[strlen(inputPassword) - 1] = '\0';
// scanf("%s", &inputPassword);
/* Check username and password */
checkUsername = strcmp(correctUsername, inputUsername);
checkPassword = strcmp(correctPassword, inputPassword);
printf("%d %d", checkUsername, checkPassword);
if (checkUsername == 0 && checkPassword == 0)
{
printf("\n\nLogged In Successful");
logStatus = true;
return logStatus;
}
else
{
printf("\n\nIncorrect username or password\n");
printf("Enter any key to continue...");
getch();
system("cls");
}
}
int main()
{
int input;
int choice;
bool loggedIn = false;
printf("hello world");
login(loggedIn);
return 0;
}
inputUsername and inputPassword are uninitialized pointers. You then pass them to fgets which attempts to dereference those invalid pointers. Doing so invokes undefined behavior.
Make them arrays like the username/password you're checking against.
char inputUsername[16];
char inputPassword[16];

How to get integer and string input using scanf?

I have a problem in C language
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char usrname[17] = "nsa-secret-agent";
char password[9] = "marshal41";
char usr[512], pass[512];
printf("username: ");
scanf("%[^\n]%*c", usr);
printf("password: ");
scanf("%[^\n]%*c", pass);
printf("%s\n", usr);
printf("%s\n", pass);
if (strcmp(usrname, usr) == 0 && strcmp(password, pass) == 0){
printf("You Have Successfully Logged In!\n");
}
else{
printf("username or password not found!\n");
exit(0);
}
return 0;
}
When I run this code it runs without any errors but when give input like below:
username: nsa-secret-agent
password: marshal41
nsa-secret-agent
marshal41
username or password not found!
I am giving correct credentials but still it's showing error
Your arrays for usrname and password are off by one:
char usrname[17] = "nsa-secret-agent";
char password[9] = "marshal41";
These are short one byte for the zero terminator which makes the comparison later fail. Either add one or just use
char usrname[] = "nsa-secret-agent";
char password[] = "marshal41";
or you could even use
char *usrname = "nsa-secret-agent";
char *password = "marshal41";
since the strings are not modified.

Program stops working when I input variables [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I want to do something in case the username is equal to "admin", but this error appears when I input username and pass.
#include <stdio.h>
#include <stdlib.h>
int main() {
char UserName[100];
char admin[6]="admin";
double Password;
int choice,result;
while (choice!=3){
printf("Username : ");
scanf("%s",&UserName);
printf("Password : ");
scanf("%d",Password);
char admin=admin;
if(strcmp(UserName, admin)&&(Password==1234))
{
printf(" enter your choice : ");
}
}
return 0;
}
I tried to minimize the changes to your code. See my attempt of a possibly working (not tested) alternative
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) { // full definition with prototype
char UserName[100];
char admin[6] = "admin";
int Password; // changed to int
int choice = 0, result; // initialize choice
while (choice != 3) {
printf("Username : ");
// limit input, the & is wrong, check the return value of scanf
if (scanf("%99s", UserName) != 1) exit(EXIT_FAILURE);
printf("Password : ");
// match type of "%" and variable, check the return value
if (scanf("%d", Password) != 1) exit(EXIT_FAILURE);
// char admin = admin; // deleted
// strcmp returns 0 when the strings match
if ((strcmp(UserName, admin) == 0) && (Password == 1234))
{
printf("OK!\n"); // do something
}
// block structure messed up?
printf(" enter your choice : ");
if (scanf("%d", &choice) != 1) exit(EXIT_FAILURE);
}
return 0;
}
this error appears when i input username and pass.
because you have these 2 undefined behaviors in your code :
scanf("%s",&UserName);
whose must be
scanf("%s",UserName);
and 'worst' :
scanf("%d",Password);
whose must be
scanf("%d", &Password);
else scanf try to write to an undefined address being the value of Password which is not initialized
May be the execution continue after scanf("%s",&UserName) but no chance it does after scanf("%d",Password) producing typically a segmentation fault
Note also Password has to be an int, or the format has to be something like "%g" but to use a floating point value for a password is very improbable
Out of that you have an other undefined behavior in
while (choice!=3){
because choice is never initialized, but that time the effect is not 'catastrophic' like it is with scanf("%d",Password);
Also what do you expect with :
char admin=admin;
that line must be removed because there is no reason to have it
And finally a closing '}' is missing before return 0;
I updated your code with some things that were missing:
Added string.h include that was required for strcmp
Removed char admin = admin
Updated the Password scanf to use the proper type
Always try to pay attention to the compiler and activate all warnings as errors when possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char UserName[100];
char admin[6] = "admin";
int Password;
int choice = 0;
while (choice != 3)
{
printf("Username : ");
scanf("%s", UserName);
printf("Password : ");
scanf("%d", &Password);
if (strcmp(UserName, admin) && (Password == 1234))
{
printf(" enter your choice : ");
}
return 0;
}
}

Resources