mistake
Operator precedence: the result of the comparison lands in fd instead of the file descriptor from open().
패스워드를 알아내야지 플래그를 볼 수 있는 듯함. 당연히 소스 코드 먼저 봐주겠음.
에바로다가김. 대충 훑어보면 패스워드 비교 코드임을 알 수 있음. 취약점은 무엇일까… if 문을 잘 살펴보자 보자 보자꾸나. open 조건문이다!
if (fd = open("/home/mistake/password", O_RDONLY, 0400) < 0) {
의도한 코드는 이거였을 것이다.
if ((fd = open(...)) < 0) // fd에 저장 후 음수인지 확인
그런데 실제 동작은 이렇다.
if (fd = (open(...) < 0)) // 비교 먼저! 결과(0 또는 1)가 fd에 저장됨
< 연산자가 = 보다 우선순위가 높아서, 비교 결과(0 또는 1)가 fd 에 들어가요.
두 개이기 때문에 read() 조건문도 잘 펴봐주겠다 (집중해 ㄱㅇㅇ).
if (!(len = read(fd, pw_buf, PW_LEN) > 0)) {
같은 이유로 실제로는 이렇게 동작한다.
if (!(len = (read(fd, pw_buf, PW_LEN) > 0)))
// len에는 실제 읽은 바이트 수가 아닌 0 또는 1이 저장됨
결과적으로 fd 는 open() 반환값이 아닌 0 또는 1이다. fd = 0 이면 표준입력(stdin) 을 읽게 됨! 즉 read(0, pw_buf, PW_LEN) 이 되어 키보드 입력을 읽는다.
pw_buf 와 pw_buf2 가 둘 다 내 입력이니까, 내가 원하는 값을 넣을 수 있다.
strncmp(pw_buf, pw_buf2, 10) == 0
이 조건을 통과하려면 pw_buf == XOR1(pw_buf2) 이어야 한다. 즉
- pw_buf 에 들어갈 값을 먼저 입력
- 그 값을 XOR 1 한 결과를 pw_buf2 로 입력
- strncmp 통과!
예를 들어 0000000000 을 입력하면, XOR 1 결과는 1111111111 이니까:
첫 번째 입력: 0000000000
두 번째 입력: 1111111111
하면 Password OK 가 뜸.


