1. 程式人生 > >佔位符,SQL注入?

佔位符,SQL注入?

這兩天在上課時被同學拿了一段程式碼問我,這段程式碼有什麼問題,我看了一會說:Connection和PreparedStatement都沒關。他說不止這方面的問題,還有sql注入的問題,我就堅決的說使用了佔位符不存在sql注入的問題,但是他提出了一種情況,在我看來也很有道理的情況。

pstmt = conn.prepareStatement("delete from user where user.id=?");
pstmt.setString(1, "w"); 他認為如果把程式碼寫成這樣就有注入問題了
pstmt = conn.prepareStatement("delete from user where user.id=?");
pstmt.setString(1, "w' or '2'='2");

當時我看了只能告訴他一定不存在注入問題,因為在我的想法中我一直記得的是用佔位符能解決注入問題,至於怎麼解決的就不知道了,看了上面的程式碼也很有道理,感覺setString後的sql語句應該是
delete from user where user.id='w' or '2'='2';

回到宿舍我專門寫了程式測試一下,事實證明並不想我們想的這樣,的確使用佔位符不存在注入問題,所以解釋是在執行的時候把一些字元給轉義了,但這個轉義的過程是在什麼地方轉義的呢,把上面的sql語句在mysql控制檯上執行一下,檢視一下資料看到所有資料都被刪除完,那隻能解釋成在java程式中轉義的,於是我就去看java的原始碼,發現在java原始碼中PreparedStatement只是一個介面,而且是沒有子類的介面,我就很納悶,沒實現怎麼用的?所以一定有實現的地方,去網上查了一下,jdk直提供介面,而具體實現是由資料庫廠商實現的,我們用的就是資料庫廠商實現的類。於是我就又去查mysql的jar包原始碼,發現有個PreparedStatement實現了jdk中的PreparedStatement了。裡面的setString方法如下實現:

public void setString(int parameterIndex, String x) throws SQLException {
		// if the passed string is null, then set this column to null
		if (x == null) {
			setNull(parameterIndex, Types.CHAR);
		} else {
			StringBuffer buf = new StringBuffer((int) (x.length() * 1.1));
			buf.append('\'');

			int stringLength = x.length();

			//
			// Note: buf.append(char) is _faster_ than
			// appending in blocks, because the block
			// append requires a System.arraycopy()....
			// go figure...
			//
			for (int i = 0; i < stringLength; ++i) {
				char c = x.charAt(i);

				switch (c) {
				case 0: /* Must be escaped for 'mysql' */
					buf.append('\\');
					buf.append('0');

					break;

				case '\n': /* Must be escaped for logs */
					buf.append('\\');
					buf.append('n');

					break;

				case '\r':
					buf.append('\\');
					buf.append('r');

					break;

				case '\\':
					buf.append('\\');
					buf.append('\\');

					break;

				case '\'':
					buf.append('\\');
					buf.append('\'');

					break;

				case '"': /* Better safe than sorry */
					if (this.usingAnsiMode) {
						buf.append('\\');
					}

					buf.append('"');

					break;

				case '\032': /* This gives problems on Win32 */
					buf.append('\\');
					buf.append('Z');

					break;

				default:
					buf.append(c);
				}
			}

			buf.append('\'');

			String parameterAsString = buf.toString();

			byte[] parameterAsBytes = null;

			if (!this.isLoadDataQuery) {
				parameterAsBytes = StringUtils.getBytes(parameterAsString,
						this.charConverter, this.charEncoding, this.connection
								.getServerCharacterEncoding(), this.connection
								.parserKnowsUnicode());
			} else {
				// Send with platform character encoding
				parameterAsBytes = parameterAsString.getBytes();
			}

			setInternal(parameterIndex, parameterAsBytes);
		}
	}


到此就告一段落,可以發現在setString時最外面的單引號被轉義了,也就是說setString後的sql語句是這樣的

delete from user where user.id=\'w' or '2'='2\';
而且仔細看會發現在setString中是一個字元一個字元的解析,該轉義的都已經轉義,正如他一句註釋中寫的Better safe than sorry.所以最終,佔位符確實不存在注入問題

相關推薦

佔位SQL注入

這兩天在上課時被同學拿了一段程式碼問我,這段程式碼有什麼問題,我看了一會說:Connection和PreparedStatement都沒關。他說不止這方面的問題,還有sql注入的問題,我就堅決的說使用了佔位符不存在sql注入的問題,但是他提出了一種情況,在我看來也很有道理的

佔位防止sql注入

防止sql注入方式:1.在jdbc的PreparedStatement 用?佔位符String sql= "SELECT * FORM emp where ENAME=?"; PreparedState

使用Freemarker解析佔位構造可執行的SQL語句

背景 最近遇到一個需求, 框架需要執行使用者給定的SQL語句,該SQL語句內包含佔位符, 佔位符表示的內容存在於在框架中,比如下面的sql select * from xxx where id =

占位SQL註入?

switch rac () ems 控制臺 程序 bsp ras ansi 這兩天在上課時被同學拿了一段代碼問我,這段代碼有什麽問題,我看了一會說:Connection和PreparedStatement都沒關。他說不止這方面的問題,還有sql註入的問題,我就堅決的說使用了

XSSSQl注入與防範

XSS攻擊全稱跨站指令碼攻擊(cross-site scripting ),是為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站指令碼攻擊縮寫為XSS,XSS是一種在web應用中的電腦保安漏洞,它允許惡意web使用者將程式碼植入到提供給其它使用者使

為啥jdbc問號佔位可以防注入

最近幾天探討一下關於sql注入的問題,以前林老師也講過,現在總結一下, 其實,like是會注入的,也不建議用,用佔位符實際查詢效果不是like本身的意思,相當全匹配。 建議使用instr()函式,本文主要記錄一下處理防止注入的原始碼,為什麼用?可以防注入,而拼接的sql可

js使用原生String替換佔位格式化資料

1、最近修改了js的String原生方法,程式碼如下:/** * 定義原生使用佔位符的方法,格式化資料 * @author sky * @date 2018-07-09 * @returns {*} */ String.prototype.format = func

[Tips]org.slf4j.Logger使用{}佔位避免字串連線

slf4j是日誌系統的Facade(外觀模式),注意必須與具體日誌繫結。 其提供TRACE, DEBUG, INFO, WARN, ERROR level。 private final stati

臥槽sql注入竟然把我們的系統搞掛了

# 前言 最近我在整理安全漏洞相關問題,準備在公司做一次分享。恰好,這段時間團隊發現了一個sql注入漏洞:在一個公共的分頁功能中,排序欄位作為入參,前端頁面可以自定義。在分頁sql的`mybatis` `mapper.xml`中,`order by`欄位後面使用$符號動態接收計算後的排序引數,這樣可以實現動態

Spring @Value("$XXX")注入值失敗錯誤資訊提示:Could not resolve placeholder佔位不能被解析

問題原因: Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'wx.app.config.appid' in string value "${wx.app.config

prepareStatement進行增刪改查---填充佔位(防止sql注入

首先建立表 然後構造一個實體類–封裝資料庫欄位 Student package com.godinsec; public class Student { private int id; private String name;

yii框架中findall方法取資料使用總結包括select各種條件where條件order by條件limit限制以及使用單純sql語句query時佔位的使用等

在yii框架中可以使用對映類的find方法取出一條資料或者用findall方法取出數條資料來,那麼如何按照所需條件來取資料呢,主要用到了CDbCriteria這個類,這個類是yii自帶的操作資料庫的支援類,可以作為引數傳遞給find等方法,這裡用findall做個例子:

關於使用佔位來解決SQL注入

總結: SQL已經預編譯好了,然後替換中間的佔位符,這個佔位符在編譯後就已經確定了它只是一個引數屬性。因此,用注入的程式碼去替換佔位符,這個SQL也不會再進行編譯了,所以也達不到注入的目的。 SQL注入並不是一個在SQL內不可解決的問題,這種攻擊方式的存在也不能完全歸

sql 替換字段中的部分字替換指定字

pos AC color 指定 gpo 字段 寫法 nbsp repl 把列中凡是有2011的全部修改成2014,如 lieming 裏的201101131431改成201401131431,寫法: update tab set lieming = replace(li

什麼叫做SQL注入如何防止?

 所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字串,欺騙伺服器執行惡意的SQL命令。在某些表單中,使用者輸入的內容直接用來構造(或者影響)動態SQL命令,或作為儲存過程的輸入引數,這類表單特別容易受到SQL注入式攻擊。常見的SQL注入式攻擊過

MySQL— pymysql模組(防止sql注入視覺化軟體Navicat

一.Pymysql import pymysql #python2.X 中是 mysqldb 和 pythonmysql 用法是一模一樣的 #pymysql可以偽裝成上面這兩個模組 user = input('username: ') pwd = input('passwo

JDBC預處理物件PreprareStatement預防SQL注入問題提高安全性

PreparedStatement介面是Statement的子介面,它直接繼承並重載了Statement的方法。 PreprareStatement預處理物件為什麼能預防SQL注入提高安全性呢? 因為SQL語句在程式執行前已經進行了預編譯,在程式執行時第一次操作資料庫之前,SQL語

新版Glide載入圖片時佔位placeholder失效的解決方案

我使用的是當前最新的Glide4.8.0的版本,想要設定在載入圖片過程中顯示預設圖片的功能,網上查到的設定placeholder,但實際發現這個屬性爆紅無法使用。 解決方案: Glide .with(this) .load(PHOTO_URL) .apply(new Request

SQL注入PreparedStatement和Statement

程式碼區 還是一個工具類 程式碼: package cn.itcats.jdbc; import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLE

Python 資料庫操作mysqlsql注入引數化

  demo.py(防sql注入): from pymysql import * def main(): find_name = input("請輸入物品名稱:") # 建立Connection連線 conn = connect(host='local