"!xxx%s%s%s%s%s%s%s%s"의 특별한 점은 무엇인가요?

"!xxx%s%s%s%s%s%s%s%s"의 특별한 점은 무엇인가요?

나는 연결되었다유닉스를 싫어하는 사람들 핸드북그리고 우연히 발견한 내용(149페이지):

제목: 관련 Unix 버그

1991년 10월 11일

동료 W4115x 학생—

활성화 레코드, 인수 전달 및 호출 규칙에 대해 다루는 동안 다음과 같은 입력을 알고 계셨습니까?

!xxx%s%s%s%s%s%s%s%s

C 쉘에 연결하면 즉시 충돌이 발생합니까? 이유를 아시나요?

생각해 볼 질문:

  • 를 입력할 때 쉘은 무엇을 합니까 !xxx?
  • 입력할 때 입력으로 무엇을 해야 합니까 !xxx%s%s%s%s%s%s%s%s?
  • 이것이 쉘을 충돌시키는 이유는 무엇입니까?
  • 이 문제가 발생하지 않도록 쉘의 문제가 되는 부분을 어떻게 (아주 쉽게) 다시 작성할 수 있습니까?

순전히 호기심으로 문제가 무엇인지 설명할 수 있는 사람이 있습니까? 당연히 Google에서 문자열을 검색해도 도움이 되지 않습니다. 메시지에서 다른 인용문을 검색하면 메시지의 다른 사본만 제공될 뿐 설명은 제공되지 않습니다.

답변1

25년 된 조개껍질의 출처를 캐고 싶지는 않지만,

그것은형식 문자열 취약점.

쉘에 다음과 같은 코드가 포함되어 있는 경우

printf(str);

str사용자 입력에서 일부 문자열을 가져온 경우 문자열의 내용은 사용 되는 형식 문자열이 됩니다 printf. ' 는 인수가 가리키는 문자열을 인쇄하라고 %s지시합니다 . printf인수가 제공되지 않으면(위와 같이 형식 문자열만 있음) 함수는 스택에서 다른 데이터를 읽고 이를 포인터로 따릅니다. 아마도 매핑되지 않은 메모리에 액세스하여 프로세스가 중단될 수 있습니다.

어떤 면에서는 메시지의 문구도 이와 같은 해결책을 암시한다고 생각합니다. 를 입력하면 !xxx쉘이 눈에 띄게 수행하는 작업은 다음과 같은 오류 메시지를 인쇄하는 것입니다 !xxx: event not found. 거기에서 !xxx%s%s%s%s%s%s%s%s: event not found형식 문자열 취약점을 암시하면서 print 도 시도하는 것은 큰 도약이 아닙니다 .


그러지 말았어야 했는데 출처를 살짝 들여다 봤습니다여기( 4.3BSD-Tahoe/usr/src/bin/csh, 날짜는 1988년부터임).

findev(cp, anyarg)~에sh.lex.c일치하는 기록 이벤트를 찾는 함수인 것 같습니다. struct Hist호출된 연결 목록을 살펴봅니다 Histlist. 아무것도 찾지 못하면 를 seterr2(cp, ": Event not found");통해 호출합니다 noev(). cp여기에 기록에서 검색되는 문자열이 있는 것 같습니다.

seterr2()변수를 err인수의 연결로 설정하고 , 의 두 위치에서 err사용됩니다 .if (err) error(err);process()sh.c. 마지막으로 error()(에서sh.err.c)에는 전형적인 형식 문자열 취약점이 포함되어 있습니다.if (s) printf(s, arg), printf(".\n");

다른 곳에서는 error()가 와 같은 인수와 함께 호출되므로 의 첫 번째 인수가 형식 문자열일 수 error("Unknown user: %s", gpath + 1);있다는 아이디어가 분명합니다 .error()

내가 히스토리 대체 기능을 완전히 이해했다고 말하면 솔직하지 않을 것입니다. C에서 거의 주석 처리되지 않은 수동 문자열 처리는 기록 대체에 특별한 의미가 있지만 첫 번째 문자(에서와 같이 ) 또는 이후 호출 시 %특별히 처리되는 것을 볼 수 있습니다 .!%findev()

관련 정보