Scan subdomains là một trong những giai đoạn thu thập thông tin kiểm thử. Việc thực hiện tìm kiếm các subdomains
bằng tay đôi khi gặp nhiều khó khăn, nên trong bài này mình sẽ hướng dẫn viết công cụ để giúp việc này dễ dàng hơn.
Cài đặt thư việc requests trong python:
1 2 | pip install requests |
Về cách triển khai trong bài này là brute-forcing, chúng ta sẽ thử tất cả các subdomains
nằm trong wordlist
bất cứ khi nào nhận được phản hồi thì đó là một subdomain
hợp lệ. Đôi khi việc scan không ra được hết tất cả các subdomains
, điều này là hoàn toàn bình thường bởi vì thư viện của chúng ta không chứ tất cả subdomains
hợp lệ của target
đó.
Import các thư viện cần thiết:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">import</span> requests <span class="token keyword">import</span> urllib3 <span class="token keyword">import</span> sys <span class="token keyword">import</span> threading <span class="token keyword">from</span> queue <span class="token keyword">import</span> Queue d <span class="token operator">=</span> Queue<span class="token punctuation">(</span><span class="token punctuation">)</span> |
- requests dùng để gửi yêu cầu đến
target
và nhận viết domain đấy có hợp lệ hay không. - urllib3 để format
target
. - threading thực hiện việc chạy đa luồng giúp cho chương trình nhanh hơn.
- queue thuận tiện hơn trong việc chạy đa luồng.
Xử lý target
:
1 2 3 4 5 6 7 8 | <span class="token keyword">def</span> <span class="token function">parse_url</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">try</span><span class="token punctuation">:</span> host <span class="token operator">=</span> urllib3<span class="token punctuation">.</span>util<span class="token punctuation">.</span>url<span class="token punctuation">.</span>parse_url<span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span>host <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Invalid domain, try again.."</span><span class="token punctuation">)</span> sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> host |
Hàm này cố gắng xử lý input để lấy hostname
nếu như không hợp lệ chương trình sẽ tự động thoát.
1 2 3 4 5 6 7 8 | <span class="token keyword">def</span> <span class="token function">parse_wordlist</span><span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">try</span><span class="token punctuation">:</span> wordlists <span class="token operator">=</span> <span class="token builtin">open</span><span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>splitlines<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> wordlists |
Hàm này giúp chúng ta đọc tất cả các subdomains
từ wordlist
, với hàm splitlines()
trong python sẽ giúp tách tất cả các dòng trong một chuỗi. Việc này giúp tránh trường hợp không thể load được wordlist
gây ra lỗi chương trình, phải đảm bảo rằng bạn đã chọn đúng đường dẫn của file wordlist
. Bạn có thể tham khảo một số wordlist về DNS trên Google, Github…
Sau đây là một trong những hàm chính của chương trình:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">def</span> <span class="token function">scan_subdomain</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">global</span> d <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span> subdomain <span class="token operator">=</span> d<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> url <span class="token operator">=</span> f<span class="token string">"http://{subdomain}.{target}"</span> <span class="token keyword">try</span><span class="token punctuation">:</span> res <span class="token operator">=</span> requests<span class="token punctuation">.</span>get<span class="token punctuation">(</span>url<span class="token punctuation">)</span> <span class="token keyword">except</span> requests<span class="token punctuation">.</span>ConnectionError<span class="token punctuation">:</span> <span class="token keyword">pass</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token keyword">if</span> res<span class="token punctuation">.</span>status_code <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"[+] "</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span> d<span class="token punctuation">.</span>task_done<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Để biết subdomains
đó có hợp lệ hay không thì chúng ta sẽ gửi một requests
đến domain đó, bất cứ khi nào nhận được phản hồi thì đó là hợp lệ. Khai báo một biến global
queue để get các subdomains
đã lưu trong queue, lặp cho đến khi tất cả các subdomains
được thực hiện request, tạo một url
với phần subdomain
lấy từ queue và target mà ta nhắm đến, thực hiện việc gửi requests đến url
đó và nhận kết quả phản hồi để xử lý. Nếu không thể Connect tới url đó thì bỏ qua và không in gì cả vì subdomains
đó không hợp lệ, nếu nhận được status code
là 200 tức là ta có thể kết nối đến subdomain
đó và ta hoàn toàn có thể in ra vì nó hoàn toàn hợp lệ.
Với các chương trình scan việc chạy đơn luồng là khá chậm, đối với những word list
lớn thì đơn luồng có thể chạy mất một ngày, để có thể cải thiện việc này bạn có thể tham khảo thêm về đa luồng.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">def</span> <span class="token function">mutil_scan_subdomains</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span>number_threads<span class="token punctuation">,</span>subdomains<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">global</span> d <span class="token keyword">for</span> subdomain <span class="token keyword">in</span> subdomains<span class="token punctuation">:</span> d<span class="token punctuation">.</span>put<span class="token punctuation">(</span>subdomain<span class="token punctuation">)</span> <span class="token keyword">for</span> thread <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>number_threads<span class="token punctuation">)</span><span class="token punctuation">:</span> t <span class="token operator">=</span> threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>scan_subdomain<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span> t<span class="token punctuation">.</span>daemon <span class="token operator">=</span> <span class="token boolean">True</span> t<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Trước tiên thêm tất cả các subdomain
từ wordlist đã được xử lý trước đó và put
vào queue:
1 2 3 | for subdomain in subdomains: d.put(subdomain) |
Sau đó khởi tạo và chạy với số luồng mà input nhập vào:
1 2 3 4 5 | for thread in range(number_threads): t = threading.Thread(target=scan_subdomain, args=(target,)) t.daemon = True t.start() |
main
1 2 3 4 5 6 7 | <span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> target <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Target: "</span><span class="token punctuation">)</span> wordlist <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Wordlist: "</span><span class="token punctuation">)</span> number_threads <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span><span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Number threads: "</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"====================="</span><span class="token punctuation">)</span> mutil_scan_subdomains<span class="token punctuation">(</span>target<span class="token operator">=</span>target<span class="token punctuation">,</span> number_threads<span class="token operator">=</span>number_threads<span class="token punctuation">,</span>subdomains<span class="token operator">=</span>parse_wordlist<span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">)</span> |
Với hàm main thì chỉ cần lấy các input truyền vào và chạy.
1 2 3 4 5 | python scansubdoamin.py Target: viblo.asia Wordlist: subdomains.txt Number threads: 100 |
Đây là kết quả khi chạy:
Full code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <span class="token keyword">import</span> requests <span class="token keyword">import</span> urllib3 <span class="token keyword">import</span> sys <span class="token keyword">import</span> threading <span class="token keyword">from</span> queue <span class="token keyword">import</span> Queue d <span class="token operator">=</span> Queue<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">parse_url</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">try</span><span class="token punctuation">:</span> host <span class="token operator">=</span> urllib3<span class="token punctuation">.</span>util<span class="token punctuation">.</span>url<span class="token punctuation">.</span>parse_url<span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span>host <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Invalid domain, try again.."</span><span class="token punctuation">)</span> sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> host <span class="token keyword">def</span> <span class="token function">parse_wordlist</span><span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">try</span><span class="token punctuation">:</span> wordlists <span class="token operator">=</span> <span class="token builtin">open</span><span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>splitlines<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> wordlists <span class="token keyword">def</span> <span class="token function">banner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token triple-quoted-string string">''' ____ ____ ____ ____ / ___| _ _ _ __ / ___/ ___|| _ ___ | | | | '_ | | ___ | |_) | ___) | |_| | | | | |___ ___) | _ < |____/ __,_|_| |_|____|____/|_| _ ===================================== '''</span><span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">scan_subdomain</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">global</span> d <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span> subdomain <span class="token operator">=</span> d<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> url <span class="token operator">=</span> f<span class="token string">"http://{subdomain}.{target}"</span> <span class="token keyword">try</span><span class="token punctuation">:</span> res <span class="token operator">=</span> requests<span class="token punctuation">.</span>get<span class="token punctuation">(</span>url<span class="token punctuation">)</span> <span class="token keyword">except</span> requests<span class="token punctuation">.</span>ConnectionError<span class="token punctuation">:</span> <span class="token keyword">pass</span> <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token keyword">if</span> res<span class="token punctuation">.</span>status_code <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">:</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"[+] "</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span> d<span class="token punctuation">.</span>task_done<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">mutil_scan_subdomains</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span>number_threads<span class="token punctuation">,</span>subdomains<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">for</span> subdomain <span class="token keyword">in</span> subdomains<span class="token punctuation">:</span> d<span class="token punctuation">.</span>put<span class="token punctuation">(</span>subdomain<span class="token punctuation">)</span> <span class="token keyword">for</span> thread <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>number_threads<span class="token punctuation">)</span><span class="token punctuation">:</span> t <span class="token operator">=</span> threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>scan_subdomain<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span> t<span class="token punctuation">.</span>daemon <span class="token operator">=</span> <span class="token boolean">True</span> t<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> target <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Target: "</span><span class="token punctuation">)</span> wordlist <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Wordlist: "</span><span class="token punctuation">)</span> number_threads <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span><span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">"Number threads: "</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"====================="</span><span class="token punctuation">)</span> mutil_scan_subdomains<span class="token punctuation">(</span>target<span class="token operator">=</span>target<span class="token punctuation">,</span> number_threads<span class="token operator">=</span>number_threads<span class="token punctuation">,</span>subdomains<span class="token operator">=</span>parse_wordlist<span class="token punctuation">(</span>wordlist<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span> banner<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"===================="</span><span class="token punctuation">)</span> main<span class="token punctuation">(</span><span class="token punctuation">)</span> d<span class="token punctuation">.</span>join<span class="token punctuation">(</span><span class="token punctuation">)</span> |