Less-24
POST型基于存储的二次注入
随意输入
点击:Forgot your password?
翻译:如果你忘记了密码,去黑掉它。
点击:New User click here?
注册用户。
尝试注册一个用户: 用户:test1 密码:test1
翻译:
用户成功
创建
重定向到5中的登录页面......
如果未重定向,请点击右上角的主页(HOME)按钮
尝试注册过后的用户进行登录:
尝试更改用户test1的密码为tese2
从上面的情况中我们可以分析出:
- 登录界面,具有登录功能,同时有忘记密码和注册的链接。
- 注册界面,具有注册功能。
- 忘记密码界面,返回一张图片
- 修改密码界面,登陆成功后,1.显示用户名,2.可以重置密码,3.有登出的链接。
- 登录失败界面,返回一张图片。
综上,可推断出注入点在更改密码上。
分析下源文件:
这三个文件与数据库进行交互,剩下的五个文件分别对应上述几个显示的界面。
代码审计:
这几个文件出现频率最高的代码是:
session_start()
可参考php手册
session_start() 会创建新会话或者重用现有会话。 如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID, 则会重用现有会话。
session_start的作用是开启$_SESION,需要在$_SESION使用之前调用。
PHP $_SESION 变量用于存储关于用户会话(session)的信息
接着分析:
1. login.php
PHP mysql_real_escape_string() 函数
定义和用法
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- '
- "
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
语法
mysql_real_escape_string(string,connection)
参数 | 描述 |
---|---|
string | 必需。规定要转义的字符串。 |
connection | 可选。规定 MySQL 连接。如果未规定,则使用上一个连接。 |
说明
本函数将 string 中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()。
可以看到代码对username和passseord的特殊字符进行了转义,想要在这里进行注入就得采取“绕过”,但这不是我们这道题想要的解法,我们就当这里无法注入好了,也就是说在登录页面login.php处无法进行注入。
登录成功后创建session
和cookie
,session
存储username
,但session
是建立在服务器上的对象,所以无法获取;cookie
只是个登录标记,几乎没有任何用处。(会话15分钟后过期)
2. login_create.php
创建用户前先查询是否已经存在该账号,若存在则弹出一个对话框,不存在就创建。
这里要注意到:mysql_escape_string()
和mysql_real_escape_string()
是不同的,前者早在PHP 5.3
中被弃用。
mysql_escape_string() 并不转义 % 和 _。 本函数和 mysql_real_escape_string() 完全一样,除了mysql_real_escape_string() 接受的是一个连接句柄并根据当前字符集转移字符串之外。mysql_escape_string()并不接受连接参数,也不管当前字符集设定。。
也就是说:mysql_escape_string()
没办法判断当前的编码,mysql_real_escape_string()
之所以能够防注入是因为同时指定了服务端的编码和客户端的编码。
综上:username,password,re_password 这三个字段所传递的字符是要被转义的。
pass_change.php
重点来了:
从session
中直接获得了当前用户名,且被直接用于更新语句并未做检查。
从根本上来说,插入数据时没有过滤,只是做了转义处理。
若当前用户名中含有注释,便可以修改当前用户名中包含的另一用户的密码,例如注册用户:Dumb'-- # 那么他就可以修改用户Dunb的密码。
本关为二次排序注入的示范例。二次排序注入也称为存储型的注入,就是将可能导致
sql 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以出发 sql 注入。
二次排序注入思路:
1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交 HTTP 数据报文请求到服务
端进行处理,提交的数据报文请求中可能包含了黑客构造的 SQL 语句或者命令。
2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的
数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响
应。
3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。
4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库
中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的 SQL 语句或者命令在服
务端环境中执行。
5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注
入漏洞利用是否成功。
此例子中我们的步骤是注册一个 Dumb'-- # 的账号,接下来登录该帐号后进行修改密码。此时修改的就是 Dumb 的密码
注入点在修改密码处
UPDATE users SET PASSWORD='$pass' WHERE username='$username' and password='$curr_pass'
要将其变为:
UPDATE users SET PASSWORD='$pass' WHERE username='$username'-- # and password='$curr_pass'
也就是执行了:
UPDATE users SET PASSWORD='新密码' WHERE username='Dumb'
步骤演示:
1.初始数据库:
2.注册 Dumb'-- # 账号,密码我们随便设置,这里设置为 110
3.注意此时的数据库中出现了 Dumb'-- # 的用户,还要注意此时原账户Dumb的密码为Dumb
4.登录账户 Dumb'-- #,并修改密码为220
5.查看修改后数据库:
6.使用账户Dumb,密码220 进行登录:
成功 HACKED 如果Dumb是管理员账户的话,那么。。。嘿嘿
总结:
对于这道题的更像是 PHP代码审计,如果是人工直接注入的话,难度还是蛮大的,因为你不知道他的代码是怎样设计的,只是靠猜的话,所耗费的时间将是漫长的,所以要多积累经验。