首页 文章 精选 留言 我的

精选列表

搜索[隐私保护工具],共10000篇文章
优秀的个人博客,低调大师

在Asp.Net Core中使用中间件保护非公开文件

在企业开发中,我们经常会遇到由用户上传文件的场景,比如某OA系统中,由用户填写某表单并上传身份证,由身份管理员审查,超级管理员可以查看。 就这样一个场景,用户上传的文件只能有三种人看得见(能够访问) 上传文件的人 身份审查人员 超级管理员 那么,这篇博客中我们将一起学习如何设计并实现一款文件授权中间件 问题分析 如何判断文件属于谁 要想文件能够被授权,文件的命名就要有规律,我们可以从文件命名中确定文件是属于谁的,例如本文例可以设计文件名为这样 工号-GUID-[Front/Back] 例如: 100211-4738B54D3609410CBC785BCD1963F3FA-Front,这代表由100211上传的身份证正面 判断文件属于哪个功能 一个企业系统中上传文件的功能可能有很多: 某个功能中上传身份证 某个功能中上传合同 某个功能上传发票 我们的区分方式是使用路径,例如本文例使用 /id-card /contract /invoices 不能通过StaticFile中间件访问 由StaticFile中间件处理的文件都是公开的,由这个中间件处理的文件只能是公开的js、css、image等等可以由任何人访问的文件 设计与实现 为什么使用中间件实现 对于我们的需求,我们还可以使用Controller/Action直接实现,这样比较简单,但是难以复用,想要在其它项目中使用只能复制代码。 使用独立的文件存储目录 在本文例中我们将所有的文件(无论来自哪个上传功能)都放在一个根目录下例如:C:xxx-uploads(windows),这个目录不由StaticFile中间件管控 中间件结构设计 这是一个典型的 Service-Handler模式,当请求到达文件授权中间件时,中间件让FileAuthorizationService根据请求特征确定该请求属于的Handler,并执行授权授权任务,获得授权结果,文件授权中间件根据授权结果来确定向客户端返回文件还是返回其它未授权结果。 请求特征设计 只有请求是特定格式时才会进入到文件授权中间件,例如我们将其设计为这样 host/中间件标记/handler标记/文件标记 那么对应的请求就可能是: https://localhost:8080/files/id-card/100211-4738B54D3609410CBC785BCD1963F3FA-Front.jpg 这里面 files是作用于中间件的标记,id-card用于确认由IdCardHandler处理,后面的内容用于确认上传者的身份 IFileAuthorizationService设计 public interface IFileAuthorizationService { string AuthorizationScheme { get; } string FileRootPath { get; } Task<FileAuthorizeResult> AuthorizeAsync(HttpContext context, string path); 这里的 AuthorizationScheme 对应,上文中的中间件标记,FileRootPath 代表文件根目录的绝对路径,AuthorizeAsync方法则用于切实的认证,并返回一个认证的结果 FileAuthorizeResult 设计 public class FileAuthorizeResult { public bool Succeeded { get; } public string RelativePath { get; } public string FileDownloadName { get; set; } public Exception Failure { get; } Succeeded 指示授权是否成功 RelativePath 文件的相对路径,请求中的文件可能会映射成完全不同的文件路径,这样更加安全例如将Uri /files/id-card/4738B54D3609410CBC785BCD1963F3FA.jpg映射到/xxx-file/abc/100211-4738B54D3609410CBC785BCD1963F3FA-Front.jpg,这样做可以混淆请求中的文件名,更加安全 FileDownloadName 文件下载的名称,例如上例中文件命中可能包含工号,而下载时可以仅仅是一个GUID Failure 授权是发生的错误,或者错误原因 IFileAuthorizeHandler 设计 public interface IFileAuthorizeHandler { Task<FileAuthorizeResult> AuthorizeAsync(HttpContext context,string path); 略... IFileAuthorizeHandler 只要求有一个方法,即授权的方法 IFileAuthorizationHandlerProvider 设计 public interface IFileAuthorizationHandlerProvider { Type GetHandlerType (string scheme); bool Exist(string scheme); 略... GetHandlerType 用于获取指定 AuthorizeHandler的实际类型,在AuthorizationService中会使用此方法 Exist方法用于确认是否含有指定的处理器 FileAuthorizationOptions 设计 public class FileAuthorizationOptions { private List<FileAuthorizationScheme> _schemes = new List<FileAuthorizationScheme>(20); public string FileRootPath { get; set; } public string AuthorizationScheme { get; set; } public IEnumerable<FileAuthorizationScheme> Schemes { get => _schemes; } public void AddHandler<THandler>(string name) where THandler : IFileAuthorizeHandler { _schemes.Add(new FileAuthorizationScheme(name, typeof(THandler))); } public Type GetHandlerType(string scheme) { return _schemes.Find(s => s.Name == scheme)?.HandlerType; 略... FileAuthorizationOptions的主要责任是确认相关选项,例如:FileRootPath和AuthorizationScheme。以及存储 handler标记与Handler类型的映射。 上一小节中IFileAuthorizationHandlerProvider 是用于提供Handler的,那么为什么要将存储放在Options里呢? 原因如下: Provider只负责提供,而存储可能不由它负责 未来存储可能更换,但是调用Provider的组件或代码并不关心 就现在的需求来说这样实现比较方便,且没有什么问题 FileAuthorizationScheme设计 public class FileAuthorizationScheme { public FileAuthorizationScheme(string name, Type handlerType) { if (string.IsNullOrEmpty(name)) { throw new ArgumentException("name must be a valid string.", nameof(name)); } Name = name; HandlerType = handlerType ?? throw new ArgumentNullException(nameof(handlerType)); } public string Name { get; } public Type HandlerType { get; } 略... 这个类的功能就是存储 handler标记与Handler类型的映射 FileAuthorizationService实现 第一部分是AuthorizationScheme和FileRootPath public class FileAuthorizationService : IFileAuthorizationService { public FileAuthorizationOptions Options { get; } public IFileAuthorizationHandlerProvider Provider { get; } public string AuthorizationScheme => Options.AuthorizationScheme; public string FileRootPath => Options.FileRootPath; 最重要的部分是 授权方法的实现: public async Task<FileAuthorizeResult> AuthorizeAsync(HttpContext context, string path) { var handlerScheme = GetHandlerScheme(path); if (handlerScheme == null || !Provider.Exist(handlerScheme)) { return FileAuthorizeResult.Fail(); } var handlerType = Provider.GetHandlerType(handlerScheme); if (!(context.RequestServices.GetService(handlerType) is IFileAuthorizeHandler handler)) { throw new Exception($"the required file authorization handler of '{handlerScheme}' is not found "); } // start with slash var requestFilePath = GetRequestFileUri(path, handlerScheme); return await handler.AuthorizeAsync(context, requestFilePath); } 授权过程总共分三步: 获取当前请求映射的handler 类型 向Di容器获取handler的实例 由handler进行授权 这里给出代码片段中用到的两个私有方法: private string GetHandlerScheme(string path) { var arr = path.Split('/'); if (arr.Length < 2) { return null; } // arr[0] is the Options.AuthorizationScheme return arr[1]; } private string GetRequestFileUri(string path, string scheme) { return path.Remove(0, Options.AuthorizationScheme.Length + scheme.Length + 1); } FileAuthorization中间件设计与实现 由于授权逻辑已经提取到 IFileAuthorizationService和IFileAuthorizationHandler中,所以中间件所负责的功能就很少,主要是接受请求和向客户端写入文件。 理解接下来的内容需要中间件知识,如果你并不熟悉中间件那么请先学习中间件 你可以参看ASP.NET Core 中间件文档进行学习 接下来我们先贴出完整的Invoke方法,再逐步解析: public async Task Invoke(HttpContext context) { // trim the start slash var path = context.Request.Path.Value.TrimStart('/'); if (!BelongToMe(path)) { await _next.Invoke(context); return; } var result = await _service.AuthorizeAsync(context, path); if (!result.Succeeded) { _logger.LogInformation($"request file is forbidden. request path is: {path}"); Forbidden(context); return; } if (string.IsNullOrWhiteSpace(_service.FileRootPath)) { throw new Exception("file root path is not spicificated"); } string fullName; if (Path.IsPathRooted(result.RelativePath)) { fullName = result.RelativePath; } else { fullName = Path.Combine(_service.FileRootPath, result.RelativePath); } var fileInfo = new FileInfo(fullName); if (!fileInfo.Exists) { NotFound(context); return; } _logger.LogInformation($"{context.User.Identity.Name} request file :{fileInfo.FullName} has beeb authorized. File sending"); SetResponseHeaders(context, result, fileInfo); await WriteFileAsync(context, result, fileInfo); } 第一步是获取请求的Url并且判断这个请求是否属于当前的文件授权中间件 var path = context.Request.Path.Value.TrimStart('/'); if (!BelongToMe(path)) { await _next.Invoke(context); return; } 判断的方式是检查Url中的第一段是不是等于AuthorizationScheme(例如:files) private bool BelongToMe(string path) { return path.StartsWith(_service.AuthorizationScheme, true, CultureInfo.CurrentCulture); } 第二步是调用IFileAuthorizationService进行授权 var result = await _service.AuthorizeAsync(context, path); 第三步是对结果进行处理,如果失败了就阻止文件的下载: if (!result.Succeeded) { _logger.LogInformation($"request file is forbidden. request path is: {path}"); Forbidden(context); return; } 阻止的方式是返回 403,未授权的HttpCode private void Forbidden(HttpContext context) { HttpCode(context, 403); } private void HttpCode(HttpContext context, int code) { context.Response.StatusCode = code; } 如果成功则,向响应中写入文件:写入文件相对前面的逻辑稍稍复杂一点,但其实也很简单,我们一起来看一下 第一步,确认文件的完整路径: string fullName; if (Path.IsPathRooted(result.RelativePath)) { fullName = result.RelativePath; } else { fullName = Path.Combine(_service.FileRootPath, result.RelativePath); } 前文提到,我们设计的是将文件全部存储到一个目录下,但事实上我们不这样做也可以,只要负责授权的handler将请求映射成完整的物理路径就行,这样,在未来就有更多的扩展性,比如某功能的文件没有存储在统一的目录下,那么也可以。 这一步就是判断和确认最终的文件路径 第二步,检查文件是否存在: var fileInfo = new FileInfo(fullName); if (!fileInfo.Exists) { NotFound(context); return; } private void NotFound(HttpContext context) { HttpCode(context, 404); } 最后一步写入文件: await WriteFileAsync(context, result, fileInfo); 完整方法如下: private async Task WriteFileAsync(HttpContext context, FileAuthorizeResult result, FileInfo fileInfo) { var response = context.Response; var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>(); if (sendFile != null) { await sendFile.SendFileAsync(fileInfo.FullName, 0L, null, default(CancellationToken)); return; } using (var fileStream = new FileStream( fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, BufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan)) { try { await StreamCopyOperation.CopyToAsync(fileStream, context.Response.Body, count: null, bufferSize: BufferSize, cancel: context.RequestAborted); } catch (OperationCanceledException) { // Don't throw this exception, it's most likely caused by the client disconnecting. // However, if it was cancelled for any other reason we need to prevent empty responses. context.Abort(); 首先我们是先请求了IHttpSendFileFeature,如果有的话直接使用它来发送文件 var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>(); if (sendFile != null) { await sendFile.SendFileAsync(fileInfo.FullName, 0L, null, default(CancellationToken)); return; } 这是Asp.Net Core中的另一重要功能,如果你不了解它你可以不用太在意,因为此处影响不大,不过如果你想学习它,那么你可以参考ASP.NET Core 中的请求功能文档 如果,不支持IHttpSendFileFeature 那么就使用原始的方法将文件写入请求体: using (var fileStream = new FileStream( fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, BufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan)) { try { await StreamCopyOperation.CopyToAsync(fileStream, context.Response.Body, count: null, bufferSize: BufferSize, cancel: context.RequestAborted); } catch (OperationCanceledException) { // Don't throw this exception, it's most likely caused by the client disconnecting. // However, if it was cancelled for any other reason we need to prevent empty responses. context.Abort(); 到此处,我们的中间件就完成了。 中间件的扩展方法 虽然我们的中间件和授权服务都写完了,但是似乎还不能直接用,所以接下来我们来编写相关的扩展方法,让其切实的运行起来 最终的使用效果类似这样: // 在di配置中 services.AddFileAuthorization(options => { options.AuthorizationScheme = "file"; options.FileRootPath = CreateFileRootPath(); }) .AddHandler<TestHandler>("id-card"); // 在管道配置中 app.UseFileAuthorization(); 要达到上述效果要编写三个类: FileAuthorizationBuilder FileAuthorizationAppBuilderExtentions FileAuthorizationServiceCollectionExtensions 地二个用于实现app.UseFileAuthorization(); 第三个用于实现services.AddFileAuthorization(options =>... 第一个用于实现.AddHandler<TestHandler>("id-card"); FileAuthorizationBuilder public class FileAuthorizationBuilder { public FileAuthorizationBuilder(IServiceCollection services) { Services = services; } public IServiceCollection Services { get; } public FileAuthorizationBuilder AddHandler<THandler>(string name) where THandler : class, IFileAuthorizeHandler { Services.Configure<FileAuthorizationOptions>(options => { options.AddHandler<THandler>(name ); }); Services.AddTransient<THandler>(); return this; 这部分主要作用是实现添加handler的方法,添加的handler是瞬时的 FileAuthorizationAppBuilderExtentions public static class FileAuthorizationAppBuilderExtentions { public static IApplicationBuilder UseFileAuthorization(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware<FileAuthenticationMiddleware>(); 这个主要作用是将中间件放入管道,很简单 FileAuthorizationServiceCollectionExtensions public static class FileAuthorizationServiceCollectionExtensions { public static FileAuthorizationBuilder AddFileAuthorization(this IServiceCollection services) { return AddFileAuthorization(services, null); } public static FileAuthorizationBuilder AddFileAuthorization(this IServiceCollection services, Action<FileAuthorizationOptions> setup) { services.AddSingleton<IFileAuthorizationService, FileAuthorizationService>(); services.AddSingleton<IFileAuthorizationHandlerProvider, FileAuthorizationHandlerProvider>(); if (setup != null) { services.Configure(setup); } return new FileAuthorizationBuilder(services); 这部分是注册服务,将IFileAuthorizationService和IFileAuthorizationService注册为单例 到这里,所有的代码就完成了 测试 我们来编写个简单的测试来测试中间件的运行效果 要先写一个测试用的Handler,这个Handler允许任何用户访问文件: public class TestHandler : IFileAuthorizeHandler { public const string TestHandlerScheme = "id-card"; public Task<FileAuthorizeResult> AuthorizeAsync(HttpContext context, string path) { return Task.FromResult(FileAuthorizeResult.Success(GetRelativeFilePath(path), GetDownloadFileName(path))); } public string GetRelativeFilePath(string path) { path = path.TrimStart('/', '\\').Replace('/', '\\'); return $"{TestHandlerScheme}\\{path}"; } public string GetDownloadFileName(string path) { return path.Substring(path.LastIndexOf('/') + 1); } } 测试方法: public async Task InvokeTest() { var builder = new WebHostBuilder() .Configure(app => { app.UseFileAuthorization(); }) .ConfigureServices(services => { services.AddFileAuthorization(options => { options.AuthorizationScheme = "file"; options.FileRootPath = CreateFileRootPath(); }) .AddHandler<TestHandler>("id-card"); }); var server = new TestServer(builder); var response = await server.CreateClient().GetAsync("http://example.com/file/id-card/front.jpg"); Assert.Equal(200, (int)response.StatusCode); Assert.Equal("image/jpeg", response.Content.Headers.ContentType.MediaType); } 这个测试如期通过,本例中还写了其它诸多测试,就不一一贴出了,另外,这个项目目前已上传到我的github上了,需要代码的同学自取 https://github.com/rocketRobin/FileAuthorization 你也可以直接使用Nuget获取这个中间件: Install-Package FileAuthorizationInstall-Package FileAuthorization.Abstractions 如果这篇文章对你有用,那就给我点个赞吧:D 欢迎转载,转载请注明原作者和出处,谢谢 最后最后,在企业开发中我们还要检测用户上传文件的真实性,如果通过文件扩展名确认,显然不靠谱,所以我们得用其它方法,如果你也有相关的问题,可以参考我的另外一篇博客在.NetCore中使用Myrmec检测文件真实格式

优秀的个人博客,低调大师

安全有疆 民用防盗报警撑起家庭安防“保护伞”

随着数字化发展的不断深入,物联网的发展以及通信巨头的介入,极大的推快了探测器无线化发展的前进步伐。报警运营行业这两年也展现出猛烈增长势头,整个联网报警产业链基本处于良性的发展状态,业内人士分析认为,单就开放住宅小区这一政策来说,给联网报警整个产业链带来的发展空间都是不容小觑的。 防盗报警探测技术的融合和创新 防盗报警探测器的性能,是防盗报警系统、乃至整个安防系统运行的关键,虽然目前有众多的技术手段去完善,但受到各技术本身的缺陷、工艺和使用环境等影响,漏报、误报、干扰等仍为用户最为伤心头疼的问题,这需要行业研发制造企业不断地去积累、融合和创新。如被动红外,怎样将人的体温特点、电磁反射特征和生物体、小生物体或非生物体特征进行甄别,以及如何对甄别出来的人或者动物行为进行分析,对此做出准确的判断和预警。目前智能视频复合、生物感应等技术的出现,为防盗报警漏/误报警的缺陷提供了最新的技术解决方案,随物联网、互联网、智能家居的不断普及,防盗报警的应用,将迎来新的发展契机。 防盗报警系统的应用融合 在互联网、智能家居的冲击下,防盗报警不仅仅作为单一的产品功能在应用,在加强家庭、社会安全的同时,将更多地与门禁、对讲、监控、智能家居等行业融合在一起,逐渐脱离传统的单机单功能模式,或成为综合性的智能产品,或成为门禁对讲、智能家居等产品的一项功能。防盗报警器也将重新定义,如添加家电控制模块、生物识别模块、网络模块、视频模块等,融家庭安全、语音通讯、家庭自动化、居住环境监测等多种功能为一体,成为一个新的智能终端入口。如报警主机添加家电控制模块,成为智能家居的控制器,用户通过手机APP、遥控或者电话,可远程控制家中电器、灯光照明、门铃窗帘等;语音识别模块,报警主机整合语音识别等技术,用户通过语音控制一切智能设备,打造极致的用户体验。 防盗报警系统,可以通过单品或套装,实现产品本身的报警功能,如保障财产安全,防盗;保障人身安全,老人求助,防火防泄露防中毒等,并对接接警中心110、120、119;同时可以改善人们的生活质量,如PM2.5检测,家电智能控制,语音对讲,生物识别等,还可以进行平台化运作,提供更多的增值服务。如通过平台,报警器用户的手机APP,不仅可以及时收到报警信息,还可以收到物业通知,能预约挂号、电影订座、网上购物等,打造智能社区,为人们生活提供贴身的便捷服务,成为真正的智能安全生活管家。 民用防盗报警器的应用现状 目前,防盗报警主要在政府部门、金融、文博等领域应用比较深入,而与民众生活息息相关的领域尚处在蓄势待发阶段,如家庭防盗报警、店铺防盗报警、工厂企业防盗报警等,并没有得到好的普及,其主要原因在于民用报警器产品技术未能获得新突破,准确率未得到有效提升,用户使用的便捷性未有极好的改善,从而导致国内防盗报警器产品在功能上、使用上、外观上同质化严重,在中低端市场,因探测精度的不足和应用上的不足,易用性与智能化不够,误报率高散失了用户信心,而在高端应用市场上,基本被国外品牌所垄断,同时智能家居、视频监控、楼宇对讲等产品,以及创客产品,融入了报警功能,使得防盗报警器产品的发展空间越来越小,使其必须在应用上创新,模式上创新,才能在安防领域占有一席之地。 乘借政策的东风,如建设部对智能化住宅小区的六项要求,住宅小区设立计算机自动化管理中心,水、电、气等自动计量、收费;住宅小区封闭,实行安全防范系统自动化监控管理;住宅的火灾,有害气体泄漏实行自动报警;住宅设置楼宇对讲和紧急呼叫系统;对住宅小区关键设备,设施实行集中管理,对其运作状态实施远程监控。安防防范和报警等都纳入小区建设的必备项目。在深圳,禁止安装防盗网,在上海、广州、温州、南昌等地,更是花费重金拆除了防盗网,规定其防盗功能必须由电子防盗系统来完成,这为防盗报警行业的发展带来了新机遇。 而同时,互联网的到来,使得各行各业发生了翻天覆地的变化,一些互联网企业跨界开始进入民用报警市场,从产品的工业设计和用户体验上下足功夫,促使传统防盗报警企业在“风口”上进行颠覆式创新,与物联网产业链的企业互联互通,简化操作、强化用户体验。目前的防盗报警产品,基本可实现一部手机知晓和控制家中所有,报警主机,不仅可对接红外探测器、门磁、烟雾探测器、燃气探测器等,以及接警中心,并融合高清视频监控,实现提前预测并实时查看,并可以联动控制家电,让普通家电智能化,PM2.5检测,改善家居环境等。 民用防盗报警的市场突破 在城市里,一些犯罪分子频频把魔爪伸向居民住宅、单位和商铺,进行入屋盗窃和抢劫,在一些高端社区,虽然有门禁系统、监控系统、周界防范、保安值守,但被盗案件依然时有发生。媒体曾报道,南京某小区同一天上午连续发生2起入室盗窃案件,居民家中被盗现金、珠宝等财物近20余万元,通过监控,查看到嫌疑人在短短40分钟的时间内,就完成进出小区、寻找目标、并打开两家的防盗门这一系列繁琐的动作。调查中发现防盗门对于小偷而言,掌握了技术性开锁后,开锁仅需几秒,如同使用自家的钥匙开锁一样,民用防盗报警的使用迫在眉睫。 在现实中,我们看到很多商铺、小区楼盘、工厂企业,防盗报警系统使用率并不高,而实际上,人们对于安全的需求是迫切的。防盗报警如何打开民用市场,这需要产品本身足够贴合实际,作用让人信服,需要运作服务模式上有新突破,根据用户的类型特点、生活方式,打造不同的解决方案,以满足民用家庭、店铺的需求。 如与社区、物业合作,一方面可以共同开展宣传活动,举办安全讲座,进行产品的深一步体验等,另一方面可以在设计安装、售后维保服务的同时,对物业监控人员、保安人员进行专业培训,提升其使用维护的技能,让报警服务切实保障人们的生命财产安全,真正的飞入百姓家。同时,还可以与社区O2O服务运营商进行合作,如通过社区O2OAPP,业主可以方便在线联系物业管理处,及时接受物业通知、查询物业水电费,智能开门,在线报修等;物业人员可与业主在线沟通,发布物业通知,及时响应业主的报修,设施预警;还提供高效的访客通行验证,智能门禁配置管理。目前,各种类型企业都加入到了分食社区O2O这块“大蛋糕”的行列,万科、中海、保利等将物业管理当作重点发展的新板块,彩生活、实惠等模式创新,也备受市场青睐。 防盗报警器通过一套打通线上线下的平台化系统,让每一位居民的生活联通起来,智慧起来,即让用户使用后,便有离不开的感觉,除将安全关联外,还将家庭电器、生活环境相关联,将日常生活需求相关联,通过具有综合的服务平台,整合资源,为用户提供综合的服务支持,构建新的防盗报警服务应用模式,出现民用监控一样的免费模式,这也许是未来防盗报警行业的新思路。 民用防盗报警产品,需冲破已有界限,在联动应用性上,打造出难以复制的核心功能,让人们生活更安全、更便捷、更智能,打动用户。 本文转自d1net(转载)

优秀的个人博客,低调大师

苹果iOS 10系统“激活锁”绕过漏洞,丢失保护功能形同虚设?

本着求真和好奇的心态,此次宅客频道将带领读者们讲述此次事件的来龙去脉、破解流程以及相关细节,试图将完整的故事呈现给读者们,让读者了解到: 漏洞是什么,可导致何种后果? 这个漏洞最早是如何被发现的? 复现漏洞的具体步骤是怎样的? 我们是否会受影响,该怎么做? 该漏洞有何后果? 从iOS 7开始,苹果设备就具有一项“激活锁”功能, 当用户的设备不慎被偷,只要激活"丢失模式”(Lost mode),盗窃者在没有得到合法机主许可就无法激活设备到正常工作状态,这使得丢失的苹果设备很难被直接转卖,不仅提高安全性还降低了失窃率。 这也是许多人在丢失苹果设备后都收到钓鱼短信及邮件的原因——盗窃者试图骗取APPID账号密码来解锁设备。 然而,此漏洞的出现,意味着任何人都可以绕过“激活锁”直接重置该设备,让丢失模式形同虚设!盗窃者可以利用该漏洞将一些非法获得的设备直接解锁后重新售卖或自行使用。简而言之,当你的设备丢失,你更难将它找回了。 那么这个漏洞是如何被发现的呢? 据外媒报道,该漏洞最早是由印度安全专家赫门特·约瑟夫(Hemant Joseph)发现的,于是宅客频道(公众号:宅客频道)通过博客了解到破解的全部操作流程。 iOS 10.1漏洞发现,源于被坑的购物经历 赫门特给朋友网购了一个iPad,哪知设备刚到手,却发现被开启了“丢失模式”,发现连接WiFi之后,设备会要求输入之前机主的APPID账号密码。赫门特这才知道,自己花了许多时间挑选iPad,最后却买回来一块“砖头”——他觉得自己被彻头彻尾地耍了,简直不能忍! “自己动手,丰衣足食”,作为安全专家的赫门特决定发挥自己的聪明才智对iPad进行破解,他立刻想到了让设备缓冲区溢出的方法。 以下为赫门特个人博客中对破解过程的描述: 我在WiFi网络选项中,选择“连接另一个网络”。 跳转到一个要求输入用户名的登录框。 以上只有一个输入字段,如果有字符限制的话,比较难引发内存缓冲区溢出。但如果点击“安全选项”,选择安全协议WEP,就有另一个WPA WPA2企业版的选项出现。 我选择WP2企业版,这时会出现三个输入框:名称、用户名和密码,然后我很惊奇地发现,这里居然没有限制字符长度,可以肆无忌惮地输入,真是太适合用来造成内存缓冲区溢出的情况了! 一直复制粘贴输入字符,直到设备卡住。 我等了一会儿,看看是恢复正常还是软件崩溃,结果既没有崩溃也没有恢复,一直卡着。又等了一会,我按下了解锁按钮,结果它把我带回到一开始的欢迎屏幕了 :( WTF ?(心中一万头羊驼奔过) 第一次尝试破解失败后,赫门特没有放弃,开始第二次尝试: 思考了一会如何诱发程序崩溃让它跳到主屏幕上,我想到了利用iPad外壳(iPad smart Case)的自动唤醒功能来试试,因为可以利用它的这个特性:当我们用盖上外壳盖来关闭屏幕,再打开外壳盖,它会重现之前关闭之前的屏幕,继续刚才的工作请求。 于是我重复了刚才的操作,在最后一步iPad卡死的时候,盖上外壳盖子,然后过一会儿再打开。 过了大概20~25秒,iPad出现了软件崩溃,然后把我带到了主屏幕,从而绕过了所谓的“激活锁”,成功! 由此可以看出,这里出现的漏洞的主要原因在于:连接WiFi时的输入框限制输入字符的长度,而在实际使用当中,没有人会使用一个超过1000个字符来当账号或密码。 看到这里,可能有些读者已经想找一台iPad来亲身体验一把了,不过你们可能不会成功,因为发现该漏洞的印度专家赫门非常耿直,发现漏洞后立马写邮件告诉了苹果官方,并很快得到了苹果官方的回复。 苹果很快推出了iOS 10.1.1 的版本更新,修复了该漏洞,因此该漏洞只可能在iOS 10.1 或者更早的版本中复现。 然而,“绕过风波”并没有就此结束。 研究员不依不挠,新版本仍能被破解 Vulnerability Lab实验室的研究人员也对此问题进行分析后,发现利用屏幕旋转和Night Shift(自动调整屏幕色温)功能可在iOS 10.1.1系统中重现这个漏洞。 他们提供了一段成功破解的视频: 宅客频道发现,在视频演示中,主要区别于破解iOS 10.1绕过漏洞的地方主要在于: 输入的字符使用了emoji表情等特殊字符 在最后一个中反复使用了智能外壳和屏幕旋转功能 需要很精准地把握好关键操作的时间点:在某个瞬间设备会出现不到一秒的主屏幕,这时需要适时按下Home键才可以完全绕过激活锁,这一时机很难把握。 宅客频道编辑找来了一个装载iOS 10.1.1系统的iPad mini 2 , 尝试复现该漏洞,但不知是由于没有把握好时机,尝试多次后并没有成功解锁设备。然而在国外社交媒体上有网友表示自己按照视频演示,成功破解了iPad mini 2(同样尝试了好几次)。 目前,宅客频道还没有发现任何成功利用此方式破解iPhone设备的案例。在国外一名研究员安德鲁·坎宁安的报道中,他也发现了相同的情况: 根据这个视频,我们能够在运行iOS 10.1.1的iPad Mini 2上重现该问题,然而在我们的测试中,我们无法在运行iOS 10.1.1 的iPhone 5设备中重现这个bug,在实验中,iPhone没有向iPad那样旋转为横屏模式,也没办法用智能外壳来控制屏幕的开关。 由此看来,该漏洞在iPad上也需要一定的技巧才能复现,而在iPhone上几乎无法实现,因此人们其实并不必为这个漏洞太过担心,并且相信苹果公司也将会在接下来推出的iOS 10.2的版本更新中修复该问题。 我们该怎么做? 针对此问题,国外相关安全机构给出了一些建议: 当苹果为这个错误提供了一个补丁后,尽快安装它。 日常苹果设备丢失,对方可能不会去恶意破解,但尽可能为之设置一个安全的PIN码或锁屏密码,以确保安全。 不过对于此次“激活锁”绕过漏洞,宅客频道有个更直接有效的终极建议:看好你的机器设备,别把它弄丢了。 --------------------------- 查看 --------------------------- 文件 "lantern.exe" 已修改。 您希望在压缩文件里更新它吗? --------------------------- 是(Y) 否(N) 取消 --------------------------- 本文转自d1net(转载)

优秀的个人博客,低调大师

本地部署 vs 云端 AI 视频生成平台对比:隐私安全与效率如何平衡

当前 AI 视频创作存在两条主流技术路径:开源模型本地部署、商用云端 SaaS 工作台。两类方案在数据主权、算力弹性、运维成本、上手门槛存在天然分歧。行业实测数据显示:个人创作者单日产出低于 15 条短视频,云端综合投入更低;企业团队日均批量产出 50 条以上、素材涉及未公开商业方案,本地部署的长期价值逐步显现。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册