-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
380 lines (232 loc) · 34.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>rebirthwyw</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="Hack For Fun">
<meta property="og:type" content="website">
<meta property="og:title" content="rebirthwyw">
<meta property="og:url" content="https://blog.rebirthwyw.top/index.html">
<meta property="og:site_name" content="rebirthwyw">
<meta property="og:description" content="Hack For Fun">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="rebirthwyw">
<meta property="article:tag" content="cyber security">
<meta name="twitter:card" content="summary">
<link rel="alternate" href="/atom.xml" title="rebirthwyw" type="application/atom+xml">
<link rel="shortcut icon" href="/favicon.png">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/index.min.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">
<meta name="generator" content="Hexo 5.4.0"></head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">rebirthwyw</a>
</h1>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
<a class="main-nav-link" href="/about">About</a>
<a class="main-nav-link" href="/links">Links</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="https://blog.rebirthwyw.top"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-analysis-of-CVE-2021-22205-pre-auth-part" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<div class="article-meta">
<a href="/2021/11/01/analysis-of-CVE-2021-22205-pre-auth-part/" class="article-date">
<time class="dt-published" datetime="2021-11-01T10:56:35.000Z" itemprop="datePublished">2021-11-01</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="p-name article-title" href="/2021/11/01/analysis-of-CVE-2021-22205-pre-auth-part/">analysis of CVE-2021-22205 pre-auth part</a>
</h1>
</header>
<div class="e-content article-entry" itemprop="articleBody">
<p>CVE-2021-22205在发现之后被拓展为了pre-auth的rce,因此在这里分析一下pre-auth的成因。</p>
<h1 id="rce"><a href="#rce" class="headerlink" title="rce"></a>rce</h1><p>rce的部分比较直观,是gitlab在处理上传的图片时采用exiftool对图片进行了处理,然后exiftool本身在处理DjVu格式的文件时存在命令注入导致的。具体的分析文章可以参考漏洞发现者的博文 <a target="_blank" rel="noopener" href="https://devcraft.io/2021/05/04/exiftool-arbitrary-code-execution-cve-2021-22204.html">https://devcraft.io/2021/05/04/exiftool-arbitrary-code-execution-cve-2021-22204.html</a></p>
<h1 id="pre-auth"><a href="#pre-auth" class="headerlink" title="pre-auth"></a>pre-auth</h1><h2 id="gitlab整体结构"><a href="#gitlab整体结构" class="headerlink" title="gitlab整体结构"></a>gitlab整体结构</h2><p>主要分析一下pre-auth部分的原因,算是走一遍gitlab的整体流程(正好是第一次分析ruby的应用)。</p>
<p>gitlab的基本结构如下</p>
<p>nginx => workhorse => puma</p>
<p>nginx部分不赘述,workhorse是一个golang写的反向代理,同时承担了部分应用逻辑。比如文件上传的部分就由workhorse在处理,exiftool也是在workhorse中调用的。</p>
<p>puma是真正的ruby后端,用来作为rails应用的服务器。</p>
<h2 id="workhorse"><a href="#workhorse" class="headerlink" title="workhorse"></a>workhorse</h2><p>workhorse默认采用unix socket domain交互,路由的基本情况位于 <code>/internal/upstream/routes.go</code>中。</p>
<p>因为gitlab在处理文件上传时做了很多策略(<a target="_blank" rel="noopener" href="https://docs.gitlab.com/ee/development/uploads.html">https://docs.gitlab.com/ee/development/uploads.html</a>),并由workhorse承担了很大一部分,所以可以看到 routes.go 中存在大量对于 upload 对象的调用。</p>
<p>以网上公开的poc中提到的 /uploads/user 路由为例,对应的路由策略是</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">u.route("POST", userUploadPattern, upload.Accelerate(api, signingProxy, preparers.uploads))</span><br></pre></td></tr></table></figure>
<p>关注到 Accelerate 函数的内容</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">func Accelerate(rails PreAuthorizer, h http.Handler, p Preparer) http.Handler {</span><br><span class="line"> return rails.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) {</span><br><span class="line"> s := &SavedFileTracker{Request: r}</span><br><span class="line"></span><br><span class="line"> opts, _, err := p.Prepare(a)</span><br><span class="line"> if err != nil {</span><br><span class="line"> helper.Fail500(w, r, fmt.Errorf("Accelerate: error preparing file storage options"))</span><br><span class="line"> return</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> HandleFileUploads(w, r, h, a, s, opts)</span><br><span class="line"> }, "/authorize")</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>发现会调用 rails.PreAuthorizeHandler 进行处理,传入的这个函数其实算是一个回调函数。</p>
<p>PreAuthorizeHandler 的实现位于 <code>/internal/api/api.go</code> ,简单来说就是调用 <code>api.PreAuthorize</code> 来做前置的权限校验(这个校验将与puma端交互),如果校验通过则处理回调部分的内容。</p>
<p><code>api.PreAuthorize</code>的校验在我们分析的这个路由下就是 将原本传递来的请求加上 /authorize 这个后缀,增加一个 Gitlab-Workhorse-Api-Request 的校验头附带一个 jwt token 作为确定请求来自workhorse的校验,然后转发给 puma 后端进行判断。形如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">POST /uploads/user/authorize HTTP/1.1</span><br><span class="line">Host: 127.0.0.1:8080</span><br><span class="line">X-Csrf-Token: konbkeNhzTLlNln7vFG99pGRiiatRtRFvBPlt1C9L47J1wrqIgxLjbiVZ/F1Ji2l96i3HlDOcU1mP9qz/iFanQ==</span><br><span class="line">Cookie: _gitlab_session=4af6cb1c584f51ff7de60cc7bcbd8db9</span><br><span class="line">Gitlab-Workhorse-Api-Request: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRsYWItd29ya2hvcnNlIn0.IiKf6b4dqC99J7Jozf0e91rGjILPtUcwSJ3rcCUNSnU</span><br></pre></td></tr></table></figure>
<p>如果这个请求返回正确,则 workhorse 会继续调用 Accelerate 中的回调函数,继而调用 HandleFileUploads => rewriteFormFilesFromMultipart => handleExifUpload => exif.NewCleaner => startProcessing => exiftool这个最终的程序触发漏洞。</p>
<h2 id="puma"><a href="#puma" class="headerlink" title="puma"></a>puma</h2><p>最后也是最麻烦的是puma这部分的分析。之所以麻烦,是因为最开始是在gitlab官方的docker中复现的,但是因为环境耦合度很多,想要单独调试puma部分的ruby应用比较麻烦,因此后面按照gitlab官方的安装教程在虚拟机中搭建了一遍后才有了比较舒服的调试环境。</p>
<p>作为rails的应用,首先是去 <code>config/routes/uploads.rb</code>下确认路由的情况。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">post ':model/authorize',</span><br><span class="line"> to: 'uploads#authorize',</span><br><span class="line"> constraints: { model: /personal_snippet|user/ }</span><br></pre></td></tr></table></figure>
<p>可以发现是调用了 uploads 这个 controller 中的 authorize 函数。</p>
<p>而在 <code>app/controllers/uploads_controller.rb</code>中存在两个 before_action 函数需要先过检查。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">before_action :authorize_create_access!, only: [:create, :authorize]</span><br><span class="line">before_action :verify_workhorse_api!, only: [:authorize]</span><br></pre></td></tr></table></figure>
<p>其中 <code>verify_workhorse_api!</code> 主要是检查 jwt 的部分,也就是保证这个请求时从 workhorse 端转发过来的。</p>
<p>主要分析的是 <code>authorize_create_access!</code>这个函数。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">def authorize_create_access!</span><br><span class="line"> return unless model</span><br><span class="line"></span><br><span class="line"> authorized =</span><br><span class="line"> case model</span><br><span class="line"> when User</span><br><span class="line"> can?(current_user, :update_user, model)</span><br><span class="line"> else</span><br><span class="line"> can?(current_user, :create_note, model)</span><br><span class="line"> end</span><br><span class="line"></span><br><span class="line"> render_unauthorized unless authorized</span><br><span class="line">end</span><br></pre></td></tr></table></figure>
<p>这也是作为第一次分析ruby的我最蛋疼的一个地方,那就是ruby里面的函数和变量在审计的时候很容易混淆。出问题的代码其实就是第一句,<code>return unless model</code>。这里的model是一个函数,在<code>app/controllers/concerns/uploads_actions.rb</code>中实现。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">def model</span><br><span class="line"> strong_memoize(:model) { find_model }</span><br><span class="line">end</span><br></pre></td></tr></table></figure>
<p>strong_memoize在<code>lib/gitlab/utils/strong_memoize.rb</code>中实现。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">def strong_memoize(name)</span><br><span class="line"> if strong_memoized?(name)</span><br><span class="line"> instance_variable_get(ivar(name))</span><br><span class="line"> else</span><br><span class="line"> instance_variable_set(ivar(name), yield)</span><br><span class="line"> end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">def strong_memoized?(name)</span><br><span class="line"> instance_variable_defined?(ivar(name))</span><br><span class="line">end</span><br></pre></td></tr></table></figure>
<p>到这里就很清晰了,因为 @model 这个变量在 <code>authorize_create_access</code>调用时还不存在,所以会走到 <code>instance_variable_set</code> 分支。触发 yield 关键字调用到上面的 find_model 函数。</p>
<p>find_model在 uploads_controller.rb 中定义,因为没有传入 id 参数,所以会直接return一个nil。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">def find_model</span><br><span class="line"> return unless params[:id]</span><br><span class="line"></span><br><span class="line"> upload_model_class.find(params[:id])</span><br><span class="line">end</span><br></pre></td></tr></table></figure>
<p>因此其实在 <code>authorize_create_access!</code> 函数中,直接在第一句语句处就会 return。</p>
<p>最后的 authorize 函数反而不需要分析,没有再做什么权限校验,因此达到了 pre-auth 的效果。</p>
<h2 id="漏洞修复"><a href="#漏洞修复" class="headerlink" title="漏洞修复"></a>漏洞修复</h2><p>分析这句导致漏洞的 <code>return unless model</code> ,其实会发现非常的多余,因为后面在调用 <code>case model</code>的model时,其实是去调用了strong_memoize,而在 strong_memoize 的定义的说明里就指出了 strong_memoize 的作用就是为了可以不需要采用 return unless 这种写法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"># Instead of writing patterns like this:</span><br><span class="line">#</span><br><span class="line"># def trigger_from_token</span><br><span class="line"># return @trigger if defined?(@trigger)</span><br><span class="line">#</span><br><span class="line"># @trigger = Ci::Trigger.find_by_token(params[:token].to_s)</span><br><span class="line"># end</span><br><span class="line">#</span><br><span class="line"># We could write it like:</span><br><span class="line">#</span><br><span class="line"># include Gitlab::Utils::StrongMemoize</span><br><span class="line">#</span><br><span class="line"># def trigger_from_token</span><br><span class="line"># strong_memoize(:trigger) do</span><br><span class="line"># Ci::Trigger.find_by_token(params[:token].to_s)</span><br><span class="line"># end</span><br><span class="line"># end</span><br><span class="line">#</span><br></pre></td></tr></table></figure>
<p>因此,在最新版本的 gitlab 中也可以发现,<code>authorize_create_access!</code>已经删除了这句 <code>return unless model</code>。</p>
<p>对于 exiftool 的修复,gitlab采用了检查上传的图片文件和后缀的对应关系的方式,限制了 exiftool 忽略文件后缀通过文件内容来针对格式进行处理的利用手段。具体commit如下 <a target="_blank" rel="noopener" href="https://gitlab.com/gitlab-org/gitlab/-/commit/6f8d9618e1e313625f3ee8c84b761fc8ff6c53df">https://gitlab.com/gitlab-org/gitlab/-/commit/6f8d9618e1e313625f3ee8c84b761fc8ff6c53df</a></p>
<h2 id="UPDATE"><a href="#UPDATE" class="headerlink" title="UPDATE"></a>UPDATE</h2><p>今天<code>@air sky</code>发邮件问了我 <a target="_blank" rel="noopener" href="https://attackerkb.com/topics/D41jRUXCiJ/cve-2021-22205/rapid7-analysis?referrer=blog">https://attackerkb.com/topics/D41jRUXCiJ/cve-2021-22205/rapid7-analysis?referrer=blog</a> 这篇文章的路由是怎么触发的,我才发现原来这个洞的preauth这么彻底,非常骚。<br>poc的形式就是直接往根url发送一个post请求,形如以下</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">POST / HTTP/1.1</span><br><span class="line">Host: 192.168.126.132</span><br><span class="line">Accept: */*</span><br><span class="line">Accept-Language: en</span><br><span class="line">User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36</span><br><span class="line">Connection: close</span><br><span class="line">Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryr1WeeKiaKhzQzGa7</span><br><span class="line">Content-Length: 857</span><br><span class="line"></span><br><span class="line">------WebKitFormBoundaryr1WeeKiaKhzQzGa7</span><br><span class="line">Content-Disposition: form-data; name="file"; filename="1.jpg"</span><br><span class="line">Content-Type: image/jpg</span><br><span class="line"></span><br><span class="line">xxxxx</span><br><span class="line">------WebKitFormBoundaryr1WeeKiaKhzQzGa7--</span><br></pre></td></tr></table></figure>
<p>那么为什么直接往根url发送请求就可以触发上传操作呢,简单分析一下<code>/internal/upstream/routes.go</code>的内容即可发现原因。<br>routeEntry里面规定了所有路由处理的方法,在routeEntry的最后有这么一条路由</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">u.route("", "", defaultUpstream),</span><br></pre></td></tr></table></figure>
<p>也就是当上面的所有路由都匹配失败后,会走到这个默认路由里面。<br>defaultUpstream的定义如下。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">defaultUpstream := static.ServeExisting(</span><br><span class="line"> u.URLPrefix,</span><br><span class="line"> staticpages.CacheDisabled,</span><br><span class="line"> static.DeployPage(static.ErrorPagesUnless(u.DevelopmentMode, staticpages.ErrorFormatHTML, uploadAccelerateProxy)),</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<p>大概就是匹配不到静态文件的处理之后就会去调用<code>static.DeployPage</code>来作默认行为。然后最后调用的就是<code>uploadAccelerateProxy</code>这个handle。<code>uploadAccelerateProxy</code>的定义如下,它和上面<code>upload.Accelerate</code>的分析差不多,但是采用了<code>upload.SkipRailsAuthorizer</code>,效果就是不再需要去经过<code>PreAuthorizer</code>的检查,也就是说不再与puma后端交互而直接触发上传的操作。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uploadAccelerateProxy := upload.Accelerate(&upload.SkipRailsAuthorizer{TempPath: uploadPath}, proxy, preparers.uploads)</span><br></pre></td></tr></table></figure>
<p>分析到这应该很清楚了,就是workhorse最后的默认路由在匹配不到静态目录下的文件的情况下,默认的处理方式是会处理文件上传这个行为的。导致这个漏洞直接往根url直接POST恶意文件即可触发漏洞。</p>
</div>
<footer class="article-footer">
<a data-url="https://blog.rebirthwyw.top/2021/11/01/analysis-of-CVE-2021-22205-pre-auth-part/" data-id="ckvgjubz60000rgm3938vbvh3" data-title="analysis of CVE-2021-22205 pre-auth part" class="article-share-link">Share</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/gitlab/" rel="tag">gitlab</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/vul/" rel="tag">vul</a></li></ul>
</footer>
</div>
</article>
<article id="post-web-challenges-in-my-ctf-life" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<div class="article-meta">
<a href="/2021/10/22/web-challenges-in-my-ctf-life/" class="article-date">
<time class="dt-published" datetime="2021-10-22T08:29:41.000Z" itemprop="datePublished">2021-10-22</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="p-name article-title" href="/2021/10/22/web-challenges-in-my-ctf-life/">这些年CTF中做过的Web题</a>
</h1>
</header>
<div class="e-content article-entry" itemprop="articleBody">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>2015年底开始参加CTF以来,参加过很多比赛,本科在BXS team时由于时间过于久远以及当时水平也比较低就不做记录了。以下记录的题目从我代表NeSE开始参加的第一场比赛Hitcon2017为起始点。</p>
<h1 id="2017"><a href="#2017" class="headerlink" title="2017"></a>2017</h1><h2 id="BabyFirst-Revenge-v2"><a href="#BabyFirst-Revenge-v2" class="headerlink" title="BabyFirst Revenge v2"></a>BabyFirst Revenge v2</h2><p><a target="_blank" rel="noopener" href="https://github.com/orangetw/My-CTF-Web-Challenges/blob/master/hitcon-ctf-2017/babyfirst-revenge-v2/index.php">题目链接</a><br>题目考点是四字节命令注入。一道考察选手对于linux上各种命令特性了解和使用的题目。当年比赛时肝出这道题让我很开心,印象中当时国内队伍只有我们做出来了。这题和Web的攻击技巧关系不大,主要是对linux上各种命令的掌握程度。</p>
<h2 id="baby-h-master-php-2017"><a href="#baby-h-master-php-2017" class="headerlink" title="baby^h-master-php-2017"></a>baby^h-master-php-2017</h2><p><a target="_blank" rel="noopener" href="https://github.com/orangetw/My-CTF-Web-Challenges/tree/master/hitcon-ctf-2017/baby%5Eh-master-php-2017">题目链接</a><br>应该是phar反序列化这个攻击面被第一次公开地展示到了大家面前。后面经过blackhat上的详细展开,我们现在的题目中才有了这么多phar反序列化的考点(<a target="_blank" rel="noopener" href="https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It.pdf">会议链接</a>)。</p>
<h1 id="2021"><a href="#2021" class="headerlink" title="2021"></a>2021</h1><h2 id="number-manager"><a href="#number-manager" class="headerlink" title="number manager"></a>number manager</h2><p>刚刚打完asisctf2021,质量出乎意料的高,前端选手的狂欢。这题采用了goahead这个c语言写的http框架作为server,题目大意是给了一个可以创建post的功能,攻击者真正可控的只有创建的子目录名,同时有个dom xss的点在location.hash处使得你可以控制key为msg的一个cookie的值,最终目标是绕过csrf的检查实现xss。考察的其实是对于goahead的代码审计。代码有两个问题,一个是防御csrf时采用websParseCookie函数去获取csrf_token的值,但是websParseCookie的实现存在问题,可以通过控制msg的值伪造csrf_token的值。第二个问题算是一个危害很低的0day,goahead的static handle在处理目录资源是会返回302请求,但是Location处直接返回了目录名,没有作crlf的防御(前提是目录名存在,所以才有创建子目录的功能)。</p>
<h2 id="af2"><a href="#af2" class="headerlink" title="af2"></a>af2</h2><p>同样是asisctf2021的一个题目,是一个xsleak,题目直接提示了参考 <a target="_blank" rel="noopener" href="https://research.securitum.com/stealing-data-in-great-style-how-to-use-css-to-attack-web-application/">https://research.securitum.com/stealing-data-in-great-style-how-to-use-css-to-attack-web-application/</a> 的技术。唯一区别是,这题的csp是<code>script-src 'none'; img-src 'none'; frame-src 'self'; font-src data: ;</code>因此不能采用 -webkit-scrollbar 配合 backgroud 的方式作消息外带。这道题采用了 lazy loading iframe 的方式来外带消息。因为用window.open方式打开的页面中我们是可以拿到加载的frame的数量的,所以采用 lazy loading 的方式可以在滑动屏幕效果产生时load指定的iframe,再通过window.open拿到的window对象来判断是否加载了特定页面来泄露信息。</p>
<h2 id="phpphp"><a href="#phpphp" class="headerlink" title="phpphp"></a>phpphp</h2><p>同样是asisctf2021的一个题目,一个php的0day题。。。。题目大意是用python实现了一个http协议的parse,将fastcgi需要的环境变量处理好交给后面的fpm去解析。这里注意处理的细节是 script_filename 是将 document_root 和 script_name 的结果作归一化后传入,但是 script_name 则不做处理直接取request_uri 的到 .php 为止的部分传入,目标是任意文件读取。我们知道在古早的时候 fpm 可以指定 script_filename 为任意文件,但是后面 security.limit_extensions 这个配置的出现基本限制了 script_filename 为特定后缀的文件,比如 .php。这次的漏洞就是绕过了 security.limit_extensions 的限制。漏洞的位置是 main/fopen_wrappers.c 中的 php_fopen_primary_script 函数,主要是把传给fpm的环境变量中的SCRIPT_NAME进行了解析作为后续要打开的文件的handle,具体的poc就不展示了,有兴趣的同学看看代码应该就能构造出来。</p>
<h1 id="todo"><a href="#todo" class="headerlink" title="todo"></a>todo</h1><p>上次更新时间: 2021年10月22日<br>最新更新时间: 2021年10月27日<br>持续更新…</p>
</div>
<footer class="article-footer">
<a data-url="https://blog.rebirthwyw.top/2021/10/22/web-challenges-in-my-ctf-life/" data-id="ckv24hucd0000glm33nxn6gmh" data-title="这些年CTF中做过的Web题" class="article-share-link">Share</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ctf/" rel="tag">ctf</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/life/" rel="tag">life</a></li></ul>
</footer>
</div>
</article>
<article id="post-weclome-to-my-blog" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
<div class="article-meta">
<a href="/2021/10/22/weclome-to-my-blog/" class="article-date">
<time class="dt-published" datetime="2021-10-22T08:26:29.000Z" itemprop="datePublished">2021-10-22</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="p-name article-title" href="/2021/10/22/weclome-to-my-blog/">初衷</a>
</h1>
</header>
<div class="e-content article-entry" itemprop="articleBody">
<p>之前也潦草地创建过一个博客,内容很少,两年多只更新了两篇CTF的WriteUp以及一个学习Java的备忘录。之所以不更新博客,主要是因为人懒,知识习惯性地记录在脑子里,想到需要整理成文、排版发布就放弃了。还有一方面原因,是因为在我狭隘的认识里,一直觉得网络安全是一个沉默的战场,一个新颖的漏洞发现或者利用技术的公开都意味着迅速贬值。基于以上的原因,博客就一直长草搁置于我的电脑中。<br>但随着年龄以及学习到的各方面知识的增多,我愈发感觉到系统地整理自己的知识,以某种媒介的形式存储下来是非常有必要的。所以打算重新开启自己的博客,主要是记录最近学习和研究的内容,基于我狭隘的世界观,这里也不会出现什么新颖的思路,只是一些公开内容的二次学习资料,在此事先说明。<br>最后,作为一个从2015年开始接触CTF的老年人,也算是度过了单独为一个题目写WriteUp的年纪,之前觉得wupco博客整理自己觉得不错的CTF题目的形式挺好(<a target="_blank" rel="noopener" href="http://www.wupco.cn/?page_id=1174">wupco博客链接</a>)。所以,后面就单独开一篇文章(<a href="https://blog.rebirthwyw.top/2021/10/22/web-challenges-in-my-ctf-life/">链接</a>)回忆以及持续记录这些年参加过的CTF比赛中遇到的Web题目,不再单独写某个题目的WriteUp了。<br>最后的最后,选择这个最简单最基础的hexo默认主题也是希望自己无论是作研究还是做人都可以单纯简单一些,不忘初心,不悔前尘。</p>
</div>
<footer class="article-footer">
<a data-url="https://blog.rebirthwyw.top/2021/10/22/weclome-to-my-blog/" data-id="ckv240dz10000cim3ef4e5jyg" data-title="初衷" class="article-share-link">Share</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/life/" rel="tag">life</a></li></ul>
</footer>
</div>
</article>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">Tags</h3>
<div class="widget">
<ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/ctf/" rel="tag">ctf</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/gitlab/" rel="tag">gitlab</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/life/" rel="tag">life</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vul/" rel="tag">vul</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tag Cloud</h3>
<div class="widget tagcloud">
<a href="/tags/ctf/" style="font-size: 10px;">ctf</a> <a href="/tags/gitlab/" style="font-size: 10px;">gitlab</a> <a href="/tags/life/" style="font-size: 20px;">life</a> <a href="/tags/vul/" style="font-size: 10px;">vul</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Archives</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/11/">November 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/10/">October 2021</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recent Posts</h3>
<div class="widget">
<ul>
<li>
<a href="/2021/11/01/analysis-of-CVE-2021-22205-pre-auth-part/">analysis of CVE-2021-22205 pre-auth part</a>
</li>
<li>
<a href="/2021/10/22/web-challenges-in-my-ctf-life/">这些年CTF中做过的Web题</a>
</li>
<li>
<a href="/2021/10/22/weclome-to-my-blog/">初衷</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
<a rel="license noopener" target="_blank" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a></br>
All website licensed under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC BY 4.0</a></br>
<a href="http://beian.miit.gov.cn" rel="noopener" target="_blank">京ICP备19051299号-3</a></br>
© 2022 rebirthwyw<br>
Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
<a href="/about" class="mobile-nav-link">About</a>
<a href="/links" class="mobile-nav-link">Links</a>
</nav>
<script src="/js/jquery-3.4.1.min.js"></script>
<script src="/fancybox/jquery.fancybox.min.js"></script>
<script src="/js/script.js"></script>
</div>
</body>
</html>