1.1 介紹
福哥在使用selenium去爬取網(wǎng)頁的時(shí)候發(fā)現(xiàn)有的網(wǎng)站的結(jié)構(gòu)設(shè)計(jì)的非常復(fù)雜,如果使用chrome自帶的find_element_by_xxx方法想要得到目標(biāo)元素簡(jiǎn)直比登天還難。福哥就想如果可以在抓取的網(wǎng)站上面加一段JavaScript代碼就好了,福哥就可以隨心所欲地玩弄頁面上面的元素了。
福哥在翻閱文檔的時(shí)候發(fā)現(xiàn)了chrome的一個(gè)特別的方法,就是execute_script方法,這個(gè)方法可以通過JavaScript代碼進(jìn)行頁面上的元素的獲取。福哥就想既然可以通過JavaScript獲取頁面元素,那么就表示可以運(yùn)行我們傳入的JavaScript代碼,既然可以運(yùn)行JavaScript代碼就夠了啊,我們也不一定要獲取元素為目的啊,我們只想運(yùn)行JavaScript代碼啊!!!
現(xiàn)在福哥先來一個(gè)演示,在一個(gè)頁面里面通過JS程序修改頁面上的內(nèi)容。
2.1 代碼
福哥寫了一段JS代碼,放入了變量code里面,將code傳遞給execute_script方法在頁面里面執(zhí)行。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
opts = webdriver.ChromeOptions()
opts.add_argument("--disable-gpu")
opts.add_argument("--no-sandbox")
chrome = webdriver.Chrome(options=opts)
chrome.get("https://tongfu.net/mobile/")
code = "$('td.mobile').html('福哥熱線');" \
"$('td.prov').html('太陽系');" \
"$('td.city').html('火星');" \
"$('td.isp').html('火信');" \
"$('td.cdt').html('公元前100年');" \
"$('td.lmdt').html('公元8888年');"
chrome.execute_script(code)
2.2 效果
原版
改版
看到了第一個(gè)示例,體會(huì)到了execute_script的威力了,下面我們來個(gè)大的,向一個(gè)不包含jQuery的頁面導(dǎo)入jQuery框架。
3.1 代碼
福哥通過讀取文件的方式將整個(gè)jquery.min.js都讀到了code變量里面,然后通過execute_script注入到了頁面里面,最后通過alert函數(shù)打印了jQuery的版本號(hào)。
因?yàn)閍bout:blank是一個(gè)空白頁面,可以正確打印jQuery版本號(hào)證明注入jQuery成功了~~
chrome.get("about:blank")
with open("jquery.min.js", "r") as fo:
lines = fo.readlines()
code = "".join(lines)
fo.close()
chrome.execute_script(code)
chrome.execute_script("alert($.fn.jquery);")
3.2 效果
導(dǎo)入本地代碼的方法就是通過open方法將JS文件里面的內(nèi)容讀取出來,然后傳入execute_script在頁面上面執(zhí)行一下就可以了。
需要注意的是,導(dǎo)入多個(gè)JS程序的時(shí)候需要安裝依賴關(guān)系按順序逐個(gè)進(jìn)行導(dǎo)入,否則有可能會(huì)造成JS執(zhí)行錯(cuò)誤的問題。
導(dǎo)入遠(yuǎn)程代碼就是通過JS動(dòng)態(tài)繪制script標(biāo)簽載入遠(yuǎn)程JS文件。
5.1 代碼
通過遠(yuǎn)程方式加載需要等待腳本載入完成,雖然可以通過onreadystatechange方式精確得到加載完成的時(shí)間,但是callback方式不是很方便編寫程序。
福哥還是推薦使用time.sleep方法等待加載完成,通過typeof判斷是否加載成功了~
chrome.get("about:blank")
code = "var s=document.createElement('script');" \
"s.type='text/javascript';" \
"s.src='http://code.jquery.com/jquery-3.6.0.min.js';" \
"document.body.appendChild(s);"
chrome.execute_script(code)
time.sleep(3)
chrome.execute_script("alert($.fn.jquery);")
5.2 效果
福哥今天帶著童鞋們學(xué)會(huì)了通過靈活運(yùn)用chrome的execute_script方法實(shí)現(xiàn)在爬取頁面自由自在地執(zhí)行JavaScript代碼、導(dǎo)入JavaScript庫的目的,有了這個(gè)技術(shù),那些設(shè)置了防爬取技術(shù)的網(wǎng)站的防護(hù)措施基本形同虛設(shè)了,我們想要什么數(shù)據(jù)都是手到擒來了,真是爽啊~~
https://m.tongfu.net/home/35/blog/513275.html
、前言
在Burp上,我們可以使用多種方法來配置宏(macro),以繞過HTML表單上的CSRF tokens,這樣一來,我們就可以使用Burp Active Scans、Burp Intruder、Burp Repeater,甚至也可以使用Burp Proxy進(jìn)行滲透測(cè)試。我們也可以找到專為Intruder模塊設(shè)計(jì)的Grep-Extract以及pitchfork攻擊類型。當(dāng)然,如果我們?cè)敢獾脑挘部梢蚤_發(fā)自己的Burp Extension。Sqlmap上也有-csrf-token以及-csrf-url參數(shù)來應(yīng)付類似場(chǎng)景,如果不使用這些命令,我們可以按照之前描述的方法來配置Burp,然后在sqlmap中通過-proxy參數(shù)與Burp配合使用。
在本文中,我們會(huì)介紹另一種辦法,那就是使用python中的CGIHTTPServer來完成這一任務(wù)。
二、實(shí)驗(yàn)環(huán)境
我們構(gòu)造了一個(gè)非常簡(jiǎn)單的PHP/mysql環(huán)境,登錄后,你可以訪問某個(gè)受限區(qū)域。你可以訪問此鏈接獲取實(shí)驗(yàn)所用的PHP代碼,以便在其他場(chǎng)景做些修改或調(diào)整。不要在意代碼細(xì)節(jié),畢竟我并不是PHP專家,只是熱衷于搭建滿足需求的測(cè)試環(huán)境而已。實(shí)驗(yàn)環(huán)境有助于我們理解測(cè)試過程,在現(xiàn)實(shí)場(chǎng)景中尋找真正目標(biāo)。
實(shí)驗(yàn)所用的CSRF tokens為一串隨機(jī)生成的SHA256散列字符串,每個(gè)HTTP請(qǐng)求都對(duì)應(yīng)一個(gè)不同的tokens。
三、面臨的問題
不經(jīng)過特殊配置時(shí),Burp不會(huì)檢測(cè)到這個(gè)問題。
同理,沒有使用-csrf-token參數(shù)時(shí),sqlmap也無能為力:
我使用了–technique、–dbms以及-p參數(shù)來加快掃描速度。由于這是一個(gè)簡(jiǎn)單的基于布爾值的SQL注入(boolean-based SQLi),我們只需要使用默認(rèn)的-level 1參數(shù)即可。但我們需要將-risk設(shè)置為3,因?yàn)橹挥惺褂幂^高的風(fēng)險(xiǎn)數(shù)值,我們才能測(cè)試OR類型的SQL注入(OR boolean-based SQLi)場(chǎng)景。OR類型的SQL注入非常危險(xiǎn),因?yàn)檫@種語句可以使任何條件的結(jié)果為真。比如,在使用WHERE子句的UPDATE或DELETE語句中,使用這種注入方式,你很有可能會(huì)不小心更新數(shù)據(jù)庫中所有用戶的密碼,或者導(dǎo)出用戶的憑據(jù)表,而這正是你在滲透測(cè)試中應(yīng)該盡力避免的結(jié)果。
在sqlmap中,我們可以使用–csrf-token=”mytoken”參數(shù)檢測(cè)到OR類型的SQL注入:
由于這是一個(gè)登錄驗(yàn)證表單,很明顯會(huì)對(duì)應(yīng)一條SELECT語句,這意味著使用最高的風(fēng)險(xiǎn)等級(jí)3不會(huì)帶來任何風(fēng)險(xiǎn)。
當(dāng)然,如果你有有效的憑據(jù)(實(shí)際滲透測(cè)試中你很難具備這個(gè)條件),此時(shí)該場(chǎng)景也會(huì)受AND類型的SQL注入(AND boolean-based SQLi)影響。然而,即使我擁有有效的憑據(jù),我首先還是會(huì)使用另一個(gè)(有效的)用戶名來尋找可用的OR類型SQLi,以免不小心鎖定賬戶(如果存在賬戶鎖定機(jī)制的話)。
在sqlmap中,我們可以使用–csrf-token=”mytoken”來檢測(cè)AND類型的SQL注入:
四、使用CGIHTTPServer
創(chuàng)建如下CGI腳本:
我們將該腳本命名為mask.py,存放在xxx/cgi-bin/目錄中,同時(shí)請(qǐng)確保.py文件為可執(zhí)行文件。創(chuàng)建該文件后,我們需要在xxx目錄中運(yùn)行python -m CGIHTTPServer命令。默認(rèn)情況下,服務(wù)器會(huì)在8000/tcp端口上監(jiān)聽。
首先,使用正確的密碼測(cè)試這個(gè)服務(wù)器:
然后,測(cè)試一下錯(cuò)誤的密碼:
現(xiàn)在,無需特殊配置,我們就可以使用Burp以及sqlmap來檢測(cè)SQL注入漏洞。
這就好像我們添加了一個(gè)中間層,可以簡(jiǎn)化CSRF tokens給我們測(cè)試過程所帶來的復(fù)雜度,現(xiàn)在我們無需刻意去提交這個(gè)token信息了。
五、參考文獻(xiàn)
[1] Sqlmap
[2] 另外我們還可以使用Mechanizer來完成類似功能,以便掃描器能夠檢測(cè)到響應(yīng)數(shù)據(jù)中存在的差異。
[3] Burp宏
[4] 對(duì)滲透測(cè)試人員較為實(shí)用的Python代碼
Python 和 JavaScript 是兩種廣泛應(yīng)用于 Web 開發(fā)的重要編程語言,在日常的 Web 開發(fā)和 Web 數(shù)據(jù)處理中,我們經(jīng)常需要使用這兩種語言。
例如,在 Web 端爬蟲過程中,我們可能會(huì)遇到需要解密網(wǎng)頁源代碼的情況,這時(shí)就需要一層一層剝離關(guān)鍵的 JS 代碼,并使用 Python 執(zhí)行這段代碼以獲取關(guān)鍵信息。
那么,Python 如何調(diào)用 JS 呢?有哪些方式呢?
以一段簡(jiǎn)單的JS腳本(add.js)為例,計(jì)算兩個(gè)數(shù)的和。
// JavaScript 示例代碼
function add(a, b) {
return a + b;
}
使用 Python 的os.popen或subprocess執(zhí)行 node 命令,執(zhí)行 JS 腳本。
首先,確保本地已經(jīng)安裝了 Node.js 環(huán)境:
> node -v
v18.16.1
修改 JS 腳本,新增一個(gè)導(dǎo)出函數(shù) init ,方便內(nèi)部函數(shù)被調(diào)用:
// JavaScript 示例代碼
function add(a, b) {
return a + b;
}
// 新增一個(gè)導(dǎo)出函數(shù)(node方式)
module.exports.init = function (arg1, arg2) {
// 調(diào)用函數(shù),并返回
console.log(add(arg1, arg2));
};
// 調(diào)用 init 方法并傳遞參數(shù)
module.exports.init(parseInt(process.argv[3]), parseInt(process.argv[4]));
使用subprocess模擬node.js命令行調(diào)用并獲取結(jié)果:
import subprocess
from loguru import logger
if __name__ == '__main__':
# 使用 subprocess 模塊執(zhí)行 Node.js 命令
result = subprocess.run(["node", "add.js", "init", "3", "5"], capture_output=True, text=True)
# 輸出執(zhí)行結(jié)果
logger.info(f"Node.js 執(zhí)行結(jié)果: {result.stdout.strip()}")
PyExecJS 是使用最多的一種方式,底層實(shí)現(xiàn)方式是本地 JS 環(huán)境下運(yùn)行 JS 代碼,支持的 JS 環(huán)境包含:Node.js、PhantomJS 等。
首先第一步安裝:
pip install PyExecJS==1.5.1
安裝完成之后,即可以使用其調(diào)用 JS 腳本:
#! -*-conding=: UTF-8 -*-
from loguru import logger
import execjs
# 定義 JavaScript 代碼
# js_code = """
# function add(a, b) {
# return a + b;
# }
# """
if __name__ == '__main__':
# Python 示例代碼
js_code = open("add.js", "r", encoding="utf-8").read()
# 使用 PyExecJS 執(zhí)行 JavaScript 代碼
ctx = execjs.compile(js_code)
# 調(diào)用 JavaScript 函數(shù),并計(jì)算結(jié)果
result = ctx.call("add", 3, 5)
logger.info(f"調(diào)用 JavaScript 函數(shù)的結(jié)果為: {result}")
DrissionPage方式
這款工具既能控制瀏覽器,也能收發(fā)數(shù)據(jù)包,甚至能把兩者合而為一。
首先安裝依賴庫:
pip install DrissionPage==4.0.4.22
執(zhí)行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from DrissionPage import ChromiumPage
if __name__ == '__main__':
page = ChromiumPage()
# 打開網(wǎng)頁
page.get("about:blank")
# 定義 JavaScript 代碼
js_code = """
function add(a, b) {
return a + b;
}
"""
# 在當(dāng)前頁面上執(zhí)行 JavaScript 代碼,并傳遞參數(shù)
result = page.run_js(js_code + " return add(8, 5)")
# 輸出執(zhí)行結(jié)果
print("JavaScript 執(zhí)行結(jié)果:", result) # JavaScript 執(zhí)行結(jié)果: 13
page.quit()
playwright方式
Playwright 是一個(gè)用于 Web 測(cè)試和自動(dòng)化的框架。
首先安裝依賴庫:
pip install playwright==1.43.0
playwright install # 安裝驅(qū)動(dòng)
執(zhí)行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from playwright.sync_api import sync_playwright
if __name__ == '__main__':
# 啟動(dòng) Playwright
with sync_playwright() as p:
# 啟動(dòng) Chromium 瀏覽器
browser = p.chromium.launch(headless=False)
# 創(chuàng)建新頁面
page = browser.new_page()
# 打開網(wǎng)頁
page.goto("https://baidu.com")
# 定義 JavaScript 代碼
js_code = """
function add(a, b) {
return a + b;
}
"""
page.add_script_tag(content=js_code) # 使用 page.add_script_tag() 方法將其注入到頁面中,然后在頁面上執(zhí)行它
# 在當(dāng)前頁面上執(zhí)行 JavaScript 代碼
result = page.evaluate("add(5, 7)")
# 輸出執(zhí)行結(jié)果
print("JavaScript 執(zhí)行結(jié)果:", result) # JavaScript 執(zhí)行結(jié)果: 12
# 關(guān)閉瀏覽器
browser.close()
selenium方式
Selenium是一個(gè)用于測(cè)試網(wǎng)站的自動(dòng)化測(cè)試工具,支持各種瀏覽器包括 Chrome、Firefox、Safari 等主流界面瀏覽器和 phantomJS 無界面瀏覽器。
首先安裝依賴庫:
pip install selenium==4.20.0
執(zhí)行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from selenium import webdriver
# 啟動(dòng) Chrome 瀏覽器
driver = webdriver.Chrome()
# 打開網(wǎng)頁
driver.get("about:blank")
# 定義 JavaScript 代碼
js_code = """
function add(a, b) {
return a + b;
}
"""
# 在當(dāng)前頁面上執(zhí)行 JavaScript 代碼,并傳遞參數(shù)
result = driver.execute_script(js_code + " return add(3, 5)")
# 輸出執(zhí)行結(jié)果
print("JavaScript 執(zhí)行結(jié)果:", result)
# 關(guān)閉瀏覽器
driver.quit()
類似的自動(dòng)化工具還有很多,如果只是單純的調(diào)用 JS 腳本,屬實(shí)有點(diǎn)殺雞用牛刀的趕jio。
Js2Py 作為一個(gè)純 Python 實(shí)現(xiàn)的 JS 解釋器,可以完全脫離 JS 環(huán)境,直接將 JS 代碼轉(zhuǎn)換為 Python 代碼。
首先第一步安裝:
pip install Js2Py==0.74
調(diào)用 JS 腳本:
#! -*-conding=: UTF-8 -*-
from js2py import eval_js
if __name__ == '__main__':
# JavaScript 示例代碼
js_code = """
function add(a, b) {
return a + b;
}
"""
# 執(zhí)行 JavaScript 代碼
result = eval_js(js_code + "add(3, 5)")
# 輸出執(zhí)行結(jié)果
print("JavaScript 執(zhí)行結(jié)果:", result)
PyMiniRacer 是一個(gè) Python 模塊,它提供了一個(gè)輕量級(jí)、快速且安全的方式來執(zhí)行 JavaScript 代碼,無需借助完整的 V8 引擎或 Node.js 環(huán)境。
不知道佬們用的多不多,據(jù)說速度比PyExecJS快不少。
直接安裝:
pip install py_mini_racer==0.6.0
運(yùn)行:
#! -*-conding=: UTF-8 -*-
from py_mini_racer import MiniRacer
if __name__ == '__main__':
# 創(chuàng)建 PyMiniRacer 實(shí)例
ctx = MiniRacer()
js_code = """
function add(a, b) {
return a + b;
}
"""
# 在 JavaScript 環(huán)境中執(zhí)行代碼并傳遞參數(shù)
ctx.eval(js_code)
result = ctx.call("add", 3, 5)
# 輸出執(zhí)行結(jié)果
print("JavaScript 執(zhí)行結(jié)果:", result) # JavaScript 執(zhí)行結(jié)果: 8
Python 中執(zhí)行和調(diào)用 JavaScript 代碼有多種方法:
每種工具都有其適用的場(chǎng)景和局限性,選擇合適的工具取決于具體的需求和項(xiàng)目要求。
原文鏈接:https://juejin.cn/post/7367701663169790002
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。