QL注入是網(wǎng)站常見的黑客攻擊行為之一,相信各大站長對此并不陌生,但是很多站長初遇SQL攻擊時都會感到不知所措。本文將對SQL進(jìn)行一些資料的收集,對針對SQL轉(zhuǎn)入提出一些對應(yīng)的解決方案,希望對各大站長有所幫助。
什么是SQL注入
SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令。具體來說,它是利用現(xiàn)有應(yīng)用程序,將(惡意的)SQL命令注入到后臺數(shù)據(jù)庫引擎執(zhí)行的能力,它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網(wǎng)站上的數(shù)據(jù)庫,而不是按照設(shè)計(jì)者意圖去執(zhí)行SQL語句。比如先前的很多影視網(wǎng)站泄露VIP會員密碼大多就是通過WEB表單遞交查詢字符暴出的,這類表單特別容易受到SQL注入式攻擊。
如何判斷SQL注入漏洞
經(jīng)專業(yè)人士總結(jié),有以下兩種方法可以判斷網(wǎng)站是否被SQL注入
1、錯誤提示
如果WEB網(wǎng)站開啟了錯誤顯示,攻擊者就可以通過反復(fù)調(diào)整發(fā)送的參數(shù)、查看頁面打印的錯誤信息,推測出WEB網(wǎng)站使用的數(shù)據(jù)庫和開發(fā)語言等重要信息。
2、盲注
除非是運(yùn)維人員疏忽,否則大多數(shù)的WEB運(yùn)營網(wǎng)站應(yīng)該都關(guān)閉錯誤提示信息,此時攻擊者一般會采用盲注的技巧來進(jìn)行反復(fù)的嘗試判斷。如果查看的網(wǎng)頁頁面的url地址為:userinfo.php?username=plhwin,此刻黑客分別訪問userinfo.php?username=plhwin’AND 1=1–hack和userinfo.php?username=plhwin’AND 1=2–hack,如果前者訪問能返回正常的信息而后者不能,就基本可以判斷此網(wǎng)站存在SQL注入漏洞,因?yàn)楹笳叩?=2這個表達(dá)方式永遠(yuǎn)不成立,所以即使username傳入了正確的參數(shù)也無法通過,由此可以推斷這個頁面存在SQL注入漏洞,并且可以通過username參數(shù)進(jìn)行注入。
網(wǎng)站如何防止SQL注入
1普通用戶與系統(tǒng)管理員用戶的權(quán)限要有嚴(yán)格的區(qū)分。
如果一個普通用戶在使用查詢語句中嵌入另一個Drop Table語句,那么是否允許執(zhí)行呢?由于Drop語句關(guān)系到數(shù)據(jù)庫的基本對象,故要操作這個語句用戶必須有相關(guān)的權(quán)限。在權(quán)限設(shè)計(jì)中,對于終端用戶,即應(yīng)用軟件的使用者,沒有必要給他們數(shù)據(jù)庫對象的建立、刪除等權(quán)限。那么即使在他們使用SQL語句中帶有嵌入式的惡意代碼,由于其用戶權(quán)限的限制,這些代碼也將無法被執(zhí)行。故應(yīng)用程序在設(shè)計(jì)的時候,
2強(qiáng)制使用參數(shù)化語句。
如果在編寫SQL語句的時候,用戶輸入的變量不是直接嵌入到SQL語句。而是通過參數(shù)來傳遞這個變量的話,那么就可以有效的防治SQL注入式攻擊。也就是說,用戶的輸入絕對不能夠直接被嵌入到SQL語句中。與此相反,用戶的輸入的內(nèi)容必須進(jìn)行過濾,或者使用參數(shù)化的語句來傳遞用戶輸入的變量。參數(shù)化的語句使用參數(shù)而不是將用戶輸入變量嵌入到SQL語句中。采用這種措施,可以杜絕大部分的SQL注入式攻擊。不過可惜的是,現(xiàn)在支持參數(shù)化語句的數(shù)據(jù)庫引擎并不多。不過數(shù)據(jù)庫工程師在開發(fā)產(chǎn)品的時候要盡量采用參數(shù)化語句。
3多使用SQL Server數(shù)據(jù)庫自帶的安全參數(shù)。
為了減少注入式攻擊對于SQL Server數(shù)據(jù)庫的不良影響,在SQLServer數(shù)據(jù)庫專門設(shè)計(jì)了相對安全的SQL參數(shù)。在數(shù)據(jù)庫設(shè)計(jì)過程中,工程師要盡量采用這些參數(shù)來杜絕惡意的SQL注入式攻擊。
如在SQL Server數(shù)據(jù)庫中提供了Parameters集合。這個集合提供了類型檢查和長度驗(yàn)證的功能。如果管理員采用了Parameters這個集合的話,則用戶輸入的內(nèi)容將被視為字符值而不是可執(zhí)行代碼。即使用戶輸入的內(nèi)容中含有可執(zhí)行代碼,則數(shù)據(jù)庫也會過濾掉。因?yàn)榇藭r數(shù)據(jù)庫只把它當(dāng)作普通的字符來處理。使用Parameters集合的另外一個優(yōu)點(diǎn)是可以強(qiáng)制執(zhí)行類型和長度檢查,范圍以外的值將觸發(fā)異常。如果用戶輸入的值不符合指定的類型與長度約束,就會發(fā)生異常,并報(bào)告給管理員。如上面這個案例中,如果員工編號定義的數(shù)據(jù)類型為字符串型,長度為10個字符。而用戶輸入的內(nèi)容雖然也是字符類型的數(shù)據(jù),但是其長度達(dá)到了20個字符。則此時就會引發(fā)異常,因?yàn)橛脩糨斎氲膬?nèi)容長度超過了數(shù)據(jù)庫字段長度的限制。
4加強(qiáng)對用戶輸入的驗(yàn)證。
總體來說,防治SQL注入式攻擊可以采用兩種方法,一是加強(qiáng)對用戶輸入內(nèi)容的檢查與驗(yàn)證;二是強(qiáng)迫使用參數(shù)化語句來傳遞用戶輸入的內(nèi)容。在SQLServer數(shù)據(jù)庫中,有比較多的用戶輸入內(nèi)容驗(yàn)證工具,可以幫助管理員來對付SQL注入式攻擊。測試字符串變量的內(nèi)容,只接受所需的值。拒絕包含二進(jìn)制數(shù)據(jù)、轉(zhuǎn)義序列和注釋字符的輸入內(nèi)容。這有助于防止腳本注入,防止某些緩沖區(qū)溢出攻擊。測試用戶輸入內(nèi)容的大小和數(shù)據(jù)類型,強(qiáng)制執(zhí)行適當(dāng)?shù)南拗婆c轉(zhuǎn)換。這即有助于防止有意造成的緩沖區(qū)溢出,對于防治注入式攻擊有比較明顯的效果。
如可以使用存儲過程來驗(yàn)證用戶的輸入。利用存儲過程可以實(shí)現(xiàn)對用戶輸入變量的過濾,如拒絕一些特殊的符號。如以上那個惡意代碼中,只要存儲過程把那個分號過濾掉,那么這個惡意代碼也就沒有用武之地了。在執(zhí)行SQL語句之前,可以通過數(shù)據(jù)庫的存儲過程,來拒絕接納一些特殊的符號。在不影響數(shù)據(jù)庫應(yīng)用的前提下,應(yīng)該讓數(shù)據(jù)庫拒絕包含以下字符的輸入。如分號分隔符,它是SQL注入式攻擊的主要幫兇。如注釋分隔符。注釋只有在數(shù)據(jù)設(shè)計(jì)的時候用的到。一般用戶的查詢語句中沒有必要注釋的內(nèi)容,故可以直接把他拒絕掉,通常情況下這么做不會發(fā)生意外損失。把以上這些特殊符號拒絕掉,那么即使在SQL語句中嵌入了惡意代碼,他們也將毫無作為。
故始終通過測試類型、長度、格式和范圍來驗(yàn)證用戶輸入,過濾用戶輸入的內(nèi)容。這是防止SQL注入式攻擊的常見并且行之有效的措施。
5多層環(huán)境如何防治SQL注入式攻擊?
在多層應(yīng)用環(huán)境中,用戶輸入的所有數(shù)據(jù)都應(yīng)該在驗(yàn)證之后才能被允許進(jìn)入到可信區(qū)域。未通過驗(yàn)證過程的數(shù)據(jù)應(yīng)被數(shù)據(jù)庫拒絕,并向上一層返回一個錯誤信息。實(shí)現(xiàn)多層驗(yàn)證。對無目的的惡意用戶采取的預(yù)防措施,對堅(jiān)定的攻擊者可能無效。更好的做法是在用戶界面和所有跨信任邊界的后續(xù)點(diǎn)上驗(yàn)證輸入。如在客戶端應(yīng)用程序中驗(yàn)證數(shù)據(jù)可以防止簡單的腳本注入。但是,如果下一層認(rèn)為其輸入已通過驗(yàn)證,則任何可以繞過客戶端的惡意用戶就可以不受限制地訪問系統(tǒng)。故對于多層應(yīng)用環(huán)境,在防止注入式攻擊的時候,需要各層一起努力,在客戶端與數(shù)據(jù)庫端都要采用相應(yīng)的措施來防治SQL語句的注入式攻擊。
SSL證書采用了技術(shù)含量比較高的加密技術(shù)。日后GDCA(數(shù)安時代)將會持續(xù)為大家推薦更多關(guān)于SSL證書的技術(shù)知識。讓大家正確認(rèn)識SSL證書,快速無誤部署HTTPS安全協(xié)議。更多資訊,請關(guān)注GDCA。
文章轉(zhuǎn)載:https://www.trustauth.cn/wiki/18364.html
、SQL注入簡介SQL注入是比較常見的網(wǎng)絡(luò)攻擊方式之一,它不是利用操作系統(tǒng)的BUG來實(shí)現(xiàn)攻擊,而是針對程序員編程時的疏忽,通過SQL語句,實(shí)現(xiàn)無帳號登錄,甚至篡改數(shù)據(jù)庫。
二、SQL注入攻擊的總體思路
1.尋找到SQL注入的位置
2.判斷服務(wù)器類型和后臺數(shù)據(jù)庫類型
3.針對不通的服務(wù)器和數(shù)據(jù)庫特點(diǎn)進(jìn)行SQL注入攻擊
三、SQL注入攻擊實(shí)例
比如在一個登錄界面,要求輸入用戶名和密碼:
可以這樣輸入實(shí)現(xiàn)免帳號登錄:
用戶名: ‘or 1=1 –
密 碼:
點(diǎn)登陸,如若沒有做特殊處理,那么這個非法用戶就很得意的登陸進(jìn)去了.(當(dāng)然現(xiàn)在的有些語言的數(shù)據(jù)庫API已經(jīng)處理了這些問題)
這是為什么呢? 下面我們分析一下:
從理論上說,后臺認(rèn)證程序中會有如下的SQL語句:
String sql="select * from user_table where username=
' "+userName+" ' and password=' "+password+" '";
當(dāng)輸入了上面的用戶名和密碼,上面的SQL語句變成:
SELECT * FROM user_table WHERE username=
'’or 1=1 -- and password='’
分析SQL語句:
條件后面username=”or 1=1 用戶名等于 ” 或1=1 那么這個條件一定會成功;
然后后面加兩個-,這意味著注釋,它將后面的語句注釋,讓他們不起作用,這樣語句永遠(yuǎn)都能正確執(zhí)行,用戶輕易騙過系統(tǒng),獲取合法身份。
這還是比較溫柔的,如果是執(zhí)行
SELECT * FROM user_table WHERE
username='' ;DROP DATABASE (DB Name) --' and password=''
….其后果可想而知…
四、應(yīng)對方法
下面我針對JSP,說一下應(yīng)對方法:
1.(簡單又有效的方法)PreparedStatement
采用預(yù)編譯語句集,它內(nèi)置了處理SQL注入的能力,只要使用它的setXXX方法傳值即可。
使用好處:
(1).代碼的可讀性和可維護(hù)性.
(2).PreparedStatement盡最大可能提高性能.
(3).最重要的一點(diǎn)是極大地提高了安全性.
原理:
sql注入只對sql語句的準(zhǔn)備(編譯)過程有破壞作用
而PreparedStatement已經(jīng)準(zhǔn)備好了,執(zhí)行階段只是把輸入串作為數(shù)據(jù)處理,
而不再對sql語句進(jìn)行解析,準(zhǔn)備,因此也就避免了sql注入問題.
2.使用正則表達(dá)式過濾傳入的參數(shù)
要引入的包:
import java.util.regex.*;
正則表達(dá)式:
private String CHECKSQL=“^(.+)\sand\s(.+)|(.+)\sor(.+)\s$”;
判斷是否匹配:
Pattern.matches(CHECKSQL,targerStr);
下面是具體的正則表達(dá)式:
檢測SQL meta-characters的正則表達(dá)式 :
/(\%27)|(\’)|(\-\-)|(\%23)|(#)/ix
修正檢測SQL meta-characters的正則表達(dá)式 :/((\%3D)|(=))[^\n]*((\%27)|(\’)|(\-\-)|(\%3B)|(:))/i
典型的SQL 注入攻擊的正則表達(dá)式 :/\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
檢測SQL注入,UNION查詢關(guān)鍵字的正則表達(dá)式 :/((\%27)|(\’))union/ix(\%27)|(\’)
檢測MS SQL Server SQL注入攻擊的正則表達(dá)式:
/exec(\s|\+)+(s|x)p\w+/ix
等等…..
3.字符串過濾
比較通用的一個方法:
(||之間的參數(shù)可以根據(jù)自己程序的需要添加)
public static boolean sql_inj(String str){
String inj_str="'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
String inj_stra[]=split(inj_str,"|");
for (int i=0 ; i < inj_stra.length ; i++ ){
if (str.indexOf(inj_stra[i])>=0){
return true;
}
}
return false;
}
4.jsp中調(diào)用該函數(shù)檢查是否包函非法字符
防止SQL從URL注入:
sql_inj.java代碼:
package sql_inj;
import java.net.*;
import java.io.*;
import java.sql.*;
import java.text.*;
import java.lang.String;
public class sql_inj{
public static boolean sql_inj(String str){
String inj_str="'|and|exec|insert|select|delete|update|
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
//這里的東西還可以自己添加
String[] inj_stra=inj_str.split("\|");
for (int i=0 ; i < inj_stra.length ; i++ ){
if (str.indexOf(inj_stra[i])>=0){
return true;
}
}
return false;
}
}
5.JSP頁面判斷代碼:
使用javascript在客戶端進(jìn)行不安全字符屏蔽
功能介紹:檢查是否含有”‘”,”\”,”/”
參數(shù)說明:要檢查的字符串
返回值:0:是1:不是
函數(shù)名是
function check(a){
return 1;
fibdn=new Array (”‘” ,”\”,”/”);
i=fibdn.length;
j=a.length;
for (ii=0; ii<i; ii++)
{ for (jj=0; jj<j; jj++)
{ temp1=a.charAt(jj);
temp2=fibdn[ii];
if (tem’; p1==temp2)
{ return 0; }
}
}
return 1;
}
總的說來,防范一般的SQL注入只要在代碼規(guī)范上下點(diǎn)功夫就可以了。
凡涉及到執(zhí)行的SQL中有變量時,用JDBC(或者其他數(shù)據(jù)持久層)提供的如:PreparedStatement就可以 ,切記不要用拼接字符串的方法就可以了。
圖片來源:unsplash.com[1]]
Node.js和npm為前端生態(tài)中提供了統(tǒng)一的開發(fā)語言、強(qiáng)大的包管理和模塊生態(tài)系統(tǒng)、靈活的構(gòu)建工具和任務(wù)自動化、以及豐富的前端框架和庫等等。
可以說,正是因?yàn)閚odejs帶來的這些工具和資源使前端開發(fā)更加高效、便捷,并推動了前端技術(shù)的快速發(fā)展。
但是近年來,Node.js 生態(tài)系統(tǒng)中的 npm 軟件包中出現(xiàn)了許多 CVE("Common Vulnerabilities and Exposures" 常見漏洞和公開漏洞),譬如lodash庫的CVE漏洞——CVE-2018-16487[2]、express庫的CVE漏洞——CVE-2018-17346[3]以及jsonwebtoken庫的CVE漏洞——CVE-2018-12424[4]等等,在這其中有一個特別危險且屢禁不止的漏洞就是命令注入(Command Injection)。
作為前端工程師而言,在我們?nèi)粘9ぷ髦校粌H需要快速交付、優(yōu)化性能相關(guān),還要時刻對項(xiàng)目中所采用的nodejs技術(shù)棧及其安全相關(guān)的因素考慮在內(nèi)。
簡而言之,關(guān)于安全這根弦兒得時刻緊繃著!
命令注入[5]是一種攻擊,其目的是通過有漏洞的應(yīng)用程序在主機(jī)操作系統(tǒng)上執(zhí)行任意命令。當(dāng)應(yīng)用程序?qū)⒂脩籼峁┑牟话踩珨?shù)據(jù)(表單、cookie、HTTP 標(biāo)頭等)傳遞給系統(tǒng)shell時,就有可能發(fā)生命令注入攻擊。在這種攻擊中,攻擊者提供的操作系統(tǒng)命令通常是以受攻擊應(yīng)用程序的權(quán)限執(zhí)行的。命令注入攻擊之所以可能,主要是因?yàn)檩斎胄r?yàn)不足。
這種攻擊與代碼注入不同,代碼注入允許攻擊者添加自己的代碼,然后由應(yīng)用程序執(zhí)行。在命令注入攻擊中,攻擊者擴(kuò)展應(yīng)用程序的默認(rèn)功能,執(zhí)行系統(tǒng)命令,而無需注入代碼。
假設(shè)有某程序員a同學(xué)在某個nodejs項(xiàng)目中寫出了類似的代碼:
const { exec }=require('child_process');
function runCommand(userInput) {
const command=`ls ${userInput}`; // 將用戶所輸入的內(nèi)容拼接到命令中
exec(command, (error, stdout, stderr)=> {
if (error) {
console.error(`執(zhí)行命令時出錯:${error}`);
return;
}
console.log(`命令執(zhí)行結(jié)果:${stdout}`);
});
}
const userInput='; rm -rf /'; // 惡意用戶所輸入的內(nèi)容
runCommand(userInput);
我們簡單分析下以上代碼,這段程序可以將用戶所輸入的內(nèi)容直接拼接到命令行字符串中。如果因?yàn)轫?xiàng)目工期緊張,沒經(jīng)過code review匆忙上線,恰好碰到個別用戶所輸入的惡意的命令,例如'; rm -rf /',那么最終執(zhí)行的命令將變?yōu)?/span>ls ; rm -rf /,導(dǎo)致“刪庫跑路”的危險操作。
當(dāng)然這只是為了舉例的簡單例子,實(shí)際項(xiàng)目中,發(fā)生命令注入的原因大多是沒有對用戶所輸入的內(nèi)容進(jìn)行嚴(yán)謹(jǐn)?shù)男r?yàn)。
命令注入是 Node.js 生態(tài)系統(tǒng)中真實(shí)而普遍的威脅。
看似顯而易見的安全風(fēng)險,如以下代碼所示:
var exec=require('child_process').execSync
var platform=require('os').platform()
module.exports=function(){
var commands=Array.isArray(arguments[0]) ? arguments[0] : Array.prototype.slice.apply(arguments)
var command=null
commands.some(function(c){
if (isExec(findCommand(c))){
command=c
return true
}
})
return command
}
function isExec(command){
try{
exec(command, { stdio: 'ignore' })
return true
}
catch (_e){
return false
}
}
function findCommand(command){
if (/^win/.test(platform)){
return "where " + command
} else {
return "command -v " + command
}
}
上述命令注入漏洞是在 find-exec[6] npm 軟件包中發(fā)現(xiàn)的,該軟件包每周的下載量多達(dá) 2000 多次。雖然數(shù)量不多,但足以讓一些用戶面臨風(fēng)險。命令注入漏洞的后果可能是毀滅性的,從數(shù)據(jù)泄露到系統(tǒng)完全崩潰不等。
現(xiàn)在我們再回過頭來看,到底什么是命令注入[7]?簡而言之,命令注入的核心是應(yīng)用程序允許未經(jīng)審核的用戶所輸入的內(nèi)容作為系統(tǒng)命令執(zhí)行。這些命令可操縱底層系統(tǒng),可能導(dǎo)致未經(jīng)授權(quán)的訪問、數(shù)據(jù)泄露,甚至完全破壞系統(tǒng)。
在另外一個案例中,我們可以看下fs-git npm 軟件包(版本 1.0.1)這個看似無害的模塊是如何成為一個嚴(yán)重的安全隱患的:
fs-git 是 Node.js 的一個 npm 包,能夠?yàn)?Git 倉庫提供類似于文件系統(tǒng)的 API,進(jìn)而可以讓開發(fā)人員更直觀、更容易地與 Git 倉庫交互。它擁有相當(dāng)數(shù)量的用戶群體,所以該安全隱患所造成的影響可見一斑。
在1.0.1 版本的 fs-git 模塊中,被發(fā)現(xiàn)了編號為 CVE-2017-1000451[8]漏洞。該模塊依賴 child_process.exec 函數(shù)來執(zhí)行系統(tǒng)命令。然而,用于構(gòu)建執(zhí)行字符串的 buildCommand函數(shù)缺少嚴(yán)謹(jǐn)?shù)男r?yàn)邏輯,使其容易受到命令注入的攻擊。
以下是fs-git 中存在漏洞的代碼片段:
showRef(): Promise<RefInfo[]> {
let command=this._buildCommand("show-ref");
return new Promise((resolve: (value: RefInfo[])=> void, reject: (error: any)=> void)=> {
child_process.exec(command, { maxBuffer: maxBuffer }, (error, stdout, stderr)=> {
if (error) {
reject(error);
} else {
let list=stdout.toString("utf8").split("\n").filter(line=> !!line);
let resultList:RefInfo[]=list.map(str=> {
let columns=str.split(" ", 2);
返回 {
gitDir: this.path、
ref: columns[0]、
name: columns[1]
};
});
resolve(resultList);
最終,代碼還將調(diào)用 _buildCommand 函數(shù),其中包含字符串連接和用戶提供的數(shù)據(jù):
_buildCommand(...args: string[]): string {
return `git --git-dir=${this.path} ${args.join(" ") }`;
當(dāng)攻擊者篡改傳遞給 fs-git 模塊的數(shù)據(jù)以制作利用命令注入漏洞的惡意代碼時,攻擊就展開了。通過提供精心制作的輸入,攻擊者能夠向系統(tǒng)注入任意命令。這樣,攻擊者就可以利用運(yùn)行進(jìn)程的權(quán)限執(zhí)行未經(jīng)授權(quán)的命令,從而可能危及主機(jī)系統(tǒng)。
該漏洞影響深遠(yuǎn)。攻擊者可以執(zhí)行任意命令,其中可能包括外泄敏感數(shù)據(jù)、修改文件甚至破壞系統(tǒng)正常運(yùn)行等操作。對于依賴fs-git的項(xiàng)目和應(yīng)用程序來說,這個漏洞構(gòu)成了重大的安全風(fēng)險。
這個案例充分說明了校驗(yàn)用戶所輸入的內(nèi)容和必要的數(shù)據(jù)清除在防止命令注入漏洞方面的重要性。
所以即使是看似無害的模塊,如果不遵循安全編碼實(shí)踐,也會帶來嚴(yán)重的安全風(fēng)險。開發(fā)者在處理用戶所輸入的內(nèi)容的數(shù)據(jù)時必須十分謹(jǐn)慎。
對于NodeJs項(xiàng)目,我們可以大致從以下幾點(diǎn)入手,從而減少命令注入的風(fēng)險:
譬如,筆者就在曾經(jīng)的Egg.js項(xiàng)目中使用過的Sequelize[9] ORM庫來執(zhí)行安全的數(shù)據(jù)庫操作。
對用戶所輸入的內(nèi)容進(jìn)行校驗(yàn)和過濾,以防止惡意輸入
避免直接拼接用戶所輸入的內(nèi)容到命令字符串、使用安全的文件路徑拼接方法等。確保在代碼中進(jìn)行輸入校驗(yàn)和輸出轉(zhuǎn)義,并注意處理用戶所輸入的內(nèi)容時的邊界情況。
使用經(jīng)過安全審計(jì)和更新頻繁的第三方庫,以減少潛在的安全漏洞。另外還可以使用工具如npm Audit[10]或NSP(Node Security Platform)[11]來檢查項(xiàng)目依賴的安全性。
假設(shè)項(xiàng)目中需要使用到exec[12]和spawn[13]方法時,如果沒有適當(dāng)?shù)臄?shù)據(jù)清理和校驗(yàn),用戶所輸入的內(nèi)容可能被惡意利用,導(dǎo)致命令注入攻擊。
以下是一個簡單Demo說明這些類似的場景:
const { exec, spawn }=require('child_process');
// 示例:使用exec執(zhí)行命令
function executeCommandWithExec(userInput) {
const command=`ls ${userInput}`; // 拼接用戶所輸入的內(nèi)容的命令
exec(command, (error, stdout, stderr)=> {
if (error) {
console.error(`執(zhí)行命令出錯:${error}`);
return;
}
console.log(`命令執(zhí)行結(jié)果:${stdout}`);
});
}
// 示例:使用spawn執(zhí)行命令
function executeCommandWithSpawn(userInput) {
const command='ls';
const args=[userInput]; // 將用戶所輸入的內(nèi)容作為命令行參數(shù)
const child=spawn(command, args);
child.stdout.on('data', (data)=> {
console.log(`命令執(zhí)行結(jié)果:${data}`);
});
child.stderr.on('data', (data)=> {
console.error(`執(zhí)行命令出錯:${data}`);
});
}
// 測試示例
const userInput='; rm -rf /'; // 惡意的用戶所輸入的內(nèi)容,嘗試刪除整個系統(tǒng)
executeCommandWithExec(userInput);
executeCommandWithSpawn(userInput);
在上面的示例中,executeCommandWithExec和executeCommandWithSpawn函數(shù)接受用戶所輸入的內(nèi)容,并將其用于執(zhí)行l(wèi)s命令。
然而,如果惡意用戶所輸入的內(nèi)容像; rm -rf /這樣的內(nèi)容,它會將rm -rf /命令添加到ls命令后面,進(jìn)而導(dǎo)致"刪庫跑路"的悲劇發(fā)生。
為了防止這種攻擊,應(yīng)該對用戶所輸入的內(nèi)容進(jìn)行適當(dāng)?shù)臄?shù)據(jù)清理和校驗(yàn)。
所以對于以上代碼,可以使用安全的執(zhí)行方法execFile和spawn,并將用戶所輸入的內(nèi)容作為命令行參數(shù)而不是直接拼接到命令中:
const { execFile, spawn }=require('child_process');
// 示例:使用execFile執(zhí)行命令
function executeCommandWithExecFile(userInput) {
const command='ls';
const args=[userInput]; // 將用戶所輸入的內(nèi)容作為命令行參數(shù)
execFile(command, args, (error, stdout, stderr)=> {
if (error) {
console.error(`執(zhí)行命令出錯:${error}`);
return;
}
console.log(`命令執(zhí)行結(jié)果:${stdout}`);
});
}
// 示例:使用spawn執(zhí)行命令
function executeCommandWithSpawn(userInput) {
const command='ls';
const args=[userInput]; // 將用戶所輸入的內(nèi)容作為命令行參數(shù)
const child=spawn(command, args);
child.stdout.on('data', (data)=> {
console.log(`命令執(zhí)行結(jié)果:${data}`);
});
child.stderr.on('data', (data)=> {
console.error(`執(zhí)行命令出錯:${data}`);
});
}
// 測試示例
const userInput='; rm -rf /'; // 惡意的用戶所輸入的內(nèi)容,嘗試刪除整個系統(tǒng)
executeCommandWithExecFile(userInput);
executeCommandWithSpawn(userInput);
在上面的代碼實(shí)現(xiàn)中,executeCommandWithExecFile函數(shù)使用了execFile[14]方法來執(zhí)行命令,而executeCommandWithSpawn函數(shù)保持不變,仍然使用spawn方法執(zhí)行命令。
使用execFile方法可以避免將用戶所輸入的內(nèi)容直接拼接到命令中,這樣可以在一定程度上減少命令注入攻擊的風(fēng)險。
記住,無論采用哪種方案,主體思想都應(yīng)該是謹(jǐn)慎處理用戶所輸入的內(nèi)容,并進(jìn)行嚴(yán)謹(jǐn)?shù)男r?yàn),以確保代碼的安全性。
[1]
unsplash.com: https://unsplash.com/
[2]
CVE-2018-16487: https://nvd.nist.gov/vuln/detail/CVE-2018-16487
[3]
CVE-2018-17346: https://nvd.nist.gov/vuln/detail/CVE-2018-17346
[4]
CVE-2018-12424: https://nvd.nist.gov/vuln/detail/CVE-2018-12424
[5]
Command Injection: https://owasp.org/www-community/attacks/Command_Injection
[6]
find-exec: https://github.com/shime/find-exec/commit/74fb108097c229b03d6dba4cce81e36aa364b51c
[7]
Securing Your Node.js Apps by Analyzing Real-World Command Injection Examples: https://www.nodejs-security.com/blog/securing-your-nodejs-apps-by-analyzing-real-world-command-injection-examples
[8]
CVE-2017-1000451: https://github.com/advisories/GHSA-wp3j-gv53-4pg8
[9]
sequelize ORM: https://sequelize.org/
[10]
npm audit: https://docs.npmjs.com/cli/v8/commands/npm-audit/
[11]
NSP: https://github.com/nodesecurity/nsp
[12]
exec: https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
[13]
spawn: https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
[14]
execFile: https://nodejs.org/docs/latest/api/child_process.html#child_processexecfilefile-args-options-callback
作者:Rien.
來源:微信公眾號:奇舞精選
出處:https://mp.weixin.qq.com/s/ElsRQhNTI-Y3qGeVzDzvCA
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。