0%

JAVA反序列话串记

前言

java的反序列化看一些,ysoserial和fastjson以及shiro的,但是笔记没怎么做。这篇文章主要做笔记给自己看,把java反序列化中的链串一下,可能只有我自己能看懂吧😂。当然如果你已经跟完所有的ysoserial代码,这篇文章也可以帮你梳理。

阅读全文 »

第一部分:背景

衔接:(一直没有落地的统一的建设标准)基于此

第二部分:引入标准 说明标准 说明范围 做什么用。标准出具时间。

第三部分:标准内的引入的安全性的检测。

第四部分:因为现在面临的巨大的安全风险。

第五部分:各种风险的介绍

第六部分:食品追溯系统作为食品安全的重要保障之一,它本身的安全需要防护。

​ 网络安全作为战略保障之一,食品追溯系统安全应紧跟国家号召。

(cfca能力)第七部分:管理安全体系建设

(cfca能力)第八部分:技术安全(个人信息安全、网络系统安全(等保、密评)、数据安全)能力列出来

结尾:

DownunderCTF 2023 writeup

前言

这比赛周末打的,web题目做出来一半(简单的那一半),medium以上的一道题目没做出来,名次由于这次只有我一个人参加,而我只会做些web和misc以及一点点crypto,逆向和pwn完全不会,而且国外的套路和国内还是不一样啊。最终排名也是泯然众人,中间名次。看了看后来的wp,简单的写一些这次收获到内容的一些题目吧。

这个比赛很好的一点在于提供了所有的题目环境,下次再出题正好改改。😂

题目环境地址:https://github.com/DownUnderCTF/Challenges_2023_Public/

阅读全文 »

python中执行速度的技术选择

前言

最近在开发一个扫描的项目,很多时候,发现一个函数的执行比较频繁且缓慢,我不知道应该用多线程、协程、还是多进程 或是消息队列等。

这说明目前开发水平太差,还是有很多需要学习的地方。所以就想着学习一些各个技术,然后简单的做个笔记啊,并总结出什么时候用哪种技术,可以让整个扫描更快。当然目前还是自嗨开发小项目阶段,没做过大项目工程,有见解不对的地方还望看到的人指正。

后面主要介绍多线程、协程、消息队列和异步。

多线程

python一提起多线程,我们搜到的资料基本就会说是鸡肋,是没用的,应该使用协程。以前我也没有好好的深究过这个问题,现在我们来看下python的多线程到底有没有用?

首先网上的资料都会说到GIL的问题导致python多线程很鸡肋,那什么是GIL锁?

GIL锁

GIL的存在主要是为了防止Python解释器中的数据结构被多个线程同时修改,导致数据结构出现不一致的情况。通过限制同一时刻只有一个线程能够执行Python字节码,GIL可以确保Python解释器中的数据结构不会被多个线程同时修改,从而保证线程安全。

测试

我们写一个多线程和普通执行的测试,都执行5000次计算,一个单线程执行,一个多线程执行:

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
# 打印随机数的函数
def print_random():
for i in range(500):
result = 9999999919+5678987656
# response = requests.get("https://www.baidu.com")
# print(response)


# 创建线程并启动
def create_threads():
start_time = time.time()
threads = []
def ppdom():
result = 9999999919+5678987656
# response = requests.get("https://www.baidu.com")
# print(response)
for i in range(500): # 创建500个线程
thread = threading.Thread(target=ppdom)
thread.start()
for thread in threads:
thread.join()
end_time = time.time()
execution_time = end_time - start_time
print("多线程执行耗时:", execution_time)

def create_singal():
start_time_signal = time.time()
print_random()
end_time_signal = time.time()
print(start_time_signal)
print(end_time_signal)
execution_time1 = end_time_signal - start_time_signal
print("单线程执行耗时:", execution_time1)
# 调用函数
if __name__ == '__main__':
create_singal()
create_threads()

执行多次发现,多线程比单线程的耗时更长(注意这里单线程是e-05次方):

![image-20230904140830892](/Users/geez/Library/Application Support/typora-user-images/image-20230904140830892.png)

这真的很离谱,多线程好像还不如单线程呢,完全没必要用到多线程。难道真的就是网上说的啥时候都别用多线程就对了吗?

那再看看下面这个代码:

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
import threading
import random
import time
import requests



## 多线程和单线程的比较

# 打印随机数的函数
def print_random():
for _ in range(5):
# result = 99+100
response = requests.get("https://www.baidu.com")
print(response)


# 创建线程并启动
def create_threads():
start_time = time.time()
threads = []
def ppdom():
# result = 99+100
response = requests.get("https://www.baidu.com")
print(response)
for _ in range(5): # 创建5个线程
thread = threading.Thread(target=ppdom)
thread.start()
end_time = time.time()
execution_time = end_time - start_time
print("多线程执行耗时:", execution_time)

def create_singal():
start_time = time.time()
print_random()
end_time = time.time()
execution_time = end_time - start_time
print("单线程执行耗时:", execution_time)
# 调用函数
if __name__ == '__main__':
create_threads()
create_singal()

这里我们仅修改函数从原来的简单计算改为网络请求,运行结果如下:

![image-20230901172004526](/Users/geez/Library/Application Support/typora-user-images/image-20230901172004526.png)

同样执行五次请求,这时候我们可以发现多线程远远快于单线程,这是为什么呢?

因为耗时的IO应用(内存、网络、硬盘等等读取属于IO密集型运算)并不影响线程的执行,也就是cpu和IO是可以并行的。由于上面的代码中 request.get() 一个 I/O 密集型操作,即主要花费时间在等待网络 I/O 操作完成上。由于线程是独立的,一个线程在等待网络响应时,其他线程可以继续执行,从而最大程度上减少了阻塞等待的时间。所以我们也能看到速度飞快。

结论

由此我们可以得出结论,在GIL锁存在的情况下,如果程序是IO密集型的,那么多线程可以极大的加快速度。但如果程序不是 I/O 密集型时,多线程可能并不能提高性能,甚至还可能因为线程间的上下文切换导致额外的开销。另外由于GIL锁的存在,即使你的CPU多核,也很难发挥作用。所以多线程的运用与否主要考虑是否是IO密集型的操作。

协程

上面说到了多线程,现在再来看看协程是怎么回事。

概念
Python 3 引入了协程(coroutine)的概念,通过使用关键字 async 和 await 实现。协程是一种轻量级的并发编程方式,支持在单线程中实现并发执行的效果。

下面是Python 3中协程的一些重要特点和概念:

  • 协程与生成器(generator):协程使用async def定义,并通过await关键字来挂起执行和等待其他协程完成。协程本质上是一种特殊的生成器,利用生成器的yield关键字进行状态保存和恢复。
  • async 和 await关键字:async关键字用于定义协程函数,表示函数是一个可以被挂起和恢复的协程。await关键字用于挂起协程的执行,等待另一个协程完成或者等待I/O操作完成。
  • 非阻塞的等待:协程可以在等待I/O完成时挂起执行,允许其他协程继续执行。这种非阻塞的等待方式使得协程能够充分利用CPU和I/O资源,提高并发性能。
  • 事件循环(event loop):Python 3的协程通常会在事件循环中执行。事件循环负责调度多个协程,使它们能够交替执行和等待,以实现并发效果。
  • 异步I/O支持:协程在处理I/O密集型任务时特别有效。常用的异步I/O库例如asyncio提供了高级的异步编程机制,用于处理协程之间的调度和协作。

测试
我们再次编写一个测试函数,分别用到了协程、多线程和单线程,分别执行50次的请求百度的运算:

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
68
69
70
71
72
73
74

import requests
import threading
import asyncio
import time

# 普通执行版本
def normal_execution():
start_time = time.time()
for _ in range(50):
# result = 99+1000
response = requests.get("https://www.baidu.com")
# print(response)
end_time = time.time()
execution_time = end_time - start_time
print("普通执行耗时:", execution_time)

# 多线程执行版本
def threaded_execution():
start_time = time.time()
threads = []

def thread_function():
# result = 99+1000
response = requests.get("https://www.baidu.com")
# print(response)

for _ in range(50):
thread = threading.Thread(target=thread_function)
threads.append(thread)
thread.start()

for thread in threads:
thread.join()

end_time = time.time()
execution_time = end_time - start_time
print("多线程执行耗时:", execution_time)

async def fetch(session):
url = 'https://www.baidu.com'
async with session.get(url) as response:
return await response.text()

async def request_baidu():
async with aiohttp.ClientSession() as session:
tasks = []
for _ in range(50):
task = asyncio.ensure_future(fetch(session))
tasks.append(task)
responses = await asyncio.gather(*tasks)



# 比较函数
def compare_execution_time():
print("开始普通执行...")
normal_execution()

print("\n开始多线程执行...")
threaded_execution()

print("\n开始协程执行...")
start_time = time.time()
loop = asyncio.get_event_loop()
results = loop.run_until_complete(request_baidu())
end_time = time.time()
execution_time = end_time - start_time
print("协程执行耗时:", execution_time)

# 调用比较函数
if __name__ == '__main__':
compare_execution_time()

执行结果如下:

![image-20230904141410552](/Users/geez/Library/Application Support/typora-user-images/image-20230904141410552.png)

可以看到协程速度飞快,

我们再换成IO非密集操作仅作算数计算,同样都计算500次:

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
68
69
70
71
72
import requests
import threading
import asyncio
import time

# 普通执行版本
def normal_execution():
start_time = time.time()
for _ in range(500):
result = 99999+54673829
# response = requests.get("https://www.baidu.com")
# print(response)
end_time = time.time()
execution_time = end_time - start_time
print("普通执行耗时:", execution_time)

# 多线程执行版本
def threaded_execution():
start_time = time.time()
threads = []

def thread_function():
result = 99999+54673829
# response = requests.get("https://www.baidu.com")
# print(response)

for _ in range(500):
thread = threading.Thread(target=thread_function)
threads.append(thread)
thread.start()

for thread in threads:
thread.join()

end_time = time.time()
execution_time = end_time - start_time
print("多线程执行耗时:", execution_time)

async def fetch(session):
result = 99999+54673829

async def request_baidu():
async with aiohttp.ClientSession() as session:
tasks = []
for _ in range(500):
task = asyncio.ensure_future(fetch(session))
tasks.append(task)
responses = await asyncio.gather(*tasks)



# 比较函数
def compare_execution_time():
print("开始普通执行...")
normal_execution()

print("\n开始多线程执行...")
threaded_execution()

print("\n开始协程执行...")
start_time = time.time()
loop = asyncio.get_event_loop()
results = loop.run_until_complete(request_baidu())
end_time = time.time()
execution_time = end_time - start_time
print("协程执行耗时:", execution_time)

# 调用比较函数
if __name__ == '__main__':
compare_execution_time()


执行结果:

![image-20230904141620788](/Users/geez/Library/Application Support/typora-user-images/image-20230904141620788.png)

可以看到协程速度虽然比多线程快,但还不如单线程,这就又回到了前面那样,在计算密集型计算中协程和多线程都是弟弟水平。但是协程度又确实比多线程快,那是不是以后需要用到多线程的地方直接用协程就行?

当然不是,如果注意观察可以看到上述代码中请求百度的库,别的代码使用的是requests,而协程使用的是aiohttp,这是因为requests不支持异步,也就没办法支持协程。另外协程的编程复杂度也高于多线程。所以很多时候在协程库不支持或是协程复杂度实现不能接受的时候,可以考虑使用多线程。

结论:

CPU密集型操作协程速度大于多线程但不如单线程,IO密集型操作协程远远大于多线程和单线程。

多进程

上面的比较又引出一个新的问题,CPU密集型的运算中 难道就只能使用单线程吗?

当然不是,这里我们引入多进程的概念:

  • Python中的多进程是指同时运行多个独立进程的能力。每个进程都有自己独立的内存空间和资源,可以并行地执行任务。这种并行和独立的特性使得多进程在处理计算密集型任务和提高CPU利用率方面非常有效。Python提供了multiprocessing模块来支持多进程编程

测试CPU密集型计算:

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

import time
import multiprocessing

def cpu_intensive_calculation():
total = 0
for i in range(20000000):
total += i
return total

def single_threaded():
start_time = time.time()

for i in range(8):
cpu_intensive_calculation()

end_time = time.time()
elapsed_time = end_time - start_time
print(f"单线程执行耗时: {elapsed_time} seconds")
def multi_process1():
start_time = time.time()

num_processes = multiprocessing.cpu_count() # 获取CPU核心数量 8个
print(num_processes)
num_tasks = 5000

processes = []
for _ in range(num_processes):
process = multiprocessing.Process(target=cpu_intensive_calculation)
processes.append(process)
process.start()

for process in processes:
process.join()
end_time = time.time()
elapsed_time = end_time - start_time
print(f"多进程执行耗时: {elapsed_time} seconds")

if __name__ == '__main__':
single_threaded()
multi_process1()

执行结果如下

![image-20230904143720227](/Users/geez/Library/Application Support/typora-user-images/image-20230904143720227.png)

可以看到 多进程在CPU密集型计算中会更有优势一点。

消息队列

其实协程中就有异步的概念,消息队列也有点异步的意思,严格来说消息队列和线程、进程不是一类技术,它是为了解决另一个问题:解耦、异步、削峰。

解耦:比如打卡系统和考勤系统是关联的,那么如果中间加入消息队列,打卡系统就只需要把打卡的数据放入消息队列由考勤系统去取就行。不必关心这两者系统的关联。

异步:多人打卡时可能每个打卡到都需要记录到考勤系统,但不可能每个人都是打完卡记录完以后才能下一个人打开,消息队列可以异步处理。简单说就是 打卡时打卡,考勤记录是考勤记录,中间由消息队列提供缓存和消息传递。

削峰:并发访问高峰期,可以缓存到中间件中减少对其他任务的压力。比如发送邮件是耗时应用,每天定期发送的邮件可能有几封,但是一家公司可能有上千人,这时候发送邮件就可以进入消息队列,然后再慢慢发送,防止流量过载。

消息队列的使用demo:

1、安装celery和redis

1
pip install celery

2、创建使用celery的应用

1
2
3
4
5
6
7
8
9
10
from celery import Celery

# 创建 Celery 应用
app = Celery('myapp', broker='redis://localhost:6379/0')

# 定义任务
@app.task
def add(x, y):
return x + y

3、启动celry服务端,也就是启动消息队列:

1
celery -A tasks worker --loglevel=info

4、其他函数调用消息队列

1
2
3
4
from tasks import add

result = add.delay(4, 6)
print(result.get())

什么时候使用?耗时应用需要解耦、异步、削峰处理时使用此技术。

比如一个爬虫,它需要爬去、解析内容、记录到数据库。

那每个任务都可以写成多线程,然后进入消息队列,下一个任务直接从消息队列中取并继续压入消息队列:

怎么选择

如果是CPU密集型任务,那当然直接多进程。

如果是IO密集型任务,就有两种选择多线程和协程,如果协程库支持不完善,代码复杂度超出能力。那就选择多线程,否则选择协程,毕竟协程是新的技术,应该有更好的速度表现。

当需要 解耦、异步、削峰 时我们考虑消息队列并结合上述的技术进行优化。

![image-20230905153811141](/Users/geez/Library/Application Support/typora-user-images/image-20230905153811141.png)

备注

需要注意的是进程、线程、协程不是并列关系,他们是包含关系。进程包含线程包含协程。也就是说一个进程可以有多个线程一个线程可以有多个进程。

由于本身不是程序员,对代码理解有限,如果文中有错误的地方欢迎评论区指出。

CSP的原理和绕过

xss的编码那么复杂,一不小心就会过滤失败,同时不同的触发点还要逐个修复、即使可以统前端过滤,仍存在漏掉的风险。那么有没有一种办法可以禁止用户插入的js代码执行呢?是有的,这就是CSP!

CSP的实现和执行全部由浏览器完成,浏览器来根据你的规则,禁止引入外部的那些链接和插入的js代码的执行,那怎么告诉浏览器我要开启CSP策略呢?

使用方法

1、通过 HTTP 头信息的Content-Security-Policy

1
2
Content-Security-Policy: script-src 'self'; object-src 'none'; 
style-src cdn.example.org third-party.org; child-src https:
阅读全文 »

xss之浏览器的编码和解码

在做一些xss的过滤和绕过时,总是使用各种编码绕过,有时候是unicode,有时候是urlencode,有时候是HTML实体化编码,但是很多时候都是直接fuzz,对于存在xss的漏洞点,并没有清楚的分析和认识,对于浏览器的编码和解码没有系统的认识,这会导致我们的payload理解不到位,从而错失很多个src中的xss漏洞。为了以后能更好的挖掘xss漏洞和更快的fuzz出过waf手法。今天就来详细梳理下浏览器的编码和解码过程。

阅读全文 »

前言

再一次CTF比赛中遇到了三四层穿透的靶场,当时由于没有外网,而且也不知道什么网络原因导致穿透三层的时候一直没成功。这个假期正好有时间就找了一个靶场,看看多层的穿透到底应该怎么来比较方便。

靶场选取的是CFS三层靶场,网上一搜就有,这里不再提供下载链接了。

环境搭建

网络环境

这里是三层网络环境,设置了三个vmnet:

image-20221005202301343

阅读全文 »

网鼎杯比赛感想

水浅王八多,python真是多。 白虎组也太卷了,金融行业尤其卷,能做出来crypto和web我能理解,pwn、reverse都是强项,比web还强,那是平常不干业务吗?难以理解,而且现在比赛都不是pwn爹了,那是pwn爷爷,ak了web,还做了misc和crypto,最后只有三四百分,一道pwn题就是400多分,一道pwn就能进线下。现在web狗真是没啥活路。

吐槽归吐槽,但是还是技不如人。不过这次白虎组web基本都做出来了。先记录下WP吧!

阅读全文 »

Java动态代理

最近在看java的动态代理,做下笔记

什么是代理

代购:如果你想买的东西在国外,你一般不会飞过去买完再飞回来,而是有个中介,帮你处理这件事,这个中介就是代购,也就是代理。帮你办一件事就是代理。

客户 —– 代理(代购) ——国外商场

为什么找代购?

便宜省心专业,我不能自己去国外买。同时代购为了自己的优势,不让买家接触自己的进货渠道,你想要这个价格和服务就只能通过代购。所以很多时候只能通过代购来买东西。

阅读全文 »

前言

最近在好几次HW中发现现有的几个扫描shiro key的漏洞经常会爆出密钥,但是又无法利用,刚开始的时候以为是利用链的问题,后来发现有时候同样的站,跑不同的几次有时候能扫描出来密钥,有时候则不行。后来分析了这个工具发现密钥误报和利用链有关。

原理

在shiro反序列化漏洞刚出来的那段时间,网上的大部分工具都是通过URLDNS这条链条来验证的,这个验证有点是比较准确,缺点就是在很多不出网的内网机器中容易漏扫。后来牛逼的大佬发现了SimplePrincipalCollection这个类,

暂未写完,有空再来填坑