what is IFS environment & linux command process
해당 과정에서 다룬 이야기를 좀 더 심도있게 다룬다.
scanf("%31s", cat_name); 으로 문자열을 받으면
`cat flag` 할때 중간에 공백에서 잘리게 된다. 이는 scanf가 스페이스로 인자를 나누기 때문인데
이를 bypass 하기 위해서는
C
`cat${IFS}flag`다음과 같은 테크닉이 필요하다
${IFS}는 리눅스에서 단어 분리에 사용되는 기준이 뭔가에 대한 환경변수이다.
C
root@47d252757cc6:/home/cat_jump# printf "%s" "$IFS" | od -t x1
0000000 20 09 0a
0000003즉, IFS 환경변수는 리눅스에서 명령어를 처리할때 단어들을 나누는 기준이 되는 것들이다.
그럼 이런생각이 들 수 있다.
위에서 보이다 싶이 IFS가 20 09 0a 으로 되어 있는데 0a가 들어가 있는 것이 의문이다.
예를 들어 우리가 cat만 치고 엔터를 치고 나중에 flag를 입력하면
C
root@47d252757cc6:/home/cat_jump# cat
flag
flag
what
what
^C다음과 같이 표준 입력을 반복하게 된다. 근데 왜
C
`cat${IFS}flag`이게 정상작동 할 수 있냐? 라고 생각할 수 있다. 근데 이건 너무 인간적인 사고이다.
셸 파서는 명령어 전체를 먼저 읽고 파싱을 할 뿐이다. 앞에서 부터 차례대로 읽으면서 0a 가 있으면 엔터를 치는게 아니기 때문이다. 즉, 그냥 사용자가 엔터를 눌렀을때 문자열을 모두 버퍼에 넣고 거기서 ${IFS} 값으로 파싱을 하는 것이다.
C
`cat${IFS}flag`이것도 마찬가지이다
cat${IFS}flag → cat\x20\x09\x0aflag 가 되지만 중간에 3바이트 모두 파서에 의해 파싱이 되는 기준이 되어서 첫번째 인자가 명령어 이후 인자들은 명령어의 인자가 되어 들어갈 뿐이다.