导航首页 » 站长干货 » 浅测 长亭雷池 WAF “动态防护”
浅测 长亭雷池 WAF “动态防护”
前言 雷池 WAF 社区版的更新速度是真快啊,几乎一周一个小版本,俩月一个大版本,攻城狮们真的狠啊,没法测了。 废话不多说,前两天看到了 这篇文章,对雷池的“动态防护”功能挺感兴趣,特地来试试。 安装部署 本文以测评为主,不再阐述部署过程,介绍一下我这里的测试环境: VM1:1Panel 部署 OpenResty,部署项目GitHub - Anyexyz/mcnav-astro: 基于 Astro 重制的 McNac 导航主题站点,IP(192.168.0.220) VM2:部署雷池 WAF 社区版,添加站点,开启“动态防护”,IP(192.168.0.225) 测试 扒取页面 通常,我会采用这种方式来复刻一个主题,最常用的就是直接从浏览器开发人员工具中扒取出页面的 html,css,js 等文件,来重制主题。 开启了雷池动态防护的页面,会有一个解密的过程,其实也就是 js 执行的过程 HTML 这个过程极大的延长了页面的加载时间,大致是 3s 左右。 页面打开后,对于元素发现页面构建相同,代表页面并没有因为加密而产生变形 可见页面已加密,不过加密也导致 索引 页面严重增大,看看后期有没有希望继续优化。 JS 加密了 js 文件尝试了一下,每次返回的js加密结果都不相同。 很明显是进行了混淆,不过经过文本对比后发现了端倪。 这里贴出完整 js 代码 // 源js文件 /*! * Lazy Load - JavaScript plugin for lazy loading images * * Copyright (c) 2007-2017 Mika Tuupola * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * Project home: * https://appelsiini.net/projects/lazyload * * Version: 2.0.0-beta.2 * */ (function(root, factory) { if (typeof exports === "object") { module.exports = factory(root); } else if (typeof define === "function" && define.amd) { define([], factory(root)); } else { root.LazyLoad = factory(root); } } )(typeof global !== "undefined" ? global : this.window || this.global, function(root) { "use strict"; const defaults = { src: "data-src", srcset: "data-srcset", selector: ".lazyload" }; /** * Merge two or more objects. Returns a new object. * @private * @param {Boolean} deep If true, do a deep (or recursive) merge [optional] * @param {Object} objects The objects to merge together * @returns {Object} Merged values of defaults and options */ const extend = function() { let extended = {}; let deep = false; let i = 0; let length = arguments.length; /* Check if a deep merge */ if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") { deep = arguments[0]; i++; } /* Merge the object into the extended object */ let merge = function(obj) { for (let prop in obj) { if (Object.prototype.hasOwnProperty.call(obj, prop)) { /* If deep merge and property is an object, merge properties */ if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") { extended[prop] = extend(true, extended[prop], obj[prop]); } else { extended[prop] = obj[prop]; } } } }; /* Loop through each object and conduct a merge */ for (; i < length; i++) { let obj = arguments[i]; merge(obj); } return extended; }; function LazyLoad(images, options) { this.settings = extend(defaults, options || {}); this.images = images || document.querySelectorAll(this.settings.selector); this.observer = null; this.init(); } LazyLoad.prototype = { init: function() { /* Without observers load everything and bail out early. */ if (!root.IntersectionObserver) { this.loadImages(); return; } let self = this; let observerConfig = { root: null, rootMargin: "0px", threshold: [0] }; this.observer = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.intersectionRatio > 0) { self.observer.unobserve(entry.target); self.loadImage(entry.target); } }); } ,observerConfig); this.images.forEach(function(image) { self.observer.observe(image); }); }, loadAndDestroy: function() { if (!this.settings) { return; } this.loadImages(); this.destroy(); }, loadImage: function(image) { image.onerror = function() { image.onerror = null; image.src = image.srcset = image.dataset.original; } ; let src = image.getAttribute(this.settings.src); let srcset = image.getAttribute(this.settings.srcset); if ("img" === image.tagName.toLowerCase()) { if (src) { image.dataset.original = image.src; image.src = src; } if (srcset) { image.srcset = srcset; } } else { image.style.backgroundImage = "url(" + src + ")"; } }, loadImages: function() { if (!this.settings) { return; } let self = this; this.images.forEach(function(image) { self.loadImage(image); }); }, destroy: function() { if (!this.settings) { return; } this.observer.disconnect(); this.settings = null; } }; root.lazyload = function(images, options) { return new LazyLoad(images,options); } ; if (root.jQuery) { const $ = root.jQuery; $.fn.lazyload = function(options) { options = options || {}; options.attribute = options.attribute || "data-src"; new LazyLoad($.makeArray(this),options); return this; } ; } return LazyLoad; });   // 动态防护加密后的js文件 function vgo8rYXzpS() { var YIhUo91Nlh = 99.6174697329428; while (YIhUo91Nlh < 6) { YIhUo91Nlh++ } var kJsBQ2iTCw = 77.7991427720637; while (kJsBQ2iTCw < 8) { kJsBQ2iTCw++ } var Uv8SujYUUJ = 54.122410119766634; 62.94717341414315 + 14.215159769026501; "eCDkWHqKcu"; 20.29250300507593 + 96.90578776550426; var hKDl2Z6IyR = 2.1154780179250436; while (hKDl2Z6IyR < 9) { hKDl2Z6IyR++ } var jJJdYPyWC8 = 96.35369160356686; while (jJJdYPyWC8 < 10) { jJJdYPyWC8++ } var q1lUq8lALI = 79.3826780702858; var KSm4kSmK5Q = 16.811363665066132; while (KSm4kSmK5Q < 5) { KSm4kSmK5Q++ } while (q1lUq8lALI < 5) { q1lUq8lALI++ } var k8jxtioSu1 = 46.12863667479478; if (k8jxtioSu1 < 50) VdgkMuAloP("dbKMKN3DiD"); else VdgkMuAloP("Z_GUlDIf7g"); 32.61116098968565 + 39.92340222133316; var WOIqRFoBWI = 35.570788142150256; while (WOIqRFoBWI < 10) { WOIqRFoBWI++ } var REP52ajkkB = 68.57029249635578; while (REP52ajkkB < 9) { REP52ajkkB++ } var UvGT8ugsmm = 77.45257249038768; var c_XLMPoMhw = 70.0508383263844; var oXNng_nyI3 = 61.714023740614785; "f3dzUmlSrt"; while (oXNng_nyI3 < 8) { oXNng_nyI3++ } "oiou9de1Yg"; "jdpOma9ApF"; var NeReO5OH2M = 63.89278655453103; while (NeReO5OH2M < 8) { NeReO5OH2M++ } var _p_ydR_UZY = 83.88263735619535; var F85mcn2g_m = 17.165604886412726; while (F85mcn2g_m < 10) { F85mcn2g_m++ } 24.428701219017995 + 36.33105120927406; var E_btPRjrmk = 95.02151619364821; var No5m6438qj = 4.1049208686863246; while (No5m6438qj < 9) { No5m6438qj++ } while (E_btPRjrmk < 6) { E_btPRjrmk++ } var NW66eJHW18 = 80.32092123501981; if (NW66eJHW18 < 50) VdgkMuAloP("wVsjIS9XQo"); else VdgkMuAloP("GoLW5hTcVj"); 43.682142399473555 + 22.477837399452866; var UNuZiogsXq = 70.37483244640134; while (UNuZiogsXq < 6) { UNuZiogsXq++ } var JyjoRvjvV4 = 60.33084553561216; "PPLO3pqrCR"; function VdgkMuAloP() { "CCutBlYuiL"; "MgmL5Sv_33"; 19.82880014765916 + 66.83450544153038; var eH8bW0LeRO = 91.84505170089825; var GGEb99P0LW = 92.75726773787632; "eM_DBnNLNQ"; "LTExkL39fU"; var ayFeMZ7J9o = 4.08422739984733; var rvzNYoM37B = 42.468405912837106; while (rvzNYoM37B < 6) { rvzNYoM37B++ } "YLovxab17O"; var dpUNCcw57i = 4.9146145098517575; while (dpUNCcw57i < 10) { dpUNCcw57i++ } var ZjzssshCHy = 22.711581319339555; "lsyj2Pu6bi"; "mAdio22F97"; 95.9152148251555 + 18.563789346616783; "Kisq7F_TOW"; var EO9rGZSTTK = 53.3184198670574; while (EO9rGZSTTK < 6) { EO9rGZSTTK++ } var Lfrg2SayBj = 96.40296951052316; var SR4gkdmFPm = 24.691037844119176; while (SR4gkdmFPm < 7) { SR4gkdmFPm++ } "njAS_NShim"; "DIoi_JwNCk"; var qZALlgtAos = 65.84687374547939; while (qZALlgtAos < 5) { qZALlgtAos++ } "i8UnwEQqP2"; var mkzN8inJtT = 89.67717243925355; "EXgVlnAkaM"; var HGgVbs9bD5 = 56.50704313244045; var myQFrz2kY4 = 54.55344568694437; while (myQFrz2kY4 < 8) { myQFrz2kY4++ } var VcC388Sonl = 78.22901590625897; while (VcC388Sonl < 5) { VcC388Sonl++ } var EDQM5T4i5x = 58.12080899105871; while (EDQM5T4i5x < 8) { EDQM5T4i5x++ } var lS3HRC8N0e = 42.29800294748819; while (lS3HRC8N0e < 5) { lS3HRC8N0e++ } } } (function(that, a) { var checkF = new RegExp("\\w *\\(\\){.+}"); "Saz5menkPn"; var checkR = new RegExp("(\\[x|u](\\w){2,4})+"); var checkFunction = function checkFunction1() { if (checkR.test(checkFunction.toString())) { f2([2, 15, 12]) } ;return '\x63\x68\x65\x63\x6b\x46\x75\x6e\x63\x74\x69\x6f\x6e' }; var f1 = function f1(a) { a.push[a]; f2(a) }; var f2 = function f2(a) { a.push[a]; f1(a) }; if (!checkF.test(checkFunction.toString())) { f2([]) } else if (checkR.test(checkFunction.toString())) { f2([1, 3, 7]) } ;"ISXAG9bapu"; var KOaO2Jk15j = 13.366279497772231; KOaO2Jk15j = 65.44109390187671; return a(that); function f5OTtZ1pUr() { "PFAZrkUkjJ"; "yohosCBZku"; "czcc_QG98P"; var Y7ZMWHKbB5 = 54.61165307973092; while (Y7ZMWHKbB5 < 7) { Y7ZMWHKbB5++ } "RAAE3i3HNJ"; var yYJU5WMbNs = 81.78463513401672; var Dsj0YbE3nh = 60.12962678573978; while (Dsj0YbE3nh < 8) { Dsj0YbE3nh++ } "OrNvH3Vm8U"; var FcVeaK_8CJ = 70.65213865609662; var V10P1fXl1e = 93.28700416475893; while (V10P1fXl1e < 7) { V10P1fXl1e++ } var _jQaUeEOlz = 50.09958863458343; while (_jQaUeEOlz < 6) { _jQaUeEOlz++ } "mkyDT6LuXp"; "i_d0Jej01W"; 93.1178573977863 + 65.0171586053574; "MdcdXdZD8e"; var FvwOTr68cW = 63.96686898919228; while (FvwOTr68cW < 5) { FvwOTr68cW++ } 12.007514883700402 + 67.83201664204582; var lVk87OnDY0 = 10.352772574019035; while (lVk87OnDY0 < 10) { lVk87OnDY0++ } "ZIxYt7RDz5"; var HOjmKYxZYn = 73.07394273998264; var xf5LYnXM_h = 34.42670716048105; while (xf5LYnXM_h < 7) { xf5LYnXM_h++ } 25.31980979829108 + 70.92299314386324; 53.64987099085665 + 15.95767193794893; 81.04615728361688 + 53.03190420900158; "xMyhHs6tqa"; var CicbLkYxKL = 71.43209809856342; while (CicbLkYxKL < 9) { CicbLkYxKL++ } 81.82768180662697 + 44.54696909044475; "a7S1hc6l6e"; 40.02457556515699 + 50.13884740950273 } } )(this, function(that) { var EfanXdEsAo = 45.044183852209066; var YiD8rJkjM4 = 60.40560906974519; while (YiD8rJkjM4 < 9) { YiD8rJkjM4++ } var SFXCSJnYT5 = 5.6590674829357; function DROWk3baLH() { var zJ2eGCAqG6 = 88.73517894514487; while (zJ2eGCAqG6 < 7) { zJ2eGCAqG6++ } "fVZRgjskF7"; var imVKfLWElR = 98.4392536479853; var JRZm9ZRXt9 = 65.52198475056669; "B07bldh2rt"; 94.61531928891331 + 21.79165407508193; "H7umcmyF_g"; var kUwyNiUzjX = 48.5975080540464; while (kUwyNiUzjX < 5) { kUwyNiUzjX++ } var G5q4i5ptYT = 17.20767169078439; while (G5q4i5ptYT < 9) { G5q4i5ptYT++ } "S0RQAJX7ZD"; var sbwEsBL3on = 31.621188048769; var Rbqnn2M5lo = 1.6814855430946412; var wXdYUzqLKS = 53.13735728383625; var iIMDA_Qowp = 87.59602310423611; 55.899852486295956 + 23.463153124052145; 49.64055650210554 + 21.699124979927305 } }); (function(root, factory) { if (typeof exports === "object") { module.exports = factory(root) } else if (typeof define === "function" && define.amd) { define([], factory(root)) } else { root.LazyLoad = factory(root) } 20.075305793669145 + 96.72088665263502; function mCbgSrID5z() { var ymZDdeQQne = 84.05118287547904; while (ymZDdeQQne < 8) { ymZDdeQQne++ } "oeSlUltLf7"; var vRcSMA7HZy = 95.63940228416716; while (vRcSMA7HZy < 5) { vRcSMA7HZy++ } 42.847416356461686 + 64.228599747433; var S4X325xZd0 = 36.8477478357082; var OjdsnE6IgU = 54.6819719737484; while (OjdsnE6IgU < 7) { OjdsnE6IgU++ } var tsdIhKV6Tu = 21.849203694513204; "IBEZHnHB9P"; var W1xUDNOclb = 97.45176245010938; var qBhKSMePxI = 53.918246237085604; while (qBhKSMePxI < 8) { qBhKSMePxI++ } var tG5h3fCZpA = 8.9527278684316; 1.8795339533222326 + 85.30147367116075; 3.4838274267666733 + 52.70631782675951; var sglVSvKjZv = 13.453736652916252; while (sglVSvKjZv < 9) { sglVSvKjZv++ } var bzJ8IfE03K = 72.4963090140686; var IzYpLOgN6D = 1.7126081902147487; 86.90125410102027 + 60.096220564929666; 55.32420449194843 + 93.21714769547813; 15.44123941754805 + 88.74042551968007; "ayjAX7QOFR"; "nsviM21tO7"; "RGvq8LBnOO"; 2.5365166268296333 + 58.41895276641477; var NwT9TZgChj = 3.2736264569624316; "ZVRMQfyCrJ"; "fwutOlKiEI"; var Ejy2yBkKAt = 51.83509013431559; while (Ejy2yBkKAt < 7) { Ejy2yBkKAt++ } 92.07691206149254 + 13.437580090223227; "qdd7jYm20k"; var j2KtWorODN = 42.14264503067741; 2.47851999站长工具导航网6620122 + 58.627727544483704 } } )(typeof global !== "undefined" ? global : this.window || this.global, function(root) { "use strict"; var defaults = { src: "data-src", srcset: "data-srcset", selector: ".lazyload" }; var extend = function extend1() { var extended = {}; var deep = false; var i = 0; var length = arguments.length; if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") { deep = arguments[0]; i++ } var merge = function merge(obj) { for (var prop in obj) { if (Object.prototype.hasOwnProperty.call(obj, prop)) { if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") { extended[prop] = extend(true, extended[prop], obj[prop]) } else { extended[prop] = obj[prop] } } } }; for (; i < length; i++) { var obj = arguments[i]; merge(obj) } return extended }; function LazyLoad(images, options) { this.settings = extend(defaults, options || {}); this.images = images || document.querySelectorAll(this.settings.selector); this.observer = null; this.init() } LazyLoad.prototype = { init: function init() { if (!root.IntersectionObserver) { this.loadImages(); return } var self = this; var observerConfig = { root: null, rootMargin: "0px", threshold: [0] }; this.observer = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.intersectionRatio > 0) { self.observer.unobserve(entry.target); self.loadImage(entry.target) } }) } ,observerConfig); this.images.forEach(function(image) { self.observer.observe(image) }) }, loadAndDestroy: function loadAndDestroy() { if (!this.settings) { return } this.loadImages(); this.destroy() }, loadImage: function loadImage(image) { image.onerror = function() { image.onerror = null; image.src = image.srcset = image.dataset.original } ; var src = image.getAttribute(this.settings.src); var srcset = image.getAttribute(this.settings.srcset); if ("img" === image.tagName.toLowerCase()) { if (src) { image.dataset.original = image.src; image.src = src } if (srcset) { image.srcset = srcset } } else { image.style.backgroundImage = "url(" + src + ")" } }, loadImages: function loadImages() { if (!this.settings) { return } var self = this; this.images.forEach(function(image) { self.loadImage(image) }) }, destroy: function destroy() { if (!this.settings) { return } this.observer.disconnect(); this.settings = null } }; root.lazyload = function(images, options) { return new LazyLoad(images,options) } ; if (root.jQuery) { var $ = root.jQuery; $.fn.lazyload = function(options) { options = options || {}; options.attribute = options.attribute || "data-src"; new LazyLoad($.makeArray(this),options); return this } } 98.21293314139757 + 7.022202427695869; return LazyLoad; var zb5YrDEzX8 = 49.67145292566205; function EMQ2TiywJ2() { "kDDG4hcurX"; "LmMQDl5Guf"; "H1d2hSNdZu"; "vR3uU0dztV"; "BYg6Cwwew1"; "Z7Cgb85The"; var vqCn2LKHiQ = 79.8849526204871; while (vqCn2LKHiQ < 6) { vqCn2LKHiQ++ } "HzKhtzFo0S"; var Ruo3QF3HKv = 57.10873587557603; while (Ruo3QF3HKv < 8) { Ruo3QF3HKv++ } var NIVPEUabT_ = 25.838978101412078; var pmvJIgXrA7 = 41.71629707156116; while (pmvJIgXrA7 < 7) { pmvJIgXrA7++ } var cTqhNJmnqp = 7.679109504729966; var Xkldnu7eiS = 89.26080892492617; while (Xkldnu7eiS < 8) { Xkldnu7eiS++ } var Iq6adjqOVj = 86.04734679658776; while (Iq6adjqOVj < 7) { Iq6adjqOVj++ } var TyC7F0mXPj = 57.405394830228786; while (TyC7F0mXPj < 7) { TyC7F0mXPj++ } var q7oS54FoCf = 19.715578974920984; 6.354381716758419 + 48.514464467999424; var JPOOCo51Cg = 94.50513995137923; 18.85838453981073 + 55.22787281970704; "rUww9Es4UQ" } });   可见该加密方式采用了: 变量名和函数名替换:将原有的变量名和函数名替换为难以理解的字符或字符串,例如vgo8rYXzpS、YIhUo91Nlh等。 字符串混淆:将代码中的字符串通过某些算法转换为难以阅读的形式。 控制流改变:通过添加无意义的循环、条件判断等,改变代码的控制流,使得代码执行过程变得复杂。 代码拆分:将代码拆分为多个部分,并通过某些机制动态地组合执行。 可见还是较为容易反混淆的,期待后期加强。 python 爬取 根据 官方文档 所述,动态防护还是为了可以更好地阻止爬虫和攻击自动化程序的分析,那么就尝试编写一段python代码来进行 HTML 内容爬取测试。 比如爬取 本站导航站,这里使用 Microsoft 的 playwright 库 import asyncio from playwright.async_api import async_playwright async def scrape_data(): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() # 加载页面 await page.goto('http://192.168.0.220') # 等待页面加载完成 await page.wait_for_load_state('networkidle') # 提取链接、图标和描述 items = await page.query_selector_all('.list-item.block') data = [] for item in items: link = await item.query_selector('a.list-content') if link: href = await link.get_attribute('href') title = await link.query_selector('.list-title') desc = await link.query_selector('.list-desc') img = await item.query_selector('img') data.append({ 'link': href, 'title': await title.inner_text() if title else None, 'desc': await desc.inner_text() if desc else None, 'icon': await img.get_attribute('src') if img else None, }) await browser.close() return data # 运行 async def main(): data = await scrape_data() for entry in data: print(entry) asyncio.run(main()) 源站执行爬取后输出: 雷池防护后: 效果明显,不过,感觉还是有绕过的空间呀?试试浏览器有头模式? import asyncio from playwright.async_api import async_playwright async def scrape_data(): async with async_playwright() as p: # 指定浏览器路径并启用有头模式 browser = await p.chromium.launch( headless=False, # 设置为 False 以显示浏览器窗口 executable_path="C:\\Users\\Anye\\AppData\\Local\\Chromium\\Application\\chrome.exe" ) page = await browser.new_page() # 加载本地服务器上的页面 await page.goto('http://192.168.0.225/') # 手动处理人机验证 print("请手动处理页面上的人机验证...") await page.wait_for_selector('.list-item.block', timeout=0) # 等待页面加载完成,没有超时限制 # 提取链接、图标和描述 items = await page.query_selector_all('.list-item.block') data = [] for item in items: link = await item.query_selector('a.list-content') if link: href = await link.get_attribute('href') title = await link.query_selector('.list-title') desc = await link.query_selector('.list-desc') img = await item.query_selector('img') data.append({ 'link': href, 'title': await title.inner_text() if title else None, 'desc': await desc.inner_text() if desc else None, 'icon': await img.get_attribute('src') if img else None, }) await browser.close() return data # 运行 async def main(): data = await scrape_data() for entry in data: print(entry) asyncio.run(main()) 结果:成功获取内容 既然这样,那岂不是等待解密后就可以获取内容了,那么等待5秒试试? import asyncio from playwright.async_api import async_playwright async def scrape_data(): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() # 加载页面 await page.goto('http://192.168.0.225') # 等待页面加载完成 await page.wait_for_load_state('networkidle') # 等待5秒 await page.wait_for_timeout(5000) # 提取链接、图标和描述 items = await page.query_selector_all('.list-item.block') data = [] for item in items: link = await item.query_selector('a.list-content') if link: href = await link.get_attribute('href') title = await link.query_selector('.list-title') desc = await link.query_selector('.list-desc') img = await item.query_selector('img') data.append({ 'link': href, 'title': await title.inner_text() if title else None, 'desc': await desc.inner_text() if desc else None, 'icon': await img.get_attribute('src') if img else None, }) await browser.close() return data # 运行 async def main(): data = await scrape_data() for entry in data: print(entry) asyncio.run(main()) 成功获取。 雷池开发别打我,HTML 确实不太好加密 不过目前来讲确实可以拦截大部分爬虫的爬取,正常爬虫不会长时间等待页面加载,也不会用有头模式。 测试++ 经测试,开启 人机验证 后,是可以有效拦截爬虫获取内容。 不过还是希望雷池开发大大可以继续研究研究如何加强“动态防护”的算法。 后记 不让黑客,越雷池一步。 本次测试为内部测试环境,请勿用于黑客攻击行为。后期雷池也会加强加密算法,保护 WEB 安全。 转自:https://www.anye.xyz/archives/bnKkYHfw