2023年6月21日发(作者:)
防sql注⼊盲注等措施ESAPI的使⽤SQL注⼊往往是在程序员编写包含⽤户输⼊的动态查询时产⽣的,但其实防范SQL注⼊的⽅法⾮常简单。程序员只要a)不再写动态查询,或b)防⽌⽤户输⼊包含能够破坏查询逻辑的恶意SQL语句,就能够防范SQL注⼊。在这篇中,我们将会说明⼀些⾮常简单的防⽌SQL注⼊的⽅法。我们⽤以下Java代码作为⽰例,String query ="SELECT account_balance FROM user_data WHERE user_name =" + ameter("customerName");
try {Statement statement =
Statement( …);ResultSet results =
eQuery(query);}在以上代码中,我们可以看到并未对变量customerName做验证,customerName的值可以直接附在query语句的后⾯传送到数据库执⾏,则攻击者可以将任意的sql语句注⼊。防范⽅法1:参数化查询参数化查询是所有开发⼈员在做数据库查询时⾸先需要的,参数化查询迫使所有开发者⾸先要定义好所有的SQL代码,然后再将每个参数逐个传⼊,这种编码风格就能够让数据库辨明代码和数据。参数化查询能够确保攻击者⽆法改变查询的内容,在下⾯修正过的例⼦中,如果攻击者输⼊了UsrID是“’or ‘1 ‘=’1”,参数化查询会去查找⼀个完全满⾜名字为‘or ‘1 ‘=’ 1的⽤户。对于不同编程语⾔,有⼀些不同的建议:Java EE——使⽤带绑定变量的PreparedStatement();.Net——使⽤带绑定变量的诸如SqlCommand()或OleDbCommand()的参数化查询;PHP——使⽤带强类型的参数化查询PDO(使⽤bindParam());Hibernate——使⽤带绑定变量的createQuery()。Java⽰例:String custname = ameter("customerName");String query ="SELECT account_balance FROM user_data WHERE user_name= ?";
PreparedStatement pstmt = eStatement(query);ing(1,custname);ResultSet results = eQuery();
C# .Net⽰例:String query ="SELECT account_balance FROM user_data WHERE user_name = ?";Try {
OleDbCommand command = new OleDbCommand(query,connection);(new OleDbParameter("customerName",));OleDbDataReader reader = eReader();}catch (OleDbException se){//error handling}
防范⽅法⼆:存储过程存储过程和参数化查询的作⽤是⼀样的,唯⼀的不同在于存储过程是预先定义并存放在数据库中,从⽽被应⽤程序调⽤的。Java存储过程⽰例: String custname = ameter("customerName"); try {CallableStatement cs = eCall("call sp_getAccountBalance(?)}");ing(1,custname);Result results = eQuery(); }catch(SQLException se){ //error handling }
VB .Net存储过程⽰例:TryDim command As SqlCommand = new SqlCommand("sp_getAccountBalance",connection) dType = Procedure (new SqlParameter("@CustomerName",)) Dim reader As SqlDataReader = eReader() ‘…Catch se As SqlException ‘error handlingEnd Try
防范⽅法三:对所有⽤户输⼊进⾏转义我们知道每个DBMS都有⼀个字符转义机制来告知DBMS输⼊的是数据⽽不是代码,如果我们将所有⽤户的输⼊都进⾏转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注⼊了。当然,如果要采⽤这种⽅法,那么你就需要对所使⽤的数据库转义机制,也可以使⽤现存的诸如OWASP ESAPI的escaping routines。ESAPI⽬前是基于和的转义机制的,使⽤起来也很⽅便。⼀个Oracle的ESAPI的使⽤⽰例如下:r().encodeForSQL(new OracleCodec(),queryparam);那么,假设你有⼀个要访问Oracle数据库的动态查询代码如下:String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+ameter("userID")+"’ and user_password =‘"+ameter("pwd")+"’";try { Statement statement = Statement(…); ResultSet results = eQuery(query) ;}那么,你就必须重写你的动态查询的第⼀⾏如下:Codec ORACLE_CODEC = new OracleCodec();String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+r().encodeForSQL(ORACLE_CODEC,ameter("userID"))+"’ and user_password = ‘"+r().encodeForSQL(ORACLE_CODEC,ameter("pwd"))+"’";
当然,为了保证⾃⼰代码的可读性,我们也可以构建⾃⼰的OracleEncoder:Encoder e = new OracleEncoder();String query ="SELECT user_id FROM user_data WHERE user_name = ‘" + (ameter("userID")) +"’ and user_password = ‘" + (ameter("pwd"))+"’"; 除了上⾯所说的三种防范⽅法以外,我们还建议可以⽤以下两种附加的⽅法来防范SQL注⼊:最⼩权限法、输⼊验证⽩名单法。最⼩权限法:为了避免注⼊攻击对数据库造成的损害,我们可以把每个数据库⽤户的权限尽可能缩⼩,不要把DBA或管理员的权限赋予你应⽤程序账户,在给⽤户权限时是基于⽤户需要什么样的权限,⽽不是⽤户不需要什么样的权限。当⼀个⽤户只需要读的权限时,我们就只给他读的权限,当⽤户只需要⼀张表的部分数据时,我们宁愿另建⼀个视图让他访问。如果你的策略是都是⽤存储过程的话,那么仅允许应⽤程序的账户执⾏这些查询,⽽不给他们直接访问数据库表的权限。诸如此类的最⼩权限法能够在很⼤程度上保证我们数据库的安全。输⼊验证⽩名单法:输⼊验证能够在数据传递到SQL查询前就察觉到输⼊是否正确合法,采⽤⽩名单⽽不是⿊名单则能在更⼤程度上保证数据的合法性。
2023年6月21日发(作者:)
防sql注⼊盲注等措施ESAPI的使⽤SQL注⼊往往是在程序员编写包含⽤户输⼊的动态查询时产⽣的,但其实防范SQL注⼊的⽅法⾮常简单。程序员只要a)不再写动态查询,或b)防⽌⽤户输⼊包含能够破坏查询逻辑的恶意SQL语句,就能够防范SQL注⼊。在这篇中,我们将会说明⼀些⾮常简单的防⽌SQL注⼊的⽅法。我们⽤以下Java代码作为⽰例,String query ="SELECT account_balance FROM user_data WHERE user_name =" + ameter("customerName");
try {Statement statement =
Statement( …);ResultSet results =
eQuery(query);}在以上代码中,我们可以看到并未对变量customerName做验证,customerName的值可以直接附在query语句的后⾯传送到数据库执⾏,则攻击者可以将任意的sql语句注⼊。防范⽅法1:参数化查询参数化查询是所有开发⼈员在做数据库查询时⾸先需要的,参数化查询迫使所有开发者⾸先要定义好所有的SQL代码,然后再将每个参数逐个传⼊,这种编码风格就能够让数据库辨明代码和数据。参数化查询能够确保攻击者⽆法改变查询的内容,在下⾯修正过的例⼦中,如果攻击者输⼊了UsrID是“’or ‘1 ‘=’1”,参数化查询会去查找⼀个完全满⾜名字为‘or ‘1 ‘=’ 1的⽤户。对于不同编程语⾔,有⼀些不同的建议:Java EE——使⽤带绑定变量的PreparedStatement();.Net——使⽤带绑定变量的诸如SqlCommand()或OleDbCommand()的参数化查询;PHP——使⽤带强类型的参数化查询PDO(使⽤bindParam());Hibernate——使⽤带绑定变量的createQuery()。Java⽰例:String custname = ameter("customerName");String query ="SELECT account_balance FROM user_data WHERE user_name= ?";
PreparedStatement pstmt = eStatement(query);ing(1,custname);ResultSet results = eQuery();
C# .Net⽰例:String query ="SELECT account_balance FROM user_data WHERE user_name = ?";Try {
OleDbCommand command = new OleDbCommand(query,connection);(new OleDbParameter("customerName",));OleDbDataReader reader = eReader();}catch (OleDbException se){//error handling}
防范⽅法⼆:存储过程存储过程和参数化查询的作⽤是⼀样的,唯⼀的不同在于存储过程是预先定义并存放在数据库中,从⽽被应⽤程序调⽤的。Java存储过程⽰例: String custname = ameter("customerName"); try {CallableStatement cs = eCall("call sp_getAccountBalance(?)}");ing(1,custname);Result results = eQuery(); }catch(SQLException se){ //error handling }
VB .Net存储过程⽰例:TryDim command As SqlCommand = new SqlCommand("sp_getAccountBalance",connection) dType = Procedure (new SqlParameter("@CustomerName",)) Dim reader As SqlDataReader = eReader() ‘…Catch se As SqlException ‘error handlingEnd Try
防范⽅法三:对所有⽤户输⼊进⾏转义我们知道每个DBMS都有⼀个字符转义机制来告知DBMS输⼊的是数据⽽不是代码,如果我们将所有⽤户的输⼊都进⾏转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注⼊了。当然,如果要采⽤这种⽅法,那么你就需要对所使⽤的数据库转义机制,也可以使⽤现存的诸如OWASP ESAPI的escaping routines。ESAPI⽬前是基于和的转义机制的,使⽤起来也很⽅便。⼀个Oracle的ESAPI的使⽤⽰例如下:r().encodeForSQL(new OracleCodec(),queryparam);那么,假设你有⼀个要访问Oracle数据库的动态查询代码如下:String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+ameter("userID")+"’ and user_password =‘"+ameter("pwd")+"’";try { Statement statement = Statement(…); ResultSet results = eQuery(query) ;}那么,你就必须重写你的动态查询的第⼀⾏如下:Codec ORACLE_CODEC = new OracleCodec();String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+r().encodeForSQL(ORACLE_CODEC,ameter("userID"))+"’ and user_password = ‘"+r().encodeForSQL(ORACLE_CODEC,ameter("pwd"))+"’";
当然,为了保证⾃⼰代码的可读性,我们也可以构建⾃⼰的OracleEncoder:Encoder e = new OracleEncoder();String query ="SELECT user_id FROM user_data WHERE user_name = ‘" + (ameter("userID")) +"’ and user_password = ‘" + (ameter("pwd"))+"’"; 除了上⾯所说的三种防范⽅法以外,我们还建议可以⽤以下两种附加的⽅法来防范SQL注⼊:最⼩权限法、输⼊验证⽩名单法。最⼩权限法:为了避免注⼊攻击对数据库造成的损害,我们可以把每个数据库⽤户的权限尽可能缩⼩,不要把DBA或管理员的权限赋予你应⽤程序账户,在给⽤户权限时是基于⽤户需要什么样的权限,⽽不是⽤户不需要什么样的权限。当⼀个⽤户只需要读的权限时,我们就只给他读的权限,当⽤户只需要⼀张表的部分数据时,我们宁愿另建⼀个视图让他访问。如果你的策略是都是⽤存储过程的话,那么仅允许应⽤程序的账户执⾏这些查询,⽽不给他们直接访问数据库表的权限。诸如此类的最⼩权限法能够在很⼤程度上保证我们数据库的安全。输⼊验证⽩名单法:输⼊验证能够在数据传递到SQL查询前就察觉到输⼊是否正确合法,采⽤⽩名单⽽不是⿊名单则能在更⼤程度上保证数据的合法性。
发布评论