0x01 介绍:
这种注入方式一般是在如下情况出现时发生:为了预防SQL注入攻击,而将输入到应用程序中的某些数据进行了“转义(escape)”,但是这些数据却又在“未被转义(Unescaped)”的查询窗体中重复使用。
例如,这里我们更改登录处理页面(在前面“攻击系统”一节中介绍的那个页面)以回避单引号:
0x02 分析
username = escape( Request.form("username") ); password = escape( Request.form("password") ); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; rso.open( sql, cn );
这个转义(escape)函数如下所示:
function escape(str) { var s = new string(str); var ret; var re = new RegExp("'","g"); ret = s.replace(re,"''"); return ret; }
请留意Jscrīpt的“String”对象在实现“replace”方法时存在一个弱点是非常重要的—下面的代码仅仅替换单引号的第一个字符:
function badescape(str) { var s = new string(str); var ret; ret = s.replace("'","''"); return ret; }
为了能够成功地进行二次SQL注入,现在的攻击者可能不会再使用我们这里用作示例的任何方法进行SQL注入。
但是,假设应用程序允许用户可以更改他们的口令,实现这种功能的代码大致如下所示:
username = escape(Request.form("username")); oldpassword = escape(Request.form("oldpassword")); newpassword = escape(Request.form("newpassword")); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username='" + username + "' and password = '" + oldpassword + "'"; rso.open(sql, cn); if (rso.EOF) { ...
0x03:利用
设置新密码的查询与如下代码可能有些相似:
sql = "update users set password = '" + newpassword + "' where username = '" + rso("username") + "'";
在该示例代码中,rso(“username”)是从“login”查询中检索到的用户名称。假定用户名称为admin’—,该查询语句实际上就是下面的查询:
update users set password = 'password' where username = 'admin'--'
因此,攻击者可以通过用户名admin’—进行注册的方法,随意设置系统管理员admin的密码。
这主要强调了自始至终都要坚持输入验证的重要性,哪怕是对系统已经使用过的数据,在查询中包含该数据以前,也要坚持对其进行输入验证。
0x04 参考文献
https://bbs.ichunqiu.com/thread-9193-1-1.html
https://www.cnblogs.com/ichunqiu/p/5852330.html
https://www.cnblogs.com/aware-why/p/5844702.html
http://www.rising.com.cn/newsletter/news/2013-11-13/14752.html
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论